2015-06-16 23 views
11

Ktoś ma wiedzę na temat funkcji, która zwraca TPath skrzyżowania dla dwóch TShapes? Zwłaszcza taki, który zwraca TPath skrzyżowania dwóch TPath.Funkcja, która zwraca przecięcie dwóch TShapes, w tym TPaths?

Na przykład:

pthIntersection := PathIntersection(Path1,Path2); 

enter image description here

+0

Podoba mi się pytanie, ale następnym razem, proszę dołączyć zdjęcie tego, co próbujesz osiągnąć, zobacz: http://stackoverflow.com/questions/3940694/line-clipping-to-arbitary-2d-polygon dla przykład efektywnego wykorzystania grafiki w pytaniu. – Johan

Odpowiedz

14

Nie ma wbudowaną funkcję do tego.
Ale to, co myślę, że próbujesz zrobić, to:

Biorąc pod uwagę wielokąt (aka TPath) składa się z różnych punktów połączonych liniami.
Zwróć wszystkie punkty w ShapeA leżące wewnątrz ShapeB.

Punkt przecięcia
Można to zrobić za pomocą PointInObjectLocal.
Uruchom pętlę odwiedzając wszystkie punkty w PathA i sprawdź, czy w środku znajduje się PathB.

Linia przecięcia
Jeśli chcesz znać wszystkie wierzchołki, które pokrywają musisz najpierw do Flatten (kopia) obu TPaths a następnie uruchomić wiersz przecinają algorytmu dla wszystkich linii w obu kształtów.
Spowoduje to przekształcenie wszystkich krzywych w wiersze.

Oto rutynowe właśnie do tego:
Od: 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; 

Wystarczy przekształcić TFloat x, y pary do TPointF i jesteś w biznesie. Fajną rzeczą w rutynie jest to, że wskazuje ona dokładnie punkt, w którym linie się pokrywają.

Jeśli podążasz za liniami, aż dwie linie pokrywają się, a stamtąd na początku śledzenia zarówno nakładających się linii i PointInShape można zbudować dokładny obraz nakładania się dwóch kształtów.

co przyspiesza
Jeśli spłaszczenie i odpowiadający im wzrost w liczbie odcinków uczynić kod zbyt powolny można zachować krzywe i sprawdzić, czy linia/krzywa przecina inną krzywą.
Do tego można przekształcić w krzywe bezier curves i używać De_Casteljau's algorithm

Więcej informacji
Zobacz również this question i link to Delphi source code w pierwszym lub drugim odpowiedź.

+1

Dankie, Johan. Bałem się, że muszę wziąć ciężką drogę i już ruszyłem tą ścieżką (nie gra słów), po tym, jak nikt nie przyszedł z rozwiązaniem TPath. Ponieważ mój problem dotyczy głównie krzywych Beziera, zajrzę także w linki. – Domus