導航:首頁 > 編程語言 > 線段求交演算法程序

線段求交演算法程序

發布時間:2023-05-27 17:02:07

① 空間線段對求交演算法

下面先介紹一種空間線段對求交演算法:

圖埋碰罩6.5 界線相交特性

三維地質建模方法及程序實現

空間兩條線段的求交運算是三維地質建模中使用頻率最高、演算法最簡單,同時也是最容易出現計算誤差,並導致後續建模失敗的數值運算之一。導致計算失敗的主要原因是計算精度與浮點數問題。例如,有3條線段,兩兩之間的交點距離非常近但不重合,如果保持3個交點彎鬧不變就會降低後續建模中曲面網格的質量;如果降低精度要求,將3個交點合並成一點,就會影響與其他線段的相交關系。另外,浮點數問題在線段平吵亮行判斷、三點共線判斷、四點共面判斷都會遇到。在處理這類問題時,可以採用一個原則,即先精後粗,也就是說在線段對求交時盡量精確,等所有線段對求交結束後可以對距離很近的點進行合並處理。

② 談談"求線段交點"的幾種演算法

求線段交點 是一種非常基礎的幾何計算 在很多游戲中都會被使用到

下面我就現學現賣的把最近才學會的一些 求線段交點 的演算法說一說 希望對大家有所幫助

本文講的內容都很初級 主要是面向和我一樣的初學者 所以請各位演算法帝們輕拍啊 嘎嘎

引用已知線段 (a b) 和線段 (c d) 其中a b c d為端點 求線段交點p (平行或共線視作不相交)

演算法一 求兩條線段所在直線的交點 再判斷交點是否在兩條線段上

求直線交點時 我們可通過直線的一般方程 ax+by+c= 求得(方程中的abc為系數 不是前面提到的端點 另外也可用點斜式方程和斜截式方程 此處暫且不論)

然後根據交點的與線段端點的位置關系來判斷交點是否在線段上 公式如下圖

【責編:at 】

演算法二 判斷每一條線段的兩個端點是否都在另一條線段的兩側 是則求出兩條線段所在直線的交點 否則不相交

第一步判斷兩個點是否在某條線段的兩側 通常可採用投影法

求出線段的法線向量 然後把點投影到法線上 最後根據投影的位置來判斷點和線段的關系 見下圖

點a和點b在線段cd法線上的投影如圖所示 這時候我們還要做一次線段cd在自己法線上的投影(選擇點c或點d中的一個即可)

主要用來做參考

圖中點a投影和點b投影在點c投影的兩側 說明線段ab的端點在線段cd的兩側

同理 再判斷一次cd是否在線段ab兩側即可

求法線 求投影 什麼的聽起來很復雜的樣子 實際上對於我來說也確實挺復雜 在幾個月前我也不會(念書那會兒的幾何知識都忘光了 ( ) 不過好在學習和實現起來還不算復雜 皆有公式可循

求線段ab的法線

JavaScript Code復制內容到剪貼板var nx=b y a y ny=a x b x var normalLine = { x nx y ny } 注意 其中 normalLine x和normalLine y的幾何意義表示法線的方向 而不是坐標

求點c在法線上的投影位置

JavaScript Code復制內容到剪貼板var dist= normalLine x*c x + normalLine y*c y

注意 這里的 投影位置 是一個標量 表示的是到法線原點的距離 而不是投影點的坐標

通常知道這個渣耐鄭距離就足夠了

當我們把圖中 點a投影(distA) 點b投影(distB) 點c投影(distC) 都求出來之後 就可以很容易的根據各自的大小判斷出相對位置

distA==distB==distC 時 兩條線段共線distA==distB!=distC 時 兩條線段平行distA 和 distB 在distC 同側時 兩條線段不相交

distA 和 distB 在distC 異側時 兩條線段是否相交需要再判斷點c點d與線段ab的關系

前面的那些步驟 只是實現了 判斷線段是否相交 當結果為true時 我們還需要進一步求交點

求交點的過程後面再說 先看一下該演算法的完整實現

JavaScript Code復制內容到剪貼板function segmentsIntr(a b c d){

//線段ab的法線N var nx = (b y a y) ny = (a x b x)

//線段cd的法線N var nx = (d y c y) ny = (c x d x)

畝螞//兩條法線做叉乘 如果結果為 說明線段ab和線段cd平行或共線 不相如頌交var denominator = nx *ny ny *nx if (denominator== ) { return false }

//在法線N 上的投影var distC_N =nx * c x + ny * c y var distA_N =nx * a x + ny * a y distC_N var distB_N =nx * b x + ny * b y distC_N

// 點a投影和點b投影在點c投影同側 (對點在線段上的情況 本例當作不相交處理) if ( distA_N *distB_N >= ) { return false }

// //判斷點c點d 和線段ab的關系 原理同上// //在法線N 上的投影var distA_N =nx * a x + ny * a y var distC_N =nx * c x + ny * c y distA_N var distD_N =nx * d x + ny * d y distA_N if ( distC_N *distD_N >= ) { return false }

//計算交點坐標var fraction= distA_N / denominator var dx= fraction * ny dy= fraction * nx return { x a x + dx y a y + dy } }

最後 求交點坐標的部分 所用的方法看起來有點奇怪 有種摸不著頭腦的感覺

其實它和演算法一 裡面的演算法是類似的 只是裡面的很多計算項已經被提前計算好了

換句話說 演算法二里求交點坐標的部分 其實也是用的直線的線性方程組來做的

現在來簡單粗略 很不科學的對比一下演算法一和演算法二 最好情況下 兩種演算法的復雜度相同 最壞情況 演算法一和演算法二的計算量差不多 但是演算法二提供了 更多的 提前結束條件 所以平均情況下 應該演算法二更優

實際測試下來 實際情況也確實如此

【責編:at 】

演算法三 判斷每一條線段的兩個端點是否都在另一條線段的兩側 是則求出兩條線段所在直線的交點 否則不相交

(咦? 怎麼感覺和演算法二一樣啊? 不要懷疑 確實一樣 …… 囧)

所謂演算法三 其實只是對演算法二的一個改良 改良的地方主要就是 不通過法線投影來判斷點和線段的位置關系 而是通過點和線段構成的三角形面積來判斷

先來復習下三角形面積公式 已知三角形三點a(x y) b(x y) c(x y) 三角形面積為

JavaScript Code復制內容到剪貼板var triArea=( (a x c x) * (b y c y) (a y c y) * (b x c x) ) /

因為 兩向量叉乘==兩向量構成的平行四邊形(以兩向量為鄰邊)的面積 所以上面的公式也不難理解

而且由於向量是有方向的 所以面積也是有方向的 通常我們以逆時針為正 順時針為負數

改良演算法關鍵點就是 如果 線段ab和點c構成的三角形面積 與 線段ab和點d構成的三角形面積 構成的三角形面積的正負符號相異 那麼點c和點d位於線段ab兩側 如下圖所示

【責編:at 】 lishixin/Article/program/Java/Javascript/201311/25424

③ 求助,兩條三維直線求交點的演算法,最好有C++

這里假設是點向式,給定直線上一點(x1,y1,z1)和向量(m1,n1,p1)確定一條直線
對於兩條直線,就是求方程組:
[m1m2|x1-x2]
[n1n2|y1-y2]
[p1p2|z1-z2]
的解。
如果有解(t1,t2),那麼(x1+m1*t1,y1+n1*t1,z1+p1*t1)就是一個交點
求解線性方程組有很多方法,這里因為只有三個方程,可以直接明行蠢用克萊默法則解
#include<iostream>
std::pair<double,double>dd(doublea,doubleb,
doublec,doubled,doublem,doublen);
voidmain(){
doublem1,n1,p1,x1,y1,z1;
doublem2,n2,p2,x2,y2,z2;
std::cin激陪>>m1>>n1>>p1>>x1>>y1>>z1;
std::cin>>m2>>n2>>p2>>x2>>y2>>z2;
std::pair<double,double>answer;
constdoubleepsilon=1E-2;
//求解直線(x-x1)/m1=(y-y1)/n1=(z-z1)/p1和(x-x2)/m2=(y-y2)/n2=(z-z2)/p2的交點
if(fabs(m2*n2-n1*m2)<epsilon&&fabs(m1*p2-p1*m2)<epsilon){
if(fabs(m1*(y1-y2)-n1*(x1-x2))<epsilon&&fabs(m1*(z1-z2)-p1*(x1-x2))<epsilon)
std::cout<<"直線平行完全重合"<<std::endl;
else
std::cout<<"直線平行不相交"<<std::endl;
}
elseif(fabs(m1*n2-n1*m2)>epsilon){
answer=dd(m1,n1,m2,n2,x1-x2,y1-y2);
if(p1*answer.first+p2*answer.second-(z1-z2)<epsilon){
std::cout<<answer.first<<" "<<answer.second<<std::endl;
std::cout<<"找到!x="<<x1+m1*answer.first<<"y="<<y1+n1*answer.second<<std::endl;
}
elsestd::cout<<"無解"<<std::endl;
}
elseif(fabs(m1*p2-p1*m2)>epsilon){
answer=dd(m1,p1,m2,p2,x1-x2,z1-z2);
if(fabs(n1*answer.first+n2*answer.second-(z1-z2))<epsilon){
std::cout<<"找到!x="<<x1+m1*answer.first<<"y="<<y1+n1*answer.second<<std::endl;
}
elsestd::cout<<"無解"<<std::endl;
}
elsestd::cout<<"出錯"<<std::endl;
}
std::pair<double,double>dd(doublea,doubleb,
doublec,doubled,doublem,doublen){
returnstd::pair<帶陵double,double>((m*d-c*n)/(a*d-c*b),(a*n-b*m)/(a*d-c*b));
}

④ 界線的求交演算法

當需要進行求交運算的界腔拆線較少,且每條界線上的線段也不多時,逐一對分別來自兩條界線上的線段進行求交運算是可行的。但是,當界線很多時,這種求交方法將花費大量計算時間,效率十分低下。為此,本書將介紹一種演算法:先利用網格定位,盡可能排除不可能相交的線段對,然後逐一對可能相交的線段對進行求交運算。該方法的具體步驟如下:

(1)確定界線矩形包圍盒。將所有界線上的所有結點按坐標進行排耐山序,找到最小與最大的三維坐標(xmin,ymin,zmin)與(xmax,ymax,zmax),作為矩形包圍盒的角點坐標。

(2)矩形包圍盒的網格劃分。以一定的間距,將包圍盒劃分成規則六面體格網,3個方向的間距可以不同,也可以相同。

(3)界線的網格定位,即確定每條界線上的每條線段與哪些網格單元相交,並將與某個網格單元相交的線段記錄在該單元的相交線段集上。線段與網格單元的相交判斷可以根據線段的端點坐標直接定位。

(4)組建可能相交的線段對。在每個格網單元中,將來自不同界線的線段進行組對,並刪除重復昌圓中出現的線段對。

(5)線段對求交運算。

(6)結點的統一編排。將原有界線上的結點、界線的交點按坐標進行統一排序,按一定的閾值合並距離很近的結點,然後重新設置界線與新結點集中結點的關系。

(7)簡單弧的劃分。將每條界線劃分成若干簡單弧,保證每條簡單弧是唯一的,並且確保簡單弧上除端點以外的內部點不被其他簡單弧共享。簡單弧劃分方法見第7章線框架生成方法。

⑤ C語言編寫函數實現求兩個線段的交點(定義一個函數而不是直接寫求解的程序)

欲求二函數交點,必手悔須有二函數的代數表達局弊式,畢臘正或者必須有兩條線段的端點坐標,否則,不可能得到線段的交點。

⑥ 求任意兩線段交點

1.先建個坐標系,再在坐標上找兩條線段經過的共同點就可以了。
2.至於如何找共同點,先要確定兩條線段所在直線的函數,然後求交點,求不出交點簡高就沒有線段交點。
3.求出了線段交點還要看改點的自變數此攔和因變數在不在定義域和攔扒尺值域范圍內。若在,就有交點;若有一條件不滿足,就沒有交點。

⑦ 用c語言 求點到線段垂線的交點,怎麼求

設線段兩點是 (x1,y1)(x2,y2),另外一個點是(x3,y3),那塵尺哪么他的方向向量就是 (a,b)=(x2-x1,y2-y1),那麼他的垂線段的方向向量就是 (-b,a); 那麼垂線的方程困消l就是就是 (x-x3)/(-b)=(y-y3)/a,l上的點就是x=t*(-b)+x3,y=a*t+y3,把(x,y)代入線段方程就可以求出t;
#include<stdio.h>派碼

struct point
{
double x,y;
point(double _x,double _y):
x(_x),y(_y){}
};
struct Line
{
double x,y;
point a;
Line(double _x,double _y,point _a):
x(_x),y(_y),a(_a){}

};

int main()
{
double x,y;
printf("輸入線段兩點\n");
scanf("%lf%lf",&x,&y);point a=point(x,y);
scanf("%lf%lf",&x,&y);point b=point(x,y);
printf("輸入線段外一點\n");
scanf("%lf%lf",&x,&y);point c=point(x,y);

Line l=Line(a.x-b.x,a.y-b.y,a);
Line l1=Line(b.y-a.y,a.x-b.x,c);

//ansx=(b.y-a.y)*t+c.x;ansy=(a.x-b.x)*t+c.y

//(ansx-a.x)/(a.x-b.x)=(ansy-a.y)/(a.y-b.y)

double t=((c.y-a.y)*(a.x-b.x)-(c.x-a.x)*(a.y-b.y))/((a.y-b.y)*(b.y-a.y)-(a.x-b.x)*(a.x-b.x));
if(t>1||t<0) puts("不存在");
else
{
double ansx=(b.y-a.y)*t+c.x;
double ansy=(a.x-b.x)*t+c.y;

printf("%lf %lf\n",ansx,ansy);
}
}

閱讀全文

與線段求交演算法程序相關的資料

熱點內容
相約密聊下載配置文件 瀏覽:797
男主是小偷的電影 瀏覽:48
上古卷軸5一鍵獲取裝備代碼 瀏覽:829
在蘋果手機咋打開USB 瀏覽:350
國內自拍電影 瀏覽:813
iphone怎麼在電腦上下載電影 瀏覽:409
word2003批註名字 瀏覽:423
c將json數組轉化成對象 瀏覽:189
不用下載免費看的網站 瀏覽:954
成龍電影網 瀏覽:158
中文影院在線 瀏覽:108
可編程式控制制器控制什麼 瀏覽:320
iphone取消阻止來電後 瀏覽:590
asp接收form表單上傳文件 瀏覽:437
用手機共享電腦網路 瀏覽:696
電腦文件路徑前綴 瀏覽:811
游戲編程都需要學哪些軟體下載 瀏覽:357
組成合同文件內容 瀏覽:895
黑寡婦燈光配置文件 瀏覽:833
前戲電影 瀏覽:668

友情鏈接