2015-06-16 7 views
11

Kennt jemand eine Funktion, die den Schnitt TPath für zwei TShapes zurückgibt? Insbesondere eine, die den Schnitt TPath von zwei TPaths zurückgibt.Funktion, die Schnittpunkt zweier TShapes zurückgibt, einschließlich TPaths?

Zum Beispiel:

pthIntersection := PathIntersection(Path1,Path2); 

enter image description here

+0

Ich mag die Frage, aber das nächste Mal, bitte fügen Sie ein Bild von dem, was Sie erreichen wollen, siehe: http://stackoverflow.com/questions/3940694/line-clipping-to-arbitary-2d-polygon für ein Beispiel für die effektive Verwendung von Grafiken in einer Frage. – Johan

Antwort

14

Es gibt keine integrierte Funktion dafür.
Aber was ich denke, Sie versuchen zu tun, ist dies:

Gegeben ein Polygon (auch bekannt als TPath) für verschiedene Punkte durch Linien verbunden.
Geben Sie alle Punkte in ShapeA zurück, die in ShapeB liegen.

Punkt Kreuzung
Dies kann mit PointInObjectLocal erfolgen.
Führen Sie eine Schleife, die alle Punkte in PathA besucht, und sehen Sie, ob irgendwelche innerhalb PathB liegen.

Linie Kreuzung
Wenn Sie alle Ecken wissen wollen, die Sie zuerst Flatten (eine Kopie) beiden TPaths haben überlappen werden und dann eine Linie schneiden Algorithmus für alle Linien in beiden Formen laufen.
Dies konvertiert alle Kurven in Linien.

Hier ist eine Routine genau das zu tun:
Von: http://www.partow.net/projects/fastgeo/index.html

function Intersect(const x1, y1, x2, y2, x3, y3, x4, y4: TFloat; out ix, iy: TFloat): boolean; 
var 
    UpperX, UpperY, LowerX, LowerY: TFloat; 
    Ax, Bx, Cx, Ay, By, Cy: TFloat; 
    D, F, E, Ratio: TFloat; 
begin 
    Result:= false; 

    Ax:= x2 - x1; 
    Bx:= x3 - x4; 

    if Ax < Zero then begin 
    LowerX:= x2; 
    UpperX:= x1; 
    end else begin 
    UpperX:= x2; 
    LowerX:= x1; 
    end; 

    if Bx > Zero then begin 
    if (UpperX < x4) or (x3 < LowerX) then Exit; 
    end else if (UpperX < x3) or (x4 < LowerX) then Exit; 

    Ay:= y2 - y1; 
    By:= y3 - y4; 

    if Ay < Zero then begin 
    LowerY:= y2; 
    UpperY:= y1; 
    end else begin 
    UpperY:= y2; 
    LowerY:= y1; 
    end; 

    if By > Zero then begin 
    if (UpperY < y4) or (y3 < LowerY) then Exit; 
    end else if (UpperY < y3) or (y4 < LowerY) then Exit; 

    Cx:= x1 - x3; 
    Cy:= y1 - y3; 
    D:= (By * Cx) - (Bx * Cy); 
    F:= (Ay * Bx) - (Ax * By); 

    if F > Zero then begin 
    if (D < Zero) or (D > F) then Exit; 
    end else if (D > Zero) or (D < F) then Exit; 

    E:= (Ax * Cy) - (Ay * Cx); 

    if F > Zero then begin 
    if (E < Zero) or (E > F) then Exit; 
    end else if (E > Zero) or (E < F) then Exit; 

    Result:= true; 

    Ratio:= (Ax * -By) - (Ay * -Bx); 

    if NotEqual(Ratio, Zero) then begin 
    Ratio:= ((Cy * -Bx) - (Cx * -By))/Ratio; 
    ix:= x1 + (Ratio * Ax); 
    iy:= y1 + (Ratio * Ay); 
    end else begin 
    //if Collinear(x1,y1,x2,y2,x3,y3) then 
    if IsEqual((Ax * -Cy), (-Cx * Ay)) then begin 
     ix:= x3; 
     iy:= y3; 
    end else begin 
     ix:= x4; 
     iy:= y4; 
    end; 
    end; 
end; 

function Intersect(const Segment1,Segment2:TSegment2D; out ix, iy : TFloat):Boolean; 
begin 
    Result := Intersect(Segment1[1].x,Segment1[1].y,Segment1[2].x,Segment1[2].y,Segment2[1].x,Segment2[1].y,Segment2[2].x,Segment2[2].y,ix,iy); 
end; 

nur wandeln die TFloat x, y-Paare zu TPointF und Du bist im Geschäft. Die coole Sache über die Routine ist, dass es Ihnen auch den genauen Punkt mitteilt, an dem sich die Linien überschneiden.

Wenn Sie den Linien folgen, bis sich zwei Linien überlappen, und von dort aus beide überlappenden Linien und PointInShape verfolgen, können Sie ein genaues Bild der Überlappung der beiden Formen erstellen.

machen es schneller
Wenn die Abflachung und die entsprechende Erhöhung der Anzahl der Liniensegmente machen zu Ihren Code zu verlangsamen Sie die Kurven halten können und sehen, ob eine Linie/Kurve eine andere Kurve schneidet.
Hierfür können Sie die Kurven in bezier curves und De_Casteljau's algorithm

Mehr Infos
Siehe auch this question und die link to Delphi source code in seiner ersten oder zweiten Antwort verwenden konvertieren.

+1

Dankie, Johan. Ich hatte Angst, dass ich den harten Weg nehmen musste und hatte diesen Weg bereits begonnen (kein Wortspiel beabsichtigt), nachdem niemand mit einer TPath-Lösung gekommen war. Da mein Thema hauptsächlich Bezierkurven betrifft, werde ich auch die Links betrachten. – Domus

Verwandte Themen