Entwickler-Ecke
Algorithmen, Optimierung und Assembler - Punkt in Polygon (schnell)
Spaceguide - Mo 12.09.05 19:55
Titel: Punkt in Polygon (schnell)
Was ist die schnellste Methode nachzuprüfen, ob ein Punkt in einem (nicht unbedingt konvexen) Vieleck liegt? Ich habe hier noch diesen Code, den ich glaub irgendwann mal von C her übersetzt habe. Gibt es eine schnellere Methode, eventuell mit Zerlegung mittels Tiles/Quadtree?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36:
| function PtInPolyDouble (const Points: array of TPoint; Count: integer; X, Y: double): Boolean;
var bInside : boolean; i,j : integer; rkU0,rkU1 : ^TPoint; fRHS, fLHS : double; begin bInside := false; j:= Count-1; for i := 0 to Count-1 do begin rkU0 := @Points[i]; rkU1 := @Points[j];
if ( y < rkU1.y ) then begin if ( rkU0.y <= y ) then begin fLHS := (y-rkU0.y)*(rkU1.x-rkU0.x); fRHS := (x-rkU0.x)*(rkU1.y-rkU0.y); if ( fLHS > fRHS ) then bInside := not bInside; end; end else if ( y < rkU0.y ) then begin fLHS := (y-rkU0.y)*(rkU1.x-rkU0.x); fRHS := (x-rkU0.x)*(rkU1.y-rkU0.y); if ( fLHS < fRHS ) then bInside := not bInside; end;
j:=i; end; Result:=bInside; end; |
worm - Sa 17.09.05 20:08
Hallo!
Folgender Code stammt aus der guten alten GLScene-Library (aus der
Geometry-Unit einer schon älteren Version, weiß nicht, ob in der aktuellen vielleicht sogar was schnelleres ist). Ich weiß auch nicht, ob er Deinen Anforderungen genügt (nicht-konvexe Vielecke). Außerdem erfordert er in der vorliegenden Version eine andere Form der Parameter (zwei Arrays statt TPoints).
GLScene ist unter der MPL veröffentlicht, siehe
glscene.sf.net [
http://glscene.sourceforge.net/faq.htm#240700-2].
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| function PointInPolygon(var xp, yp : array of Single; x, y: Single) : Boolean; var I, J: Integer; begin Result:=False; if High(XP)=High(YP) then begin J:=High(XP); for I:=0 to High(XP) do begin if ((((YP[I]<=Y) and (Y<YP[J])) or ((YP[J]<=Y) and (Y<YP[I])) ) and (X<(XP[J]-XP[I])*(Y-YP[I])/(YP[J]-YP[I])+XP[I])) then Result:=not Result; J:=I; end; end; end; |
Spaceguide - So 18.09.05 17:31
Danke, muss ich mal "benchen". Ich sehe aber eine Division, das ist schonmal ein schlechtes Zeichen.
Edit: Deiner ist knapp 10% schneller, ist aber auch nur ein Tropfen auf den heissen Stein.
delfiphan - So 18.09.05 17:36
Wofür brauchst du das denn? Die Methode mittles Scanlines (PtInPolyDouble) scheint eigentlich schon recht optimal zu sein. Wie sind die Vielecke durchschnittlich?
Spaceguide - So 18.09.05 17:50
Durchschnittlich so vielleicht 100-200 Punkte. Würde sich eine Zerlegung in Dreiecke + Quadtree lohnen?
delfiphan - So 18.09.05 17:54
Die Division kannst du ja auch auf die andere Seite der Ungleichung nehmen. Das geht aber nur, wenn der Divisor nicht negativ ist... Eine Aufteilung bringt sicher was, geht aber nur, wenn man das vorberechnen kann (d.h. das Objekt darf sich nicht mehr ändern).
Aber nochmals: Wofür brauchst du es? Kollisionserkennung? Wie genau musst du das erkennen können?
Spaceguide - So 18.09.05 17:58
Ich brauche es zum "rendern" von Polygonen mit Antialiasing.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!