2015-06-16 16 views
11

Qualcuno ha una conoscenza di una funzione che restituisce l'intersezione TPath per due TShapes? Soprattutto quello che restituisce l'intersezione TPath di due TPath.Funzione che restituisce l'intersezione di due TShapes, inclusi i TPath?

Per esempio:

pthIntersection := PathIntersection(Path1,Path2); 

enter image description here

+0

Mi piace la domanda, ma la prossima volta, includi una foto di ciò che stai cercando di ottenere, vedi: http://stackoverflow.com/questions/3940694/line-clipping-to-arbitary-2d-polygon per un esempio di uso efficace della grafica in una domanda. – Johan

risposta

14

Non esiste una funzione built-in per questo.
Ma quello che penso tu stia cercando di fare è questo:

Dato un poligono (noto anche come TPath) composto per punti distinti collegati da linee.
Restituisce tutti i punti in ShapeA che si trovano all'interno di ShapeB.

punto di intersezione
questo può essere fatto utilizzando PointInObjectLocal.
Esegui un ciclo visitando tutti i punti in PathA e verifica se c'è spazio all'interno di PathB.

linea di intersezione
Se volete conoscere tutti i vertici che si sovrappongono per prima cosa devi Flatten (una copia) di entrambi TPaths e quindi eseguire una linea interseca algoritmo per tutte le linee in entrambe le forme.
Converte tutte le curve in linee.

Ecco una routine per fare proprio questo:
Da: 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; 

solo convertire i TFloat coppie x, y per TPointF e siete a posto. La cosa bella della routine è che ti dice anche il punto esatto in cui le linee si sovrappongono.

Se si seguono le linee, fino a quando due linee si sovrappongono e da lì in poi si esegue il tracciamento di entrambe le linee sovrapposte e PointInShape è possibile costruire un'immagine esatta della sovrapposizione delle due forme.

rendendo più veloce
Se l'appiattimento e il corrispondente aumento del numero di segmenti di linea rendono il codice troppo lento è possibile mantenere le curve e vedere se una linea/curva interseca un'altra curva.
Per questo è possibile convertire le curve in bezier curves e utilizzare De_Casteljau's algorithm

Maggiori informazioni
Vedi anche this question e il link to Delphi source code nella sua prima o seconda risposta.

+1

Dankie, Johan. Avevo paura di dover prendere la strada difficile e avevo già iniziato su questa strada (nessun gioco di parole) dopo che nessuno è arrivato con una soluzione TPath. Dal momento che il mio problema riguarda soprattutto le curve di Bezier, esaminerò anche i collegamenti. – Domus

Problemi correlati