如何判断一个点是否在多边形内?
判斷點是否在多邊形內部
如何判斷一個點是否在多邊形內部?
(1)面積和判別法:判斷目標點與多邊形的每條邊組成的三角形面積和是否等于該多邊形,相等則在多邊形內部。
(2)夾角和判別法:判斷目標點與所有邊的夾角和是否為360度,為360度則在多邊形內部。
(3)引射線法:從目標點出發引一條射線,看這條射線和多邊形所有邊的交點數目。如果有奇數個交點,則說明在內部,如果有偶數個交點,則說明在外部。
具體做法:將測試點的Y坐標與多邊形的每一個點進行比較,會得到一個測試點所在的行與多邊形邊的交點的列表。在下圖的這個例子中有8條邊與測試點所在的行相交,而有6條邊沒有相交。如果測試點的兩邊點的個數都是奇數個則該測試點在多邊形內,否則在多邊形外。在這個例子中測試點的左邊有5個交點,右邊有三個交點,它們都是奇數,所以點在多邊形內。
算法圖解:
關于這個算法的具體的更多圖形例子:http://alienryderflex.com/polygon/
參考代碼:
int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy){
int i, j, c = 0;
for (i = 0, j = nvert-1; i < nvert; j = i++)
{
if ( ((verty[i]>testy) != (verty[j]>testy)) &&
(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
c = !c;
}
return c;
}
來自一個polygon的內部實現:
public bool IsInside(PointLatLng p){
int count = Points.Count; </span><span style="color:rgb(0,0,255);line-height:1.5 !important;">if</span>(count < <span style="color:rgb(128,0,128);line-height:1.5 !important;">3</span><span style="line-height:1.5 !important;">){</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">return</span> <span style="color:rgb(0,0,255);line-height:1.5 !important;">false</span><span style="line-height:1.5 !important;">;}</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">bool</span> result = <span style="color:rgb(0,0,255);line-height:1.5 !important;">false</span><span style="line-height:1.5 !important;">;</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">for</span>(<span style="color:rgb(0,0,255);line-height:1.5 !important;">int</span> i = <span style="color:rgb(128,0,128);line-height:1.5 !important;">0</span>, j = count - <span style="color:rgb(128,0,128);line-height:1.5 !important;">1</span>; i < count; i++<span style="line-height:1.5 !important;">){</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">var</span> p1 =<span style="line-height:1.5 !important;"> Points[i];</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">var</span> p2 =<span style="line-height:1.5 !important;"> Points[j];</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">if</span>(p1.Lat < p.Lat && p2.Lat >= p.Lat || p2.Lat < p.Lat && p1.Lat >=<span style="line-height:1.5 !important;"> p.Lat){</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">if</span>(p1.Lng + (p.Lat - p1.Lat) / (p2.Lat - p1.Lat) * (p2.Lng - p1.Lng) <<span style="line-height:1.5 !important;"> p.Lng){result </span>= !<span style="line-height:1.5 !important;">result;}}j </span>=<span style="line-height:1.5 !important;"> i;}</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">return</span><span style="line-height:1.5 !important;"> result;}</span></pre><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy" style="line-height:1.5 !important;"><a title="復制代碼" style="color:#008000;border:none !important;" target="_blank"><img src="http://common.cnblogs.com/images/copycode.gif" alt="復制代碼" style="border:none !important;"></a></span></div></div><p>特殊情況:要檢測的點在多變形的一條邊上,射線法判斷的結果是不確定的,需要特殊處理(<span>If the test point is on the border of the polygon, this algorithm will deliver unpredictable results</span>)。</p><p>計算一個多邊形的面積(area of a polygon):</p><div class="cnblogs_code" style="background-color:rgb(245,245,245);border:1px solid rgb(204,204,204);overflow:auto;font-family:'Courier New' !important;font-size:12px !important;"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy" style="line-height:1.5 !important;"><a title="復制代碼" style="color:#008000;border:none !important;" target="_blank"><img src="http://common.cnblogs.com/images/copycode.gif" alt="復制代碼" style="border:none !important;"></a></span></div><pre style="font-family:'Courier New' !important;"> <span style="color:rgb(0,0,255);line-height:1.5 !important;">private</span> <span style="color:rgb(0,0,255);line-height:1.5 !important;">static</span> <span style="color:rgb(0,0,255);line-height:1.5 !important;">double</span> SignedPolygonArea(List<PointLatLng><span style="line-height:1.5 !important;"> points){</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">//</span><span style="color:rgb(0,128,0);line-height:1.5 !important;"> Add the first point to the end.</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">int</span> pointsCount =<span style="line-height:1.5 !important;"> points.Count;PointLatLng[] pts </span>= <span style="color:rgb(0,0,255);line-height:1.5 !important;">new</span> PointLatLng[pointsCount + <span style="color:rgb(128,0,128);line-height:1.5 !important;">1</span><span style="line-height:1.5 !important;">];points.CopyTo(pts, </span><span style="color:rgb(128,0,128);line-height:1.5 !important;">0</span><span style="line-height:1.5 !important;">);pts[pointsCount] </span>= points[<span style="color:rgb(128,0,128);line-height:1.5 !important;">0</span><span style="line-height:1.5 !important;">];</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">for</span> (<span style="color:rgb(0,0,255);line-height:1.5 !important;">int</span> i = <span style="color:rgb(128,0,128);line-height:1.5 !important;">0</span>; i < pointsCount + <span style="color:rgb(128,0,128);line-height:1.5 !important;">1</span>; ++<span style="line-height:1.5 !important;">i){pts[i].Lat </span>= pts[i].Lat * (System.Math.PI * <span style="color:rgb(128,0,128);line-height:1.5 !important;">6378137</span> / <span style="color:rgb(128,0,128);line-height:1.5 !important;">180</span><span style="line-height:1.5 !important;">);pts[i].Lng </span>= pts[i].Lng * (System.Math.PI * <span style="color:rgb(128,0,128);line-height:1.5 !important;">6378137</span> / <span style="color:rgb(128,0,128);line-height:1.5 !important;">180</span><span style="line-height:1.5 !important;">);}</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">//</span><span style="color:rgb(0,128,0);line-height:1.5 !important;"> Get the areas.</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">double</span> area = <span style="color:rgb(128,0,128);line-height:1.5 !important;">0</span><span style="line-height:1.5 !important;">;</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">for</span> (<span style="color:rgb(0,0,255);line-height:1.5 !important;">int</span> i = <span style="color:rgb(128,0,128);line-height:1.5 !important;">0</span>; i < pointsCount; i++<span style="line-height:1.5 !important;">){area </span>+= (pts[i + <span style="color:rgb(128,0,128);line-height:1.5 !important;">1</span>].Lat - pts[i].Lat) * (pts[i + <span style="color:rgb(128,0,128);line-height:1.5 !important;">1</span>].Lng + pts[i].Lng) / <span style="color:rgb(128,0,128);line-height:1.5 !important;">2</span><span style="line-height:1.5 !important;">;}</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">//</span><span style="color:rgb(0,128,0);line-height:1.5 !important;"> Return the result.</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">return</span><span style="line-height:1.5 !important;"> area;}</span><span style="color:rgb(128,128,128);line-height:1.5 !important;">///</span> <span style="color:rgb(128,128,128);line-height:1.5 !important;"><summary></span><span style="color:rgb(128,128,128);line-height:1.5 !important;">///</span><span style="color:rgb(0,128,0);line-height:1.5 !important;"> Get the area of a polygon</span><span style="color:rgb(128,128,128);line-height:1.5 !important;">///</span> <span style="color:rgb(128,128,128);line-height:1.5 !important;"></summary></span><span style="color:rgb(128,128,128);line-height:1.5 !important;">///</span> <span style="color:rgb(128,128,128);line-height:1.5 !important;"><param name="points"></param></span><span style="color:rgb(128,128,128);line-height:1.5 !important;">///</span> <span style="color:rgb(128,128,128);line-height:1.5 !important;"><returns></returns></span><span style="color:rgb(0,0,255);line-height:1.5 !important;">public</span> <span style="color:rgb(0,0,255);line-height:1.5 !important;">static</span> <span style="color:rgb(0,0,255);line-height:1.5 !important;">double</span> GetPolygonArea(List<PointLatLng><span style="line-height:1.5 !important;"> points){</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">//</span><span style="color:rgb(0,128,0);line-height:1.5 !important;"> Return the absolute value of the signed area.</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">//</span><span style="color:rgb(0,128,0);line-height:1.5 !important;"> The signed area is negative if the polygon is oriented clockwise.</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">return</span><span style="line-height:1.5 !important;"> Math.Abs(SignedPolygonArea(points));}</span></pre><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy" style="line-height:1.5 !important;"><a title="復制代碼" style="color:#008000;border:none !important;" target="_blank"><img src="http://common.cnblogs.com/images/copycode.gif" alt="復制代碼" style="border:none !important;"></a></span></div></div><p> </p><p> </p><p> </p><p>參考資料:</p><p>http://alienryderflex.com/polygon/</p><p>http://en.wikipedia.org/wiki/Point_in_polygon</p><p>http://www.codeproject.com/Tips/84226/Is-a-Point-inside-a-Polygon</p><p> </p></div><div id="MySignature" style="background-color:rgb(248,248,238);border:1px solid rgb(232,231,208);color:#808080;"><div style="line-height:25px;">作者:<a href="http://www.cnblogs.com/luxiaoxun/" rel="nofollow" style="color:#008000;text-decoration:none;" target="_blank">阿凡盧</a></div><div style="line-height:25px;">出處:<a href="http://www.cnblogs.com/luxiaoxun/" rel="nofollow" style="color:#008000;text-decoration:none;" target="_blank">http://www.cnblogs.com/luxiaoxun/</a></div><div style="line-height:25px;">本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。</div></div></div><br><pre class="best-text mb-10" style="background-color:rgb(255,255,255);font-family:'Microsoft YaHei', arial, 'courier new', courier, '宋體', monospace;font-size:16px;line-height:29px;min-height:55px;" name="code"><span style="color:#333333;">
假設多邊形的坐標存放在一個數組里,首先我們需要取得該數組在橫坐標和縱坐標的最大值和最小值,根據這四個點算出一個四邊型,首先判斷目標坐標點是否在這個四邊型之內,如果在這個四邊型之外,那可以跳過后面較為復雜的計算,直接返回false。
if (p.x < minX || p.x > maxX || p.y < minY || p.y > maxY) {
// 這個測試都過不了。。。直接返回false;
}
接下來是核心算法部分:
int pnpoly (int nvert, float *vertx, float *verty, float testx, float testy) {
int i, j, c = 0;
for (i = 0, j = nvert-1; i < nvert; j = i++) {
if ( ( (verty[i]>testy) != (verty[j]>testy) ) &&
(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
c = !c;
}
return c;
}
額,代碼就這么簡單,但到底啥意思呢:
首先,參數nvert 代表多邊形有幾個點。浮點數testx, testy代表待測試點的橫坐標和縱坐標,*vertx,*verty分別指向儲存多邊形橫縱坐標數組的首地址。
我們注意到,每次計算都涉及到相鄰的兩個點和待測試點,然后考慮兩個問題:
被測試點的縱坐標testy是否在本次循環所測試的兩個相鄰點縱坐標范圍之內?即
verty[i] <testy < verty[j]
或者
verty[j] <testy < verty[i]
待測點test是否在i,j兩點之間的連線之下?看不懂后半短if statement的朋友請自行在紙上寫下i,j兩點間的斜率公式,要用到一點初中解析幾何和不等式的知識范疇,對廣大碼農來說小菜一碟。
然后每次這兩個條件同時滿足的時候我們把返回的布爾量取反。
可這到底是啥意思啊?
這個表達式的意思是說,隨便畫個多邊形,隨便定一個點,然后通過這個點水平劃一條射線,先數數看這條
以上轉載百度知道;以下轉載阿凡盧,轉載地址:http://www.cnblogs.com/luxiaoxun/p/3722358.html
判斷點是否在多邊形內部
如何判斷一個點是否在多邊形內部?
(1)面積和判別法:判斷目標點與多邊形的每條邊組成的三角形面積和是否等于該多邊形,相等則在多邊形內部。
(2)夾角和判別法:判斷目標點與所有邊的夾角和是否為360度,為360度則在多邊形內部。
(3)引射線法:從目標點出發引一條射線,看這條射線和多邊形所有邊的交點數目。如果有奇數個交點,則說明在內部,如果有偶數個交點,則說明在外部。
具體做法:將測試點的Y坐標與多邊形的每一個點進行比較,會得到一個測試點所在的行與多邊形邊的交點的列表。在下圖的這個例子中有8條邊與測試點所在的行相交,而有6條邊沒有相交。如果測試點的兩邊點的個數都是奇數個則該測試點在多邊形內,否則在多邊形外。在這個例子中測試點的左邊有5個交點,右邊有三個交點,它們都是奇數,所以點在多邊形內。
算法圖解:
關于這個算法的具體的更多圖形例子:http://alienryderflex.com/polygon/
參考代碼:
int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy){
int i, j, c = 0;
for (i = 0, j = nvert-1; i < nvert; j = i++)
{
if ( ((verty[i]>testy) != (verty[j]>testy)) &&
(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
c = !c;
}
return c;
}
來自一個polygon的內部實現:
public bool IsInside(PointLatLng p){
int count = Points.Count; </span><span style="color:rgb(0,0,255);line-height:1.5 !important;">if</span>(count < <span style="color:rgb(128,0,128);line-height:1.5 !important;">3</span><span style="line-height:1.5 !important;">){</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">return</span> <span style="color:rgb(0,0,255);line-height:1.5 !important;">false</span><span style="line-height:1.5 !important;">;}</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">bool</span> result = <span style="color:rgb(0,0,255);line-height:1.5 !important;">false</span><span style="line-height:1.5 !important;">;</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">for</span>(<span style="color:rgb(0,0,255);line-height:1.5 !important;">int</span> i = <span style="color:rgb(128,0,128);line-height:1.5 !important;">0</span>, j = count - <span style="color:rgb(128,0,128);line-height:1.5 !important;">1</span>; i < count; i++<span style="line-height:1.5 !important;">){</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">var</span> p1 =<span style="line-height:1.5 !important;"> Points[i];</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">var</span> p2 =<span style="line-height:1.5 !important;"> Points[j];</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">if</span>(p1.Lat < p.Lat && p2.Lat >= p.Lat || p2.Lat < p.Lat && p1.Lat >=<span style="line-height:1.5 !important;"> p.Lat){</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">if</span>(p1.Lng + (p.Lat - p1.Lat) / (p2.Lat - p1.Lat) * (p2.Lng - p1.Lng) <<span style="line-height:1.5 !important;"> p.Lng){result </span>= !<span style="line-height:1.5 !important;">result;}}j </span>=<span style="line-height:1.5 !important;"> i;}</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">return</span><span style="line-height:1.5 !important;"> result;
}
特殊情況:要檢測的點在多變形的一條邊上,射線法判斷的結果是不確定的,需要特殊處理(If the test point is on the border of the polygon, this algorithm will deliver unpredictable results)。
計算一個多邊形的面積(area of a polygon):
private static double SignedPolygonArea(List<PointLatLng> points){
// Add the first point to the end.
int pointsCount = points.Count;
PointLatLng[] pts = new PointLatLng[pointsCount + 1];
points.CopyTo(pts, 0);
pts[pointsCount] = points[0]; </span><span style="color:rgb(0,0,255);line-height:1.5 !important;">for</span> (<span style="color:rgb(0,0,255);line-height:1.5 !important;">int</span> i = <span style="color:rgb(128,0,128);line-height:1.5 !important;">0</span>; i < pointsCount + <span style="color:rgb(128,0,128);line-height:1.5 !important;">1</span>; ++<span style="line-height:1.5 !important;">i){pts[i].Lat </span>= pts[i].Lat * (System.Math.PI * <span style="color:rgb(128,0,128);line-height:1.5 !important;">6378137</span> / <span style="color:rgb(128,0,128);line-height:1.5 !important;">180</span><span style="line-height:1.5 !important;">);pts[i].Lng </span>= pts[i].Lng * (System.Math.PI * <span style="color:rgb(128,0,128);line-height:1.5 !important;">6378137</span> / <span style="color:rgb(128,0,128);line-height:1.5 !important;">180</span><span style="line-height:1.5 !important;">);}</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">//</span><span style="color:rgb(0,128,0);line-height:1.5 !important;"> Get the areas.</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">double</span> area = <span style="color:rgb(128,0,128);line-height:1.5 !important;">0</span><span style="line-height:1.5 !important;">;</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">for</span> (<span style="color:rgb(0,0,255);line-height:1.5 !important;">int</span> i = <span style="color:rgb(128,0,128);line-height:1.5 !important;">0</span>; i < pointsCount; i++<span style="line-height:1.5 !important;">){area </span>+= (pts[i + <span style="color:rgb(128,0,128);line-height:1.5 !important;">1</span>].Lat - pts[i].Lat) * (pts[i + <span style="color:rgb(128,0,128);line-height:1.5 !important;">1</span>].Lng + pts[i].Lng) / <span style="color:rgb(128,0,128);line-height:1.5 !important;">2</span><span style="line-height:1.5 !important;">;}</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">//</span><span style="color:rgb(0,128,0);line-height:1.5 !important;"> Return the result.</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">return</span><span style="line-height:1.5 !important;"> area;}</span><span style="color:rgb(128,128,128);line-height:1.5 !important;">///</span> <span style="color:rgb(128,128,128);line-height:1.5 !important;"><summary></span><span style="color:rgb(128,128,128);line-height:1.5 !important;">///</span><span style="color:rgb(0,128,0);line-height:1.5 !important;"> Get the area of a polygon</span><span style="color:rgb(128,128,128);line-height:1.5 !important;">///</span> <span style="color:rgb(128,128,128);line-height:1.5 !important;"></summary></span><span style="color:rgb(128,128,128);line-height:1.5 !important;">///</span> <span style="color:rgb(128,128,128);line-height:1.5 !important;"><param name="points"></param></span><span style="color:rgb(128,128,128);line-height:1.5 !important;">///</span> <span style="color:rgb(128,128,128);line-height:1.5 !important;"><returns></returns></span><span style="color:rgb(0,0,255);line-height:1.5 !important;">public</span> <span style="color:rgb(0,0,255);line-height:1.5 !important;">static</span> <span style="color:rgb(0,0,255);line-height:1.5 !important;">double</span> GetPolygonArea(List<PointLatLng><span style="line-height:1.5 !important;"> points){</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">//</span><span style="color:rgb(0,128,0);line-height:1.5 !important;"> Return the absolute value of the signed area.</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">//</span><span style="color:rgb(0,128,0);line-height:1.5 !important;"> The signed area is negative if the polygon is oriented clockwise.</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">return</span><span style="line-height:1.5 !important;"> Math.Abs(SignedPolygonArea(points));}</span></pre><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy" style="line-height:1.5 !important;"><a title="復制代碼" style="color:#008000;border:none !important;" target="_blank"><img src="http://common.cnblogs.com/images/copycode.gif" alt="復制代碼" style="border:none !important;"></a></span></div></div><p> </p><p> </p><p> </p><p>參考資料:</p><p>http://alienryderflex.com/polygon/</p><p>http://en.wikipedia.org/wiki/Point_in_polygon</p><p>http://www.codeproject.com/Tips/84226/Is-a-Point-inside-a-Polygon</p><p> </p></div><div id="MySignature" style="background-color:rgb(248,248,238);border:1px solid rgb(232,231,208);color:#808080;"><div style="line-height:25px;">作者:<a href="http://www.cnblogs.com/luxiaoxun/" rel="nofollow" style="color:#008000;text-decoration:none;" target="_blank">阿凡盧</a></div><div style="line-height:25px;">出處:<a href="http://www.cnblogs.com/luxiaoxun/" rel="nofollow" style="color:#008000;text-decoration:none;" target="_blank">http://www.cnblogs.com/luxiaoxun/</a></div><div style="line-height:25px;">本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。</div></div></div><br><pre class="best-text mb-10" style="background-color:rgb(255,255,255);font-family:'Microsoft YaHei', arial, 'courier new', courier, '宋體', monospace;font-size:16px;line-height:29px;min-height:55px;" name="code"><span style="color:#333333;">
總結
以上是生活随笔為你收集整理的如何判断一个点是否在多边形内?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中encode函数_Pyth
- 下一篇: Fantom (FTM) 价格将在未来几