2017-11-17 1 views
1

Zuletzt benutzte ich formschön, ich hatte wirklich this nice import-and-fly-feeling. Jedoch habe ich in letzter Zeit ein eher nicht intuitives Verhalten in diesem Modul, als ich versuchte, den Schnittpunkt zwischen einem Liniensegment und einem Dreieck im 3D-Raum zu finden. Lassen Sie uns ein Segment und ein Dreieck wie folgt definieren:Formschön: Schnittpunkt zwischen Linie und Polygon in 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.]]) 

Um ihren Schnittpunkt gewöhnungs ich l.intersection(p) und einen Punkt erwartet, nämlich POINT Z (POINT Z (2 0.5 0.25)). Es wird unten mit dem blauen Punkt dargestellt:

enter image description here

Stattdessen, was ich bekam, war LINESTRING Z (1.7 0.5 0.25, 2.8 0.5 1) - rote Linie unten - und ehrlich gesagt bin ich ziemlich ratlos darüber, was es darstellen soll. enter image description here

Merkwürdigerweise, wenn das Polygon/Dreieck in der xz-Ebene und senkrecht zu dem Liniensegment ist, verhält sich die Funktion als man erwarten würde. Wenn das Dreieck jedoch "gelehnt" ist, gibt es eine Linie zurück. Dies hat mich vorübergehend zu der Annahme verleitet, dass es den Schnittpunkt zwischen der Linie und der Begrenzungsbox des Dreiecks zurückgegeben hat. Die obige rote Linie beweist das Gegenteil.

So eine Problemumgehung für dieses Problem wurde this very enlightening web-page lesen und ihre C++ Code an die Arbeit mit formschönen Objekten anpassen. Die intersection Methode funktioniert hervorragend, um zu überprüfen, ob die Linie durch das Polygon verläuft, und die folgende Funktion findet den Punkt von Interesse.

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 

Nicht sehr mehr Import-and-fly ...

So endlich auf meine Fragen:

  • Was intersection Rückkehr tut, wenn auf 3D-Objekte angewendet und warum ist es ein Linie?

  • Gibt es eine formschöne Funktion, die das macht, was ich will? oder irgendein optionales Argument, Tweak oder dunkler Zaubertrick?

  • Gibt es noch andere Bibliotheken, die diesen Job machen und meinen Traum von Einfachheit und Faulheit erfüllen?

Antwort

1

leider, wie die Dokumentation heißt es:

Koordinatenfolgen unveränderlich sind. Ein dritter z-Koordinatenwert kann beim Erstellen von Instanzen verwendet werden, hat jedoch keine Auswirkungen auf die geometrische Analyse. Alle Operationen werden in der x-y-Ebene ausgeführt.

Man kann dies überprüfen, mit:

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) 

oder sogar:

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) 
Verwandte Themen