2017-11-17 234 views
1

上一次我用得很體面,我真的有this nice import-and-fly-feeling。 但是最近,我在這個模塊中遇到了一個相當不直觀的行爲,因爲我試圖在3D空間中找到線段和三角形之間的交點。讓我們定義一個段和一個三角形如下:勻稱:3D中線條與多邊形的交點

l = LineString([[1,0.5,0.5],[3,0.5,0.5]]) 
p = Polygon([[1.2,0.0,0.],[2.2,1.0,0.],[2.8,0.5,1.]]) 

得到他們的交點,我用l.intersection(p),和預期的一個點,即POINT Z (POINT Z (2 0.5 0.25))。它說明與下面的藍點:

enter image description here

相反,我得到了什麼是LINESTRING Z (1.7 0.5 0.25, 2.8 0.5 1) - 低於紅線 - 坦率地說,我很困惑關於什麼是應該來表示。 enter image description here

奇怪的是,當多邊形/三角形位於xz平面中且與線段正交時,該函數的行爲與預期相同。但是,當三角形「傾斜」時,它會返回一條直線。這暫時讓我相信它返回了直線和三角形邊界框之間的交點。上面的紅線證明不然。

因此,針對此問題的一種解決方法是讀取this very enlightening web-page,並使其代碼與修整後的對象配合使用。 intersection方法非常適用於檢查線是否穿過多邊形,並且下面的函數找到感興趣的點。

def intersect3D_SegmentPlane(Segment, Plane): 

    # Points in Segment: Pn Points in Plane: Qn 
    P0, P1  = np.array(Segment.coords) 
    Q0, Q1, Q2 = np.array(Plane.exterior)[:-1] 

    # vectors in Plane 
    q1 = Q1 - Q0 
    q2 = Q2 - Q0 

    # vector normal to Plane 
    n = np.cross(q1, q2)/np.linalg.norm(np.cross(q1, q2)) 
    u = P1 - P0 # Segment's direction vector 
    w = P0 - Q0 # vector from plane ref point to segment ref point 

    ## Tests parallelism 
    if np.dot(n, u) == 0: 
     print "Segment and plane are parallel" 
     print "Either Segment is entirely in Plane or they never intersect." 
     return None 
    ## if intersection is a point 
    else: 
     ## Si is the scalar where P(Si) = P0 + Si*u lies in Plane 
     Si = np.dot(-n, w)/np.dot(n, u) 
     PSi = P0 + Si * u 
     return PSi 

不是很了進口和飛...

所以最後我的問題:

  • 當應用到3D對象是什麼intersection回報,爲什麼它是一個線?

  • 有沒有一個功能在做得到我想要的?或任何可選的參數,調整或黑暗的魔術技巧?

  • 有沒有其他的圖書館可以完成這個工作,同時實現我對簡單和懶惰的夢想?

回答

1

不幸的是,文件規定:

座標序列是不可改變的。構造實例時可以使用第三個z座標值,但對幾何分析沒有影響。所有操作都在x-y平面中執行。

from shapely.geometry import LineString, Polygon 

l = LineString([[1,0.5,0.5],[3,0.5,0.5]]) 
p = Polygon([[1.2,0.0,0.],[2.2,1.0,0.],[2.8,0.5,1.]]) 
print(l.intersection(p)) 
#LINESTRING Z (1.7 0.5 0.25, 2.8 0.5 1) 

l = LineString([[1,0.5],[3,0.5]]) 
p = Polygon([[1.2,0.0],[2.2,1.0],[2.8,0.5]]) 
print(l.intersection(p)) 
#LINESTRING (1.7 0.5, 2.8 0.5) 

甚至:

from shapely.geometry import LineString, Polygon 

l = LineString([[1,0.5,0],[3,0.5,0]]) 
p = Polygon([[1.2,0.0,1],[2.2,1.0,1],[2.8,0.5,1]]) 
print(l.intersects(p)) 
#True (even though the objects are in different z-planes) 

一個可以驗證這一點