判断两条线段是否相交 java_判断两个线段是否相交02
寫在前面
在其他博客中看到這方面的知識,很多都是重復,并且說的總是云里霧里的,所以這里我就自己總結一下這種問題如何求解,判斷兩個線段是否相交在前面我們提到了會用到叉積的一點知識,那么這里就來詳細說一下怎么判斷兩個線段是否相交
算法詳解
首先我們看一下快速排斥實驗,快速排斥實驗也就是以兩條線段作為對角線做矩形,判斷兩個矩形是否相交,那么我們這里可以知道:
1)如果兩個矩形不相交,那么線段一定不相交
2)如果兩個矩形相交,那么線段不一定相交,如下圖
所以這里我們首先就要判斷兩條線段形成的矩形是否相交,只有相交我們才要繼續進行判斷后面的線段是否相交.......
跨立實驗:前面我們知道叉積可以用來判斷兩個向量之間的位置關系(順時針還是逆時針關系),那么這里我們就會用到這個性質
我們知道如果兩個線段相交的話,那么一條線段兩邊的兩個點要位于另一條線段的兩邊,只有兩條線段都滿足這個條件,我們就可以判定這兩條直線相交了,那么我們這里所說的一條線段兩個端點位于另一條線段的兩邊,這就是其他博客中提到的跨立吧
那么我們就用叉積來對是否滿足這個條件進行判斷:
取其中一個向量作為中間向量,中間向量中開始端點作為另外兩個向量的起點,判斷三個向量之間的位置關系即可:
第一個圖中: (ca × cd)(cd × cb) >= 0 我們即可判斷滿足跨立條件
第二個圖中: (bc × ba)(ba × bd) >=0 我們即可判斷滿足跨立條件
第三個圖中: (bc × ba)(ba × bd)? < 0不滿足跨立條件
第四個圖中: (ca?× cd)(cd?× cb) >= 0我們即可判斷滿足跨立條件
即計算(ca × cd)(cd × cb) 與(bc × ba)(ba × bd)的結果必須同時大于零,這兩個線段才是相交的;
當然,單獨判斷其中一個,可以獲得一個線段所在的直線是否與另一個線段相交。
那么我們就可以知道上面條件就是判斷跨立是否成立的條件了,那么這樣我們線段是否相交就已經可以解決了.
栗子及模板
zoj1648
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f
using namespace std;
const int MAXN = 2100;
struct Point
{
double x,y;
}line[MAXN][2];
double mult(Point p0,Point p1,Point p2) //叉積計算,p0為公用節點
{
return (p0.x - p1.x) * (p0.y - p2.y) - (p0.y - p1.y) * (p0.x - p2.x);
}
//aa、bb屬于同一個矩形 cc、dd屬于同一個矩形 相交返回true,不相交返回false
bool Judge(Point aa,Point bb,Point cc,Point dd)
{
//判斷兩個形成的矩形不相交
if(max(aa.x , bb.x) < min(cc.x , dd.x)) return false;
if(max(aa.y , bb.y) < min(cc.y , dd.y)) return false;
if(max(cc.x , dd.x) < min(aa.x , bb.x)) return false;
if(max(cc.y , dd.y) < min(aa.y , bb.y)) return false;
//現在已經滿足快速排斥實驗,那么后面就是跨立實驗內容(叉積判斷兩個線段是否相交)
if(mult(aa,cc,bb) * mult(aa,bb,dd) < 0) return false; //正確的話也就是aa,bb要在cc或者dd的兩邊
if(mult(cc,aa,dd) * mult(cc,dd,bb) < 0) return false;
return true;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
bool flag = true;
for(int i = 0;i < n;i ++)
scanf("%lf%lf%lf%lf",&line[i][0].x,&line[i][0].y,&line[i][1].x,&line[i][1].y);
for(int i = 0;i < n;i ++)
for(int j = i+1;j < n;j ++)
{
if(Judge(line[i][0],line[i][1],line[j][0],line[j][1])) // 判斷兩條直線是否相交
{
flag = false;
break;
}
if(!flag) break;
}
if(!flag) printf("burned!\n");
else printf("ok!\n");
}
return 0;
}
參考博客
https://blog.csdn.net/Dacc123/article/details/51219491
https://blog.csdn.net/sizaif/article/details/79192165
---------------------
作者:阿_波_
來源:CSDN
原文:https://blog.csdn.net/li1615882553/article/details/80372202
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
C#代碼
usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;public classMathTool : MonoBehaviour
{publicTransform A, B, C, D;//Start is called before the first frame update
voidStart()
{
}//Update is called once per frame
voidUpdate()
{
Debug.Log(IsIntersection0(A.position, B.position, C.position, D.position));
}//不優化的情況下
boolIsIntersection0(Vector3 a, Vector3 b, Vector3 c, Vector3 d)
{
Vector3 ca= A.position -C.position;
Vector3 cb= B.position -C.position;
Vector3 cd= D.position -C.position;
Vector3 ba= A.position -B.position;
Vector3 bc= C.position -B.position;
Vector3 bd= D.position -B.position;
Vector3 c1=Vector3.Cross(ca, cd);
Vector3 c2=Vector3.Cross(cd, cb);float f1 =Vector3.Dot(c1, c2);
Vector3 c3=Vector3.Cross(bc, ba);
Vector3 c4=Vector3.Cross(ba, bd);float f2 =Vector3.Dot(c3, c4);//必須f1,f2同時滿足大于等于0才能算相交
if (f1 >= 0&&f2>=0) return true;else return false;
}
}
總結
以上是生活随笔為你收集整理的判断两条线段是否相交 java_判断两个线段是否相交02的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在演讲中如何吸引你的听众技巧
- 下一篇: jsmap(桔色棉袄配什么颜色打底衫)