﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-smiling</title><link>http://www.cppblog.com/smiling/</link><description /><language>zh-cn</language><lastBuildDate>Sat, 02 May 2026 10:07:06 GMT</lastBuildDate><pubDate>Sat, 02 May 2026 10:07:06 GMT</pubDate><ttl>60</ttl><item><title>判断两条线段是否相交</title><link>http://www.cppblog.com/smiling/archive/2006/10/12/13605.html</link><dc:creator>extince volcano</dc:creator><author>extince volcano</author><pubDate>Thu, 12 Oct 2006 08:39:00 GMT</pubDate><guid>http://www.cppblog.com/smiling/archive/2006/10/12/13605.html</guid><wfw:comment>http://www.cppblog.com/smiling/comments/13605.html</wfw:comment><comments>http://www.cppblog.com/smiling/archive/2006/10/12/13605.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/smiling/comments/commentRss/13605.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/smiling/services/trackbacks/13605.html</trackback:ping><description><![CDATA[
		<p>方法一、<br />bool TwoLineIsIntersect(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float &amp;InterX, float &amp;InterY)<br />{ //两条线段是否相交X0X1 AND X1X2<br />   float x, y;<br />   float Minx01 = Min(x0, x1);<br />   float Miny01 = Min(y0, y1);<br />   float Minx23 = Min(x2, x3);<br />   float Miny23 = Min(y2, y3);<br />   float Maxx01 = Max(x0, x1);<br />   float Maxy01 = Max(y0, y1);<br />   float Maxx23 = Max(x2, x3);<br />   float Maxy23 = Max(y2, y3);<br />   <br />   if(x1!=x0 &amp;&amp; x2!=x3)<br />   {<br />       float k1 = (y1-y0)/(x1-x0);<br />       float k2 = (y3-y2)/(x3-x2);<br />       float Den = (y1-y0)*(x3-x2) - (y3-y2)*(x1-x0);<br />       if(k1==k2)<br />       { //平行不相交<br />          float d1 = abs(y0*(x1-x0)-x0*(y1-y0)-y2*(x3-x2)+x2*(y3-y2)); //距离公式d = abs(c1-c2) / sqrt(a*a+b*b)<br />          if(d1==0)<br />          {//直线重合<br />             if((x2&gt;Minx01 &amp;&amp; x2&lt;Maxy01 &amp;&amp; y2&gt;Miny01 &amp;&amp; y2&lt;Maxy01) || (x3&gt;Minx01 &amp;&amp; x3&lt;Maxy01 &amp;&amp; y3&gt;Miny01 &amp;&amp; y3&lt;Maxy01)<br />             || (x0&gt;Minx23 &amp;&amp; x0&lt;Maxy23 &amp;&amp; y0&gt;Miny23 &amp;&amp; y0&lt;Maxy23) || (x1&gt;Minx23 &amp;&amp; x1&lt;Maxy23 &amp;&amp; y1&gt;Miny23 &amp;&amp; y1&lt;Maxy23))<br />             {  //实际碰撞问题线段重合认为相交了<br />                return true;<br />             }<br />             else<br />             {<br />                return false;<br />             }<br />          }<br />          else<br />          {<br />             return false;<br />          }   <br />       }<br />       x = ((y2-y0)*(x1-x0)*(x3-x2)+(y1-y0)*(x3-x2)*x0-(y3-y2)*(x1-x0)*x2)/Den;<br />       y = ((y1-y0)*(x-x0))/(x1-x0) + y0;</p>
		<p>       if(Minx01&lt;=x &amp;&amp; x&lt;=Maxx01 &amp;&amp; Miny01&lt;=y &amp;&amp; y&lt;=Maxy01 &amp;&amp; Minx23&lt;=x &amp;&amp; x&lt;=Maxx23 &amp;&amp; Miny23&lt;=y &amp;&amp; y&lt;=Maxy23)<br />       {<br />          InterX = x;<br />          InterY = y;<br />          return true;<br />       }<br />   }<br />   else if(x1==x0 &amp;&amp; x2!=x3)<br />   {<br />       x = x0;<br />       y = ((y3-y2)*(x0-x2))/(x3-x2) + y2;<br />       if(Minx01&lt;=x &amp;&amp; x&lt;=Maxx01 &amp;&amp; Miny01&lt;=y &amp;&amp; y&lt;=Maxy01 &amp;&amp; Minx23&lt;=x &amp;&amp; x&lt;=Maxx23 &amp;&amp; Miny23&lt;=y &amp;&amp; y&lt;=Maxy23)<br />       {<br />          InterX = x;<br />          InterY = y;<br />          return true;<br />       }<br />   }<br />   else if(x1!=x0 &amp;&amp; x2==x3)<br />   {<br />       x = x2;<br />       y = ((y1-y0)*(x2-x0))/(x1-x0) + y0;<br />       if(Minx01&lt;=x &amp;&amp; x&lt;=Maxx01 &amp;&amp; Miny01&lt;=y &amp;&amp; y&lt;=Maxy01 &amp;&amp; Minx23&lt;=x &amp;&amp; x&lt;=Maxx23 &amp;&amp; Miny23&lt;=y &amp;&amp; y&lt;=Maxy23)<br />       {<br />          InterX = x;<br />          InterY = y;<br />          return true;<br />       }       <br />   }<br />   return false;<br />}<br />方法二、<br /></p>
		<p>(1) 快速排斥试验 </p>
		<p>　　　　设以线段 P1P2 为对角线的矩形为 R ， 设以线段 Q1Q2 为对角线的矩形为 T ，如果 R 和 T <br />不相交，显然两线段不会相交。 </p>
		<p>(2) 跨立试验 </p>
		<p>　　　　 如果两线段相交，则两线段必然相互跨立对方。若 P1P2 跨立 Q1Q2 ，则矢量 ( P1 - Q1 ) 和<br /> ( P2 - Q1 ) 位于矢量 ( Q2 - Q1 ) 的两侧，<br />即 ( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 ) &lt; 0 。<br />上式可改写成 ( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) &gt; 0 。<br />当 ( P1 - Q1 ) × ( Q2 - Q1 ) = 0 时，说明 ( P1 - Q1 ) 和 ( Q2 - Q1 ) 共线，<br />但是因为已经通过快速排斥试验，所以 P1 一定在线段 Q1Q2 上；<br />同理， ( Q2 - Q1 ) ×(P2 - Q1 ) = 0 说明 P2 一定在线段 Q1Q2 上。<br />所以判断 P1P2 跨立 Q1Q2 的依据是： <br />( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) &gt;= 0 。<br />同理判断 Q1Q2 跨立 P1P2 的依据是：<br /> ( Q1 - P1 ) × ( P2 - P1 ) * ( P2 - P1 ) × ( Q2 - P1 ) &gt;= 0 。</p>
		<p>
				<br />#define   EP   1e-10   <br />    <br />  struct   YPoint{   <br />  double   x,y;   <br />  };   <br />    <br />  struct   YLineSeg{   <br />  YPoint   a,b;   <br />  };   <br />  //确定两条线段是否相交   <br />  int   Yu_GeometryLibrary::intersect(YLineSeg   u,YLineSeg   v)   <br />  {   <br />  return(   (max(u.a.x,u.b.x)&gt;=min(v.a.x,v.b.x))&amp;&amp;   <br />                  (max(v.a.x,v.b.x)&gt;=min(u.a.x,u.b.x))&amp;&amp;   <br />                  (max(u.a.y,u.b.y)&gt;=min(v.a.y,v.b.y))&amp;&amp;   <br />                  (max(v.a.y,v.b.y)&gt;=min(u.a.y,u.b.y))&amp;&amp;   <br />                  (multiply(v.a,u.b,u.a)*multiply(u.b,v.b,u.a)&gt;=0)&amp;&amp;   <br />                  (multiply(u.a,v.b,v.a)*multiply(v.b,u.b,v.a)&gt;=0));   <br />  }   <br />    <br />  //判断两个点是否相等   <br />  int   Yu_GeometryLibrary::Euqal_Point(YPoint   p1,YPoint   p2)   <br />  {   <br />  return((fabs(p1.x-p2.x)&lt;EP)&amp;&amp;(fabs(p1.y-p2.y)&lt;EP));   <br />  }   <br />    <br />  //一种线段相交判断函数，当且仅当u,v相交并且交点不是u,v的端点时函数为true;   <br />  int   Yu_GeometryLibrary::intersect_A(YLineSeg   u,YLineSeg   v)   <br />  {   <br />  return((intersect(u,v))&amp;&amp;   <br />                (!Euqal_Point(u.a,v.a))&amp;&amp;   <br />                (!Euqal_Point(u.a,v.b))&amp;&amp;   <br />                (!Euqal_Point(u.b,v.a))&amp;&amp;   <br />                (!Euqal_Point(u.b,v.b)));   <br />  }   <br />  <br /></p>
<img src ="http://www.cppblog.com/smiling/aggbug/13605.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/smiling/" target="_blank">extince volcano</a> 2006-10-12 16:39 <a href="http://www.cppblog.com/smiling/archive/2006/10/12/13605.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>