本文講的內容都很初級, 主要是面向和我一樣的初學者, 所以請各位算法帝們輕拍啊
引用
已知線段1(a,b) 和線段2(c,d) ,其中a b c d為端點, 求線段交點p .(平行或共線視作不相交)
算法一: 求兩條線段所在直線的交點, 再判斷交點是否在兩條線段上.
求直線交點時 我們可通過直線的一般方程 ax+by+c=0 求得(方程中的abc為系數,不是前面提到的端點,另外也可用點斜式方程和斜截式方程,此處暫且不論).
然后根據交點的與線段端點的位置關系來判斷交點是否在線段上.
公式如下圖:
<code class="hljs avrasm">function segmentsIntr(a, b, c, d){ /** 1 解線性方程組, 求線段交點. **/ // 如果分母為0 則平行或共線, 不相交 var denominator = (b.y - a.y)*(d.x - c.x) - (a.x - b.x)*(c.y - d.y); if (denominator==0) { return false; } // 線段所在直線的交點坐標 (x , y) var x = ( (b.x - a.x) * (d.x - c.x) * (c.y - a.y) + (b.y - a.y) * (d.x - c.x) * a.x - (d.y - c.y) * (b.x - a.x) * c.x ) / denominator ; var y = -( (b.y - a.y) * (d.y - c.y) * (c.x - a.x) + (b.x - a.x) * (d.y - c.y) * a.y - (d.x - c.x) * (b.y - a.y) * c.y ) / denominator; /** 2 判斷交點是否在兩條線段上 **/ if ( // 交點在線段1上 (x - a.x) * (x - b.x) <= 0 && (y - a.y) * (y - b.y) <= 0 // 且交點也在線段2上 && (x - c.x) * (x - d.x) <= 0 && (y - c.y) * (y - d.y) <= 0 ){ // 返回交點p return { x : x, y : y } } //否則不相交 return false } </code>
算法一思路比較清晰易懂, 但是性能并不高. 因為它在不確定交點是否有效(在線段上)之前, 就先去計算了交點, 耗費了較多的時間.
如果最后發現交點無效, 那么之前的計算就白折騰了. 而且整個計算的過程也很復雜.
那么有沒有一種思路,可以讓我們先判斷是否存在有效交點,然后再去計算它呢?
顯然答案是肯定的. 于是就有了后面的一些算法.
算法二: 判斷每一條線段的兩個端點是否都在另一條線段的兩側, 是則求出兩條線段所在直線的交點, 否則不相交.
第一步判斷兩個點是否在某條線段的兩側, 通??刹捎猛队胺?
求出線段的法線向量, 然后把點投影到法線上, 最后根據投影的位置來判斷點和線段的關系.
見下圖
點a和點b在線段cd法線上的投影如圖所示, 這時候我們還要做一次線段cd在自己法線上的投影(選擇點c或點d中的一個即可).
主要用來做參考.
圖中點a投影和點b投影在點c投影的兩側, 說明線段ab的端點在線段cd的兩側.
同理, 再判斷一次cd是否在線段ab兩側即可.
求法線 , 求投影 什么的聽起來很復雜的樣子, 實際上對于我來說也確實挺復雜,在幾個月前我也不會(念書那會兒的幾何知識都忘光了 :'( )'
不過好在學習和實現起來還不算復雜, 皆有公式可循
求線段ab的法線:
var nx=b.y - a.y, ny=a.x - b.x; var normalLine = { x: nx, y: ny };
注意: 其中 normalLine.x
和normalLine.y
的幾何意義表示法線的方向, 而不是坐標.
求點c在法線上的投影位置:
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時, 我們還需要進一步求交點.
求交點的過程后面再說, 先看一下該算法的完整實現 :
function segmentsIntr(a, b, c, d){ //線段ab的法線N1 var nx1 = (b.y - a.y), ny1 = (a.x - b.x); //線段cd的法線N2 var nx2 = (d.y - c.y), ny2 = (c.x - d.x); //兩條法線做叉乘, 如果結果為0, 說明線段ab和線段cd平行或共線,不相交 var denominator = nx1*ny2 - ny1*nx2; if (denominator==0) { return false; } //在法線N2上的投影 var distC_N2=nx2 * c.x + ny2 * c.y; var distA_N2=nx2 * a.x + ny2 * a.y-distC_N2; var distB_N2=nx2 * b.x + ny2 * b.y-distC_N2; // 點a投影和點b投影在點c投影同側 (對點在線段上的情況,本例當作不相交處理); if ( distA_N2*distB_N2>=0 ) { return false; } // //判斷點c點d 和線段ab的關系, 原理同上 // //在法線N1上的投影 var distA_N1=nx1 * a.x + ny1 * a.y; var distC_N1=nx1 * c.x + ny1 * c.y-distA_N1; var distD_N1=nx1 * d.x + ny1 * d.y-distA_N1; if ( distC_N1*distD_N1>=0 ) { return false; } //計算交點坐標 var fraction= distA_N2 / denominator; var dx= fraction * ny1, dy= -fraction * nx1; return { x: a.x + dx , y: a.y + dy }; }
最后 求交點坐標的部分 所用的方法看起來有點奇怪, 有種摸不著頭腦的感覺.
其實它和算法一 里面的算法是類似的,只是里面的很多計算項已經被提前計算好了.
換句話說, 算法二里求交點坐標的部分 其實也是用的直線的線性方程組來做的.
現在來簡單粗略 很不科學的對比一下算法一和算法二:
1、最好情況下, 兩種算法的復雜度相同
2、最壞情況, 算法一和算法二的計算量差不多
3、但是算法二提供了 更多的”提前結束條件”,所以平均情況下,應該算法二更優.
實際測試下來, 實際情況也確實如此.
前面的兩種算法基本上是比較常見的可以應付絕大多數情況. 但是事實上還有一種更好的算法.
這也是我最近才新學會的(我現學現賣了,大家不要介意啊…)
算法三: 判斷每一條線段的兩個端點是否都在另一條線段的兩側, 是則求出兩條線段所在直線的交點, 否則不相交.
(咦? 怎么感覺和算法二一樣啊? 不要懷疑 確實一樣 … 亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美刺激性大交免费视频| 久久久亚洲国产| 一夜七次郎国产精品亚洲| xxxx欧美18另类的高清| 日韩免费观看网站| 欧美成年人视频网站| 亚洲成人精品在线| 神马国产精品影院av| 夜夜嗨av一区二区三区四区| 国产精品免费久久久| 欧美精品videosex极品1| 色爱av美腿丝袜综合粉嫩av| 欧美日韩性生活视频| 欧美日韩美女视频| 亚洲毛片在线观看| 欧美日韩国产综合新一区| 亚洲裸体xxxx| 国产精品美腿一区在线看| 欧美日韩激情视频8区| 色悠久久久久综合先锋影音下载| 美女国内精品自产拍在线播放| 久久久亚洲国产天美传媒修理工| 亚洲一区二区三区sesese| 日韩电影中文字幕av| 亚洲第一天堂无码专区| 欧美三级免费观看| 性夜试看影院91社区| 美日韩精品免费视频| 国产噜噜噜噜噜久久久久久久久| 欧美日韩国产色视频| 亚洲国产欧美一区| 亚洲iv一区二区三区| 亚洲国产日韩精品在线| 国产精品99免视看9| 黄网站色欧美视频| 日韩av片免费在线观看| 在线视频亚洲欧美| 国语自产精品视频在线看| 欧美成aaa人片免费看| 国产91露脸中文字幕在线| 国产精品一区二区电影| 亚洲欧美日韩中文在线制服| 中文字幕一精品亚洲无线一区| 亚洲精品日韩av| 九九精品视频在线| 精品国产一区二区三区久久狼黑人| 午夜精品久久久久久久99热浪潮| 日本a级片电影一区二区| 久久亚洲欧美日韩精品专区| 久久亚洲国产精品成人av秋霞| 亚洲欧洲国产伦综合| 国模精品视频一区二区三区| 91麻豆桃色免费看| 欧美激情国产日韩精品一区18| 日韩精品www| 久久久久国产精品免费| 久久国产天堂福利天堂| 精品呦交小u女在线| 国产精品久久网| 日韩精品视频在线| 欧美整片在线观看| 亚洲国产精品一区二区三区| 亚洲国产福利在线| 国产日产亚洲精品| 日韩美女av在线| 高清一区二区三区日本久| 国产亚洲美女久久| 欧美成人免费播放| 国产视频欧美视频| 欧美性猛交xxxxx水多| 欧美成年人视频网站欧美| 亚洲热线99精品视频| 日韩av电影在线播放| 亚洲欧美资源在线| 韩国精品美女www爽爽爽视频| 国产999精品久久久| 国产女精品视频网站免费| 97国产一区二区精品久久呦| 欧美激情第6页| 日韩美女在线播放| 久久国产天堂福利天堂| 成人中心免费视频| 97精品视频在线播放| 韩国精品久久久999| 美女999久久久精品视频| 成人中文字幕在线观看| 91社影院在线观看| 国产成人91久久精品| 精品在线欧美视频| 精品久久久999| 国产精品成久久久久三级| 亚洲天堂免费在线| 国产精品一区二区av影院萌芽| 日韩精品在线观看网站| 中文字幕精品—区二区| 成人免费看吃奶视频网站| 亚洲高清在线观看| 亚洲欧美日韩一区二区三区在线| 亚洲一区二区三区四区在线播放| 久久视频在线视频| 国产精品久久久久77777| 2023亚洲男人天堂| 国产69精品久久久久9999| 欧美视频二区36p| 成人亲热视频网站| 国产精品一区二区久久久久| 91免费高清视频| 欧美一级视频在线观看| 欧美激情区在线播放| 98视频在线噜噜噜国产| 国产97色在线| 亚洲精品永久免费精品| 亚洲人精品午夜在线观看| 日韩极品精品视频免费观看| 久久久日本电影| 久久99精品久久久久久噜噜| 色综合导航网站| 最新国产成人av网站网址麻豆| 性欧美暴力猛交69hd| 久久精品国产久精国产一老狼| 久久成人这里只有精品| 亚洲的天堂在线中文字幕| 亚洲品质视频自拍网| 成人性生交大片免费观看嘿嘿视频| 国产日韩在线观看av| 久久亚洲国产精品成人av秋霞| 成人免费网站在线观看| 成人97在线观看视频| 久久国内精品一国内精品| 亚洲成人动漫在线播放| 欧美国产日韩精品| 久久久精品电影| 欧美成人精品影院| 久久久久久久久久久成人| 青草青草久热精品视频在线网站| 性欧美视频videos6一9| 国产精品成人在线| 91日韩在线播放| 97精品在线视频| 亚洲美女av电影| 久久精品亚洲热| 精品在线观看国产| 精品动漫一区二区| 欧美丝袜第一区| 国产精品色悠悠| 国产不卡av在线免费观看| 久久久久这里只有精品| 日本91av在线播放| 欧美最猛性xxxxx亚洲精品| 国产在线精品成人一区二区三区| 欧美激情奇米色| 亚洲片国产一区一级在线观看| 成人网在线免费看| 伊人精品在线观看| 日韩毛片在线看| 欧美视频在线观看免费网址| 国产成人福利视频| 亚洲美女在线看| 亚洲精品999| 欧美日韩电影在线观看| 日韩av在线网站| 日韩电影大全免费观看2023年上| 亚洲午夜女主播在线直播| 日韩电影在线观看永久视频免费网站|