![]() |
Kollision zweier 2dim Polygonen.
Hi, ich suche einen ähnlichen Algorithmus für 2 Polygone, wie es man ihn überall für die Kollision von einem Punkt und einem Polygon findet.
Bewegung ist dabei relativ egal. Ich will einfach nur wissen, ob zwei 2dim Polygone kollidieren. Habe bisher recht wenig gefunden. Das beste von allem waren Algorithmen in anderen Programmiersprachen, welche dort spezifische Funktionen benutzen, welche ich wohl schlecht in Delphi konvertieren könnte. Geschweige denn verstehen. Gruß Chris |
Re: Kollision zweier 2dim Polygonen.
Zitat:
2 Polygone kollidieren, wenn sich irgendwelche ihrer Umrandungslinien schneiden. D.h. bei 1 Fünf- und 1 Sechseck 5 x 6 = 30 mal berechnen, ob sich 2 Geradenstücke (nicht Geraden!) schneiden. Ich weiss nicht, ob es eine schnellere Möglichkeit gibt. Gruss Reinhard |
Re: Kollision zweier 2dim Polygonen.
Hallo Chris,
ich kann keine Aussage über die zu erreichende Geschwindigkeit machen, aber hast du es schon einmal mit den Region-Befehlen aus der Win32-API versucht? Mit ![]() ![]() Gruß Hawkeye PS: Willkommen in der Delphi-PRAXiS! |
Re: Kollision zweier 2dim Polygonen.
Du Must auch Berücksichtigen das 1 Polygon Komplett in einem Anderen drin sein kann.
Ich zieh mir zu diesem Zeug grad die Ganze Theorie rein. Aber es wird noch ein paar Tage dauern bis ich verwertbare Ergebnisse habe. |
Re: Kollision zweier 2dim Polygonen.
Solange die Polygone beide Konvex sind, kollidieren sie, wenn ein Punkt des ersten im zweiten oder ein Punkt des zweiten im ersten liegt.
Nachdem Du wie Du schriebst bereits einen Algorithmus hast, der einen Punkt mit einem Poly vergleicht sollte das einfach sein. Du kannst aber auch zuerst jeweils den Umkreis (Oder Umrechteck, ist schneller, aber ungenauer) beider Polygone berechnen (einmal reicht, oder sobald sie sich ändern) und erstmal gucken, ob sich die Umkreise berühren. Wenn nein kollidieren sie nicht, wenn ja, musst Du Punktgenau werden. Bei Konvexen Polygonen gilt die erste Regel immernoch, aber in der Einschränkung, dass wenn nicht, die Polys dennoch kollidieren können. In dem Fall musst Du dann wirklich alle Seiten paarweise kreuzen. |
Re: Kollision zweier 2dim Polygonen.
Zitat:
ja, das habe ich übersehen. Aber das bedeutet nur, dass man noch 2 Prüfungen Punkt zu Polygon anhängen muss, wobei es ja egal ist, welchen Punkt man jeweils nimmt, also am einfachsten den Startpunkt für den Umriss. Gruss Reinhard |
Re: Kollision zweier 2dim Polygonen.
Das mit dem gegenseitigen Punkttest, kommt mir etwas Langsam vor.
Versuche gerade die Lösung von Hawkeye219 zu realisieren. Mir fehlt allerdings noch eine Zeile :-/
Code:
Wie muss jetzt mein Vergleich jetzt Aussehen? Ich kenne mich mit Regionen in keinster Weise aus.
function PolygonInPolygon(PointArrayA, PointArrayB: Array of TPoint):boolean;
var RgnA, RgnB, RgnC: hdc; begin RgnA := CreatePolygonRgn(PointArrayA,Length(PointArrayA),Winding); RgnB := CreatePolygonRgn(PointArrayB,Length(PointArrayB),Winding); try CombineRgn( RgnC, // handle to destination region RgnA, // handle to source region RgnB, // handle to source region RGN_AND // region combining mode ); (* Hier muss natürlich jetzt eine Abfrage stehen, ob es RgnB ein Polygon ist *) finally DeleteObject(RgnA); DeleteObject(RgnB); DeleteObject(RgnC); end; end; Für meinen Punkttest benutze ich übrigens auch die Windows API Funktion. Gruß Chris |
Re: Kollision zweier 2dim Polygonen.
Der Rückgabewert von CombineRgn kann einer der folgenden sein:
Zitat:
|
Re: Kollision zweier 2dim Polygonen.
Wie wäre es damit? Ich hatte schonmal das selbe Problem...
![]() EDIT: Ich habe den Code mal hier her kopiert, um toten Links vorzubeugen:
Delphi-Quellcode:
type
TPointArray = array of TPoint; function PointInPolygon(const Polygon : TPointArray; const P : TPoint): boolean; var ToTheLeftofPoint, ToTheRightofPoint : byte; np : integer; OpenPolygon : boolean; XIntersection : real; begin ToTheLeftofPoint := 0; ToTheRightofPoint := 0; OpenPolygon := False; if not ((Polygon[0].X = Polygon[High(Polygon)].X) and (Polygon[0].Y = Polygon[High(Polygon)].Y)) then OpenPolygon := True; for np := 1 to High(Polygon) do if ((Polygon[np - 1].Y <= P.Y) and (Polygon[np].Y > P.Y)) or ((Polygon[np - 1].Y > P.Y) and (Polygon[np].Y <= P.Y)) then begin XIntersection := Polygon[np - 1].X + ((Polygon[np].X - Polygon[np - 1].X) / (Polygon[np].Y - Polygon[np - 1].Y)) * (P.Y - Polygon[np - 1].Y); if XIntersection < P.X then Inc(ToTheLeftofPoint); if XIntersection > P.X then Inc(ToTheRightofPoint); end; if OpenPolygon then begin np := High(Polygon); if ((Polygon[np].Y <= P.Y) and (Polygon[0].Y > P.Y)) or ((Polygon[np].Y > P.Y) and (Polygon[0].Y <= P.Y)) then begin XIntersection := Polygon[np].X + ((Polygon[0].X - Polygon[np].X) / (Polygon[0].Y - Polygon[np].Y)) * (P.Y - Polygon[np].Y); if XIntersection < P.X then Inc(ToTheLeftofPoint); if XIntersection > P.X then Inc(ToTheRightofPoint); end; end; if (ToTheLeftofPoint mod 2 = 1) and (ToTheRightofPoint mod 2 = 1) then Result := True else Result := False; end; |
Re: Kollision zweier 2dim Polygonen.
@igel457: Das ist ja nur eine Funktion, um zu testen, ob ein Punkt in einem Polygon liegt. Ich suche aber eine Funktion, welche prüft ob ein Polygon in einem anderen Polygon ist...
Habe meine Funktion mal angepasst, sie funktioniert aber nicht. Hier mal die Funktion, welche ich zum testen benutzt habe:
Delphi-Quellcode:
Als Rückgabewert bekomme ich immer '0' also einen Fehler. Hat jemand eine Ahnung warum?
procedure TestPolygonInPolygon;
var RgnA, RgnB, RgnC: hdc; TestA, TestB: Array of TPoint; begin SetLength(TestA, 3); TestA[0] := point(1,1); TestA[1] := point(5,1); TestA[2] := point(2,6); SetLength(TestB, 3); TestB[0] := point(3,1); TestB[1] := point(1,4); TestB[2] := point(4,4); RgnA := CreatePolygonRgn(TestA,3,Winding); RgnB := CreatePolygonRgn(TestB,3,Winding); try showmessage(IntToStr(CombineRgn( RgnC, // handle to destination region RgnA, // handle to source region RgnB, // handle to source region RGN_AND // region combining mode ))+#10+'NULLREGION: '+IntToStr(NULLREGION) +#10+'SIMPLEREGION: '+IntToStr(SIMPLEREGION) +#10+'COMPLEXREGION: '+IntToStr(COMPLEXREGION) +#10+'ERROR: '+IntToStr(ERROR)); finally DeleteObject(RgnA); DeleteObject(RgnB); DeleteObject(RgnC); end; end; Gruß Chris |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:26 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz