2010-03-17 32 views
6

我有3點(lat,lon)形成一個三角形。如何找到一個點是否在這個三角形內?確定一個點是否在由給定經度/緯度的3點形成的三角形內

+0

這不是項目歐拉問題嗎? –

+2

你的三角形可能有多大?是否足夠小以至於認爲表面可以被認爲是平坦的或者您是否需要球形幾何? –

+1

繼續Mark的說法,你如何定義「內部」與「外部」?如果你的觀點是火奴魯魯,曼谷和拉各斯,那麼三角形邊緣大致沿着赤道,北極內部還是南極內部? –

回答

1

主要問題是您是否可以使用2D逼近(換句話說,您的三角形是否足夠小)。

如果是這樣,那麼簡單的重心座標就可以很好地工作。

+0

他們在任何數量的維度上工作,AFAIK。 –

+0

棘手的一點是,當它是嵌在3D球體上的2D空間時,三角形的邊緣不是線條,它們是很棒的弧線。從技術上講,你仍然可以使用重心座標,但距離函數是不同的,你必須處理週期性,這只是一個巨大的麻煩。你想要的答案不會完全匹配二維三角形的答案大或不方便放置的三角形。 – tfinniga

3

大多數語言都包含此功能。在Java中它是Polygon.contains() http://docs.oracle.com/javase/7/docs/api/java/awt/Polygon.html

只需從你的點創建一個多邊形,然後在你的測試點上調用contains()。

+1

這不是語言,而是這種情況下提供的語言框架。瞭解軟件的功能總是很好的。只要找到一個點是否在三角形內就可以了,我不認爲使用Polygon會是最好的/最有效的解決方案。 – Christo

+0

我同意@Christo。你並不總是有'awt'在你的處置。 –

+0

這是不理想的,因爲Polygon.contains()支持任何類型的多邊形,因此,算法複雜得多,而且其他手動(但簡單)的解決方案在其他答案中提供了更多。此外,awt並不是Java開發人員通常瘋狂使用的一組類。 –

0
function SameSide(p1,p2, a,b) 
    cp1 = CrossProduct(b-a, p1-a) 
    cp2 = CrossProduct(b-a, p2-a) 
    if DotProduct(cp1, cp2) >= 0 then return true 
    else return false 

function PointInTriangle(p, a,b,c) 
    if SameSide(p,a, b,c) and SameSide(p,b, a,c) 
     and SameSide(p,c, a,b) then return true 
    else return false 

解釋在下面的鏈接

http://www.blackpawn.com/texts/pointinpoly/default.html

+0

...先將點投影到三角形的平面上。 –

+0

在這個例子中太多的「魔法」正在進行。 CrossProduct永遠不會被展開。 –

2

您可以使用點多邊形測試。

很簡單。從你的角度畫一條線到東方足夠的距離。計算該線與您的plygon相交的次數。如果它是平衡的,你的觀點在外面,如果奇怪的話,它的內部。

適用於任何類型的多邊形。

+1

如果使用此方法,請確保處理邊緣情況 - 兩條平行線可以具有無限多的交點。 –

0

我今天做了這樣的事情!還有(lat,lon),實際上(theta,phi),儘管我更瞭解我正在使用的網格。我正在使用(theta,phi)與0 < = theta < = PI & = phi < = 2 * PI。

如果其中一個頂點位於球體的頂部或底部,可能會遇到一些麻煩,因爲在我的情況下,phi並未真正定義。你最終會得到一個奇點。你基本上有一個正方形,這使得更容易檢查你的觀點是否在其中。

在所有其他情況下,如果您已將點轉換爲(lat,lon)/(theta,phi)。使用@Michelle Six描述的方法應該很簡單。

5

Java代碼只是三角形,即3點。

public static boolean pntInTriangle(double px, double py, double x1, double y1, double x2, double y2, double x3, double y3) { 

    double o1 = getOrientationResult(x1, y1, x2, y2, px, py); 
    double o2 = getOrientationResult(x2, y2, x3, y3, px, py); 
    double o3 = getOrientationResult(x3, y3, x1, y1, px, py); 

    return (o1 == o2) && (o2 == o3); 
} 

private static int getOrientationResult(double x1, double y1, double x2, double y2, double px, double py) { 
    double orientation = ((x2 - x1) * (py - y1)) - ((px - x1) * (y2 - y1)); 
    if (orientation > 0) { 
     return 1; 
    } 
    else if (orientation < 0) { 
     return -1; 
    } 
    else { 
     return 0; 
    } 
} 
+0

我不完全理解這是如何工作的。 getOrientationResult中的魔術表達從何而來? – singpolyma

+0

它不是*那*魔法,它是重心計算 –

+0

定向公式是錯誤的。我發現了多個來源,證實了P1,P2和P3三角形的公式是:(p1.x - p3.x)*(p2.y - p3.y) - (p1.y - p3.y) *(p2.x - p3.x);此外,三個三角形的方向必須與原始三角形的方向相同,這裏不再贅述。來源(抱歉,它們是西班牙文,但公式是通用的;-) http://www.dma.fi.upm.es/mabellanas/tfcs/kirkpatrick/Aplicacion/algoritmos.htm#puntoInterior http:// ouphenus .scienceontheweb.net/2008/07/13 /未PUNTO-迪登特魯-DE-未triangulo / –

2

這裏是一個Javascript實現重心座標解discussed here

// Returns true if point P inside the triangle with vertices at A, B and C 
// representing 2D vectors and points as [x,y]. Based on       
// http://www.blackpawn.com/texts/pointinpoly/default.html 
function pointInTriange(P, A, B, C) { 
    // Compute vectors   
    function vec(from, to) { return [to[0] - from[0], to[1] - from[1]]; } 
    var v0 = vec(A, C); 
    var v1 = vec(A, B); 
    var v2 = vec(A, P); 
    // Compute dot products 
    function dot(u, v) { return u[0] * v[0] + u[1] * v[1]; } 
    var dot00 = dot(v0, v0); 
    var dot01 = dot(v0, v1); 
    var dot02 = dot(v0, v2); 
    var dot11 = dot(v1, v1); 
    var dot12 = dot(v1, v2); 
    // Compute barycentric coordinates 
    var invDenom = 1.0/(dot00 * dot11 - dot01 * dot01); 
    var u = (dot11 * dot02 - dot01 * dot12) * invDenom; 
    var v = (dot00 * dot12 - dot01 * dot02) * invDenom; 
    // Check if point is in triangle 
    return (u >= 0) && (v >= 0) && (u + v < 1); 
} 

據說這比跨產品基礎的解決方案更快。

相關問題