Ich versuche zwei Dinge zu kombinieren. Ich schreibe ein Spiel und muss die Gitterquadrate bestimmen, die auf einer Linie mit den Gleitkomma-Endpunkten liegen.
Außerdem muss es alle Gitterquadrate enthalten, die es berührt (dh nicht nur Bresenhams Linie, sondern die blaue):
Kann mir jemand einen Einblick geben, wie das geht? Die naheliegende Lösung ist die Verwendung eines naiven Linienalgorithmus. Gibt es jedoch etwas Optimierteres (schnelleres)?
c#
algorithm
grid
interpolation
floating-point
SmartK8
quelle
quelle
Antworten:
Sie suchen nach einem Gitterdurchquerungsalgorithmus. Dieses Papier gibt eine gute Umsetzung;
Hier ist die grundlegende Implementierung in 2D, die auf dem Papier zu finden ist:
Es gibt auch eine 3D-Raycasting-Version auf dem Papier.
Falls die Verbindung rotiert , finden Sie viele Spiegel mit dem Namen: Ein schnellerer Voxel-Durchquerungsalgorithmus für das Raytracing .
quelle
Die Idee von Blue ist gut, aber die Implementierung ist etwas umständlich. In der Tat können Sie es leicht ohne sqrt tun. Nehmen wir für den Moment an, dass Sie entartete Fälle ausschließen (
BeginX==EndX || BeginY==EndY
) ausschließen und sich daher nur auf die Linienrichtungen im ersten Quadranten konzentrierenBeginX < EndX && BeginY < EndY
. Sie müssen auch eine Version für mindestens einen anderen Quadranten implementieren, aber das ist der Version für den ersten Quadranten sehr ähnlich - Sie überprüfen nur andere Kanten. Im C'ish-Pseudocode:Jetzt ändern Sie für andere Quadranten einfach die Bedingung
++cx
oder++cy
und die Schleifenbedingung. Wenn Sie dies für eine Kollision verwenden, müssen Sie wahrscheinlich alle 4 Versionen implementieren, andernfalls können Sie mit zwei davonkommen, indem Sie die Anfangs- und Endpunkte entsprechend vertauschen.quelle
Es ist nicht unbedingt Ihre Annahme, die Zellen zu finden, sondern die Linien, die sie in diesem Raster kreuzen.
Wenn Sie beispielsweise ein Bild aufnehmen, können wir nicht die Zellen, sondern die Linien des Gitters hervorheben, das es kreuzt:
Dies zeigt dann, dass, wenn es eine Gitterlinie kreuzt, die Zellen auf beiden Seiten dieser Linie diejenigen sind, die gefüllt sind.
Mithilfe eines Schnittalgorithmus können Sie ermitteln, ob Ihre Gleitkomma-Linie diese schneidet, indem Sie Ihre Punkte in Pixel skalieren. Wenn Sie ein Verhältnis von fließenden Koordinaten zu Pixeln von 1,0: 1 haben, werden Sie sortiert und können es einfach direkt übersetzen. Mit dem Liniensegment-Schnittalgorithmus können Sie prüfen, ob sich Ihre untere linke Linie (1,7) (2,7) mit Ihrer Linie (1.3,6.2) (6.51,2.9) schneidet.http://alienryderflex.com/intersect/
Einige Übersetzungen von c nach C # werden benötigt, aber Sie können die Idee aus diesem Papier ableiten. Ich werde den Code unten setzen, falls der Link bricht.
Wenn Sie nur herausfinden müssen, wann (und wo) sich die Liniensegmente schneiden, können Sie die Funktion wie folgt ändern:
quelle
JS Demo:
Code-Snippet anzeigen
quelle
Ich bin heute auf dasselbe Problem gestoßen und habe aus einem Maulwurfshügel einen ziemlich großen Berg Spaghetti gemacht. Am Ende hatte ich jedoch etwas, das funktioniert: https://github.com/SnpM/Pan-Line-Algorithm .
Aus der Liesmich:
Die Liesmich erklärt die Lösung viel besser als der Code. Ich plane, es zu überarbeiten, um weniger Kopfschmerzen zu verursachen.
Ich weiß, dass ich ungefähr ein Jahr zu spät für diese Frage bin, aber ich hoffe, dass dies auch andere erreicht, die nach einer Lösung für dieses Problem suchen.
quelle