Willst du es als String oder Enum? (Ja, es ist wichtig)
Philipp
Entweder, da es in beide Richtungen verwendet wird :) Obwohl ich eine Schnur nehmen würde, wenn ich sie auswählen müsste.
izb
1
Sind Sie auch besorgt über die Leistung oder nur über die Prägnanz?
Marcin Seredynski
2
var angle = Math.atan2 (y, x); Rückgabe <Richtung> Math.floor ((Math.round (angle / (2 * Math.PI / 8)) + 8 + 2)% 8); Ich benutze diese
Kikaimaru
Prägnant: durch Kürze des Ausdrucks oder der Aussage gekennzeichnet: frei von jeglicher Ausarbeitung und überflüssigen Details.
Wirf das
Antworten:
25
Am einfachsten ist es wahrscheinlich, den Winkel des Vektors mit atan2()zu berechnen, wie Tetrad in den Kommentaren angibt, und ihn dann zu skalieren und zu runden, z. B. (Pseudocode):
// enumerated counterclockwise, starting from east = 0:enum compassDir {
E =0, NE =1,
N =2, NW =3,
W =4, SW =5,
S =6, SE =7};// for string conversion, if you can't just do e.g. dir.toString():conststring[8] headings ={"E","NE","N","NW","W","SW","S","SE"};// actual conversion code:float angle = atan2( vector.y, vector.x );int octant = round(8* angle /(2*PI)+8)%8;
compassDir dir =(compassDir) octant;// typecast to enum: 0 -> E etc.string dirStr = headings[octant];
Die octant = round( 8 * angle / (2*PI) + 8 ) % 8Zeile benötigt möglicherweise eine Erklärung. In so ziemlich allen Sprachen, die ich kenne, gibt die atan2()Funktion den Winkel im Bogenmaß zurück. Teilen Sie es durch 2 π wird es vom Bogenmaß in Bruchteile eines vollen Kreises umgewandelt und durch Multiplizieren mit 8 in Achtel eines Kreises umgewandelt, den wir dann auf die nächste ganze Zahl runden. Schließlich reduzieren wir es modulo 8, um den Wrap-Around zu erledigen, damit sowohl 0 als auch 8 korrekt nach Osten abgebildet werden.
Der Grund für das + 8, was ich oben übersprungen habe, ist, dass in einigen Sprachen atan2()negative Ergebnisse (dh von - π bis + π statt von 0 bis 2 π ) zurückgegeben werden können und der Modulo-Operator ( %) definiert werden kann, um negative Werte für zurückzugeben negative Argumente (oder sein Verhalten für negative Argumente kann undefiniert sein). Das Hinzufügen 8(dh eine volle Umdrehung) zu der Eingabe vor dem Reduzieren stellt sicher, dass die Argumente immer positiv sind, ohne das Ergebnis auf andere Weise zu beeinflussen.
Wenn Ihre Sprache keine bequeme Funktion zum Aufrunden der nächsten Zahl bietet, können Sie stattdessen eine Ganzzahlumwandlung mit Kürzung verwenden und dem Argument einfach 0,5 hinzufügen, wie folgt:
int octant =int(8* angle /(2*PI)+8.5)%8;// int() rounds down
Beachten Sie, dass in einigen Sprachen bei der Standardkonvertierung von Float in Integer negative Eingaben eher in Richtung Null als nach unten gerundet werden. Dies ist ein weiterer Grund, um sicherzustellen, dass die Eingabe immer positiv ist.
Natürlich können Sie alle Vorkommen 8in dieser Zeile durch eine andere Zahl ersetzen (z. B. 4 oder 16 oder sogar 6 oder 12, wenn Sie sich auf einer Hex-Karte befinden), um den Kreis in so viele Richtungen zu unterteilen. Passen Sie einfach die Enumeration / das Array entsprechend an.
Beachten Sie, dass dies normalerweise atan2(y,x)nicht der Fall ist atan2(x,y).
Sam Hocevar
@Sam: Ups, korrigiert. Natürlich atan2(x,y)würde das auch funktionieren, wenn man stattdessen die Kompass-Überschriften im Uhrzeigersinn beginnend von Norden auflistet.
Ilmari Karonen
2
+1 übrigens, ich denke wirklich, das ist die direkteste und konsequenteste Antwort.
Sam Hocevar
1
@TheLima:octant = round(8 * angle / 360 + 8) % 8
Ilmari Karonen
1
Zu beachten ist, dass dies leicht zu einem 4-Wege - Kompass umgewandelt werden: quadtant = round(4 * angle / (2*PI) + 4) % 4und mit Enum: { E, N, W, S }.
Spoike
10
Sie haben 8 Optionen (oder 16 oder mehr, wenn Sie eine noch feinere Präzision wünschen).
Verwenden Sie atan2(y,x), um den Winkel für Ihren Vektor zu ermitteln.
atan2() funktioniert wie folgt:
Also ergibt x = 1, y = 0 0 und es ist diskontinuierlich bei x = -1, y = 0 und enthält sowohl π als auch -π.
Jetzt müssen wir nur noch die Ausgabe von atan2()zuordnen, um sie mit der des oben angegebenen Kompasses abzugleichen.
Die wahrscheinlich einfachste Implementierung ist eine inkrementelle Überprüfung der Winkel. Hier ist ein Pseudocode, der leicht geändert werden kann, um die Genauigkeit zu erhöhen:
//start direction from the lowest value, in this case it's west with -πenum direction {
west,
south,
east,
north
}
increment =(2PI)/direction.count
angle = atan2(y,x);
testangle =-PI + increment/2
index =0while angle > testangle
index++if(index > direction.count -1)return direction[0]//roll over
testangle += increment
return direction[index]
Um die Genauigkeit zu erhöhen, fügen Sie einfach die Werte zur Richtungsaufzählung hinzu.
Der Algorithmus überprüft auf dem Kompass zunehmende Werte, um festzustellen, ob unser Winkel irgendwo zwischen dem Ort der letzten Überprüfung und der neuen Position liegt. Deshalb fangen wir bei -PI + increment / 2 an. Wir möchten unsere Schecks so ausgleichen, dass sie in jede Richtung den gleichen Abstand einschließen. Etwas wie das:
West ist zweigeteilt, da die Rückgabewerte von atan2()at West diskontinuierlich sind.
Eine einfache Möglichkeit, sie in einen Winkel umzuwandeln, ist die Verwendung von atan2. Beachten Sie jedoch, dass 0 Grad wahrscheinlich Ost und nicht Nord sind.
Tetrad
1
Sie brauchen die angle >=Schecks im obigen Code nicht; Wenn der Winkel beispielsweise kleiner als 45 ist, wurde der Norden bereits zurückgegeben, sodass Sie für die Ostprüfung nicht überprüfen müssen, ob der Winkel> = 45 ist. Ebenso brauchen Sie vor Ihrer Rückkehr nach Westen überhaupt keinen Scheck - es ist die einzige verbleibende Möglichkeit.
MrKWatkins
4
Ich würde das nicht als einen prägnanten Weg bezeichnen, um die Richtung zu bestimmen. Es scheint ziemlich klobig und erfordert eine Menge Änderungen, um dies an verschiedene "Auflösungen" anzupassen. Ganz zu schweigen von unzähligen ifAussagen, wenn Sie 16 oder mehr Richtungen einschlagen möchten.
Mistzack
2
Der Vektor muss nicht normalisiert werden: Der Winkel bleibt bei Änderungen der Größe gleich.
Kylotan
Danke @bummzack, ich habe den Beitrag bearbeitet, um es übersichtlicher und einfacher zu machen, die Genauigkeit zu erhöhen, indem ich einfach mehr Aufzählungswerte hinzufüge.
MichaelHouse
8
Wenn Sie sich mit Vektoren beschäftigen, sollten Sie grundlegende Vektoroperationen in Betracht ziehen, anstatt sie in Winkel in einem bestimmten Frame umzuwandeln.
Bei einem Abfragevektor vund einer Menge von Einheitsvektoren sist der am meisten ausgerichtete Vektor der Vektor s_i, der maximiert dot(v,s_i). Dies liegt daran, dass das für die Parameter festgelegte Skalarprodukt ein Maximum für Vektoren mit derselben Richtung und ein Minimum für Vektoren mit entgegengesetzten Richtungen aufweist, die sich gleichmäßig dazwischen ändern.
Dies verallgemeinert sich trivial in mehr als zwei Dimensionen, ist mit beliebigen Richtungen erweiterbar und leidet nicht an rahmenspezifischen Problemen wie unendlichen Verläufen.
In Bezug auf die Implementierung würde dies darauf hinauslaufen, ausgehend von einem Vektor in jeder Himmelsrichtung einen Bezeichner (enum, string, was auch immer Sie benötigen) zuzuordnen, der diese Richtung darstellt. Sie würden dann eine Schleife über Ihren Richtungssatz ziehen und den mit dem höchsten Skalarprodukt finden.
map<float2,Direction> candidates;
candidates[float2(1,0)]= E; candidates[float2(0,1)]= N;// etc.for each (float2 dir in candidates){float goodness = dot(dir, v);if(goodness > bestResult){
bestResult = goodness;
bestDir = candidates[dir];}}
Diese Implementierung kann auch ohne großen Aufwand verzweigungslos geschrieben und vektorisiert werden.
Promit
1
Ein mapmit float2als Schlüssel? Das sieht nicht sehr ernst aus.
Sam Hocevar
Es ist "Pseudo-Code" auf didaktische Weise. Wenn Sie panikoptimierte Implementierungen wünschen, ist GDSE wahrscheinlich nicht der richtige Ort für Ihre Copy-Pasta. Was die Verwendung von float2 als Schlüssel angeht, so kann ein float genau die ganzen Zahlen darstellen, die wir hier verwenden, und Sie können einen vollkommen guten Komparator für sie erstellen. Gleitkomma-Schlüssel sind nur dann ungeeignet, wenn sie spezielle Werte enthalten oder Sie versuchen, berechnete Ergebnisse nachzuschlagen. Das Durchlaufen einer assoziativen Sequenz ist in Ordnung. Ich hätte eine lineare Suche in einem Array verwenden können, aber es wäre nur sinnloses Durcheinander.
Lars Viklund
3
Eine Möglichkeit, die hier nicht erwähnt wurde, besteht darin, die Vektoren als komplexe Zahlen zu behandeln. Sie erfordern keine Trigonometrie und können sehr intuitiv zum Hinzufügen, Multiplizieren oder Runden von Rotationen verwendet werden, zumal Ihre Überschriften bereits als Zahlenpaare dargestellt sind.
Falls Sie mit ihnen nicht vertraut sind, werden die Richtungen in Form von a + b (i) ausgedrückt, wobei a die reale Komponente ist und b (i) die imaginäre. Wenn Sie sich die kartesische Ebene vorstellen, bei der X real und Y imaginär ist, wäre 1 östlich (rechts), ich wäre nördlich.
Hier ist der Schlüsselteil: Die 8 Himmelsrichtungen werden ausschließlich mit den Zahlen 1, -1 oder 0 für ihre realen und imaginären Komponenten dargestellt.Alles, was Sie tun müssen, ist, Ihre X-, Y-Koordinaten als Verhältnis zu reduzieren und beide auf die nächste ganze Zahl zu runden, um die Richtung zu erhalten.
NW (-1+ i) N (i) NE (1+ i)
W (-1)Origin E (1)
SW (-1- i) S (-i) SE (1- i)
Reduzieren Sie für die Konvertierung von Überschrift zu nächster Diagonale X und Y proportional, sodass der größere Wert genau 1 oder -1 ist. einstellen
Wenn Sie beide Komponenten von dem, was ursprünglich (10, -2) war, runden, erhalten Sie 1 + 0 (i) oder 1. Die nächste Richtung ist also Ost.
Das obige erfordert nicht die Verwendung einer komplexen Zahlenstruktur, aber wenn man sich diese als solche ansieht, ist es schneller, die 8 Himmelsrichtungen zu finden. Sie können Vektormathematik auf die übliche Weise ausführen, wenn Sie die Netzüberschrift von zwei oder mehr Vektoren erhalten möchten. (Als komplexe Zahlen addieren Sie nicht, sondern multiplizieren das Ergebnis.)
Das ist großartig, macht aber einen ähnlichen Fehler wie den, den ich in meinem eigenen Versuch gemacht habe. Die Antworten sind nah, aber nicht richtig. Der Grenzwinkel zwischen E und NE beträgt 22,5 Grad, dieser schneidet jedoch bei 26,6 Grad ab.
izb
Max(x, y)sollte sein Max(Abs(x, y)), für die negativen Quadranten zu arbeiten. Ich habe es ausprobiert und das gleiche Ergebnis wie bei izb erhalten - dies ändert die Kompassrichtung in den falschen Winkeln. Ich würde vermuten, dass es wechseln würde, wenn überschreitet Heading.y / Heading.x 0,5 (so dass der gerundete Wert von 0 auf 1 wechselt), was Arctan (0,5) = 26,565 ° ist.
27.
Eine andere Art, komplexe Zahlen zu verwenden, besteht darin, zu beobachten, dass die Multiplikation komplexer Zahlen eine Rotation beinhaltet. Wenn Sie eine komplexe Zahl konstruieren, die 1/8 einer Drehung um einen Kreis darstellt, bewegen Sie sich bei jeder Multiplikation um einen Oktanten. Sie könnten sich also fragen: Können wir zählen, wie viele Multiplikationen nötig waren, um von Osten in die aktuelle Richtung zu gelangen? Die Antwort auf "Wie oft müssen wir damit multiplizieren" ist ein Logarithmus . Wenn Sie nach Logarithmen für komplexe Zahlen suchen, wird atan2 verwendet. Das entspricht also letztendlich Ilmaris Antwort.
Höchstwahrscheinlich, weil Ihr Code keine Erklärung enthält. Warum ist das die Lösung und wie funktioniert es?
Vaillancourt
Hast du es gemacht?
Ray Tayek
Nein, und unter dem Namen der Klasse habe ich angenommen, dass Sie es getan haben und es hat funktioniert. Und das ist großartig. Aber Sie haben gefragt, warum die Leute abstimmen, und ich habe geantwortet. Ich habe nie angedeutet, dass es nicht funktioniert hat :)
Vaillancourt
-2
E = 0, NE = 1, N = 2, NW = 3, W = 4, SW = 5, S = 6, SE = 7
Im Moment ist dies nur eine Ansammlung von Charakteren, die wenig Sinn ergeben. Warum ist dies eine Lösung, die für die Frage funktionieren würde, wie funktioniert es?
Vaillancourt
Ich schreibe die Formel so wie ich sie geschrieben habe und sie funktioniert perfekt.
Dies gibt Ihnen Konstanten durch Verwendung von Bitfeldern:
// main direction constants
DIR_E =0x1
DIR_W =0x2
DIR_S =0x4
DIR_N =0x8// mixed direction constants
DIR_NW = DIR_N | DIR_W
DIR_SW = DIR_S | DIR_W
DIR_NE = DIR_N | DIR_E
DIR_SE = DIR_S | DIR_E
// calculating the direction
dir =0x0if(x >0) dir |= DIR_E
if(x <0) dir |= DIR_W
if(y >0) dir |= DIR_S
if(y <0) dir |= DIR_N
return dir
Eine leichte Leistungsverbesserung wäre, die <-checks in den else-Zweig der entsprechenden >-checks zu setzen, aber ich habe darauf verzichtet, weil dies die Lesbarkeit beeinträchtigt.
Entschuldigung, aber das gibt nicht genau die Antwort, die ich suche. Mit diesem Code wird nur "N" ausgegeben, wenn der Vektor genau nördlich ist, und NE oder NW, wenn x ein anderer Wert ist. Was ich brauche, ist die nächstgelegene Kompassrichtung. Wenn der Vektor z. B. näher an N als NW liegt, ergibt dies N.
izb 13.02.13
Würde dies tatsächlich die nächste Richtung angeben? Es scheint, dass ein Vektor von (0.00001.100) Ihnen Nordosten geben würde. edit: du hast mich geschlagen izb.
CiscoIPPhone
du hast nicht gesagt, dass du die nächste Richtung willst.
Philipp
1
Entschuldigung, das habe ich im Titel versteckt. Sollte im
Fragetext
1
Was ist mit der unendlichen Norm? Wenn Sie durch max (abs (vector.components)) dividieren, erhalten Sie einen normalisierten Vektor in Bezug auf diese Norm. Jetzt können Sie eine kleine Check-up-Tabelle schreiben, die auf if (x > 0.9) dir |= DIR_Eund dem Rest basiert . Es sollte besser sein als Phillipps Originalcode und ein bisschen billiger als die L2-Norm und atan2. Vielleicht, vielleicht auch nicht.
Antworten:
Am einfachsten ist es wahrscheinlich, den Winkel des Vektors mit
atan2()
zu berechnen, wie Tetrad in den Kommentaren angibt, und ihn dann zu skalieren und zu runden, z. B. (Pseudocode):Die
octant = round( 8 * angle / (2*PI) + 8 ) % 8
Zeile benötigt möglicherweise eine Erklärung. In so ziemlich allen Sprachen, die ich kenne, gibt dieatan2()
Funktion den Winkel im Bogenmaß zurück. Teilen Sie es durch 2 π wird es vom Bogenmaß in Bruchteile eines vollen Kreises umgewandelt und durch Multiplizieren mit 8 in Achtel eines Kreises umgewandelt, den wir dann auf die nächste ganze Zahl runden. Schließlich reduzieren wir es modulo 8, um den Wrap-Around zu erledigen, damit sowohl 0 als auch 8 korrekt nach Osten abgebildet werden.Der Grund für das
+ 8
, was ich oben übersprungen habe, ist, dass in einigen Sprachenatan2()
negative Ergebnisse (dh von - π bis + π statt von 0 bis 2 π ) zurückgegeben werden können und der Modulo-Operator (%
) definiert werden kann, um negative Werte für zurückzugeben negative Argumente (oder sein Verhalten für negative Argumente kann undefiniert sein). Das Hinzufügen8
(dh eine volle Umdrehung) zu der Eingabe vor dem Reduzieren stellt sicher, dass die Argumente immer positiv sind, ohne das Ergebnis auf andere Weise zu beeinflussen.Wenn Ihre Sprache keine bequeme Funktion zum Aufrunden der nächsten Zahl bietet, können Sie stattdessen eine Ganzzahlumwandlung mit Kürzung verwenden und dem Argument einfach 0,5 hinzufügen, wie folgt:
Beachten Sie, dass in einigen Sprachen bei der Standardkonvertierung von Float in Integer negative Eingaben eher in Richtung Null als nach unten gerundet werden. Dies ist ein weiterer Grund, um sicherzustellen, dass die Eingabe immer positiv ist.
Natürlich können Sie alle Vorkommen
8
in dieser Zeile durch eine andere Zahl ersetzen (z. B. 4 oder 16 oder sogar 6 oder 12, wenn Sie sich auf einer Hex-Karte befinden), um den Kreis in so viele Richtungen zu unterteilen. Passen Sie einfach die Enumeration / das Array entsprechend an.quelle
atan2(y,x)
nicht der Fall istatan2(x,y)
.atan2(x,y)
würde das auch funktionieren, wenn man stattdessen die Kompass-Überschriften im Uhrzeigersinn beginnend von Norden auflistet.octant = round(8 * angle / 360 + 8) % 8
quadtant = round(4 * angle / (2*PI) + 4) % 4
und mit Enum:{ E, N, W, S }
.Sie haben 8 Optionen (oder 16 oder mehr, wenn Sie eine noch feinere Präzision wünschen).
Verwenden Sie
atan2(y,x)
, um den Winkel für Ihren Vektor zu ermitteln.atan2()
funktioniert wie folgt:Also ergibt x = 1, y = 0 0 und es ist diskontinuierlich bei x = -1, y = 0 und enthält sowohl π als auch -π.
Jetzt müssen wir nur noch die Ausgabe von
atan2()
zuordnen, um sie mit der des oben angegebenen Kompasses abzugleichen.Die wahrscheinlich einfachste Implementierung ist eine inkrementelle Überprüfung der Winkel. Hier ist ein Pseudocode, der leicht geändert werden kann, um die Genauigkeit zu erhöhen:
Um die Genauigkeit zu erhöhen, fügen Sie einfach die Werte zur Richtungsaufzählung hinzu.
Der Algorithmus überprüft auf dem Kompass zunehmende Werte, um festzustellen, ob unser Winkel irgendwo zwischen dem Ort der letzten Überprüfung und der neuen Position liegt. Deshalb fangen wir bei -PI + increment / 2 an. Wir möchten unsere Schecks so ausgleichen, dass sie in jede Richtung den gleichen Abstand einschließen. Etwas wie das:
West ist zweigeteilt, da die Rückgabewerte von
atan2()
at West diskontinuierlich sind.quelle
atan2
. Beachten Sie jedoch, dass 0 Grad wahrscheinlich Ost und nicht Nord sind.angle >=
Schecks im obigen Code nicht; Wenn der Winkel beispielsweise kleiner als 45 ist, wurde der Norden bereits zurückgegeben, sodass Sie für die Ostprüfung nicht überprüfen müssen, ob der Winkel> = 45 ist. Ebenso brauchen Sie vor Ihrer Rückkehr nach Westen überhaupt keinen Scheck - es ist die einzige verbleibende Möglichkeit.if
Aussagen, wenn Sie 16 oder mehr Richtungen einschlagen möchten.Wenn Sie sich mit Vektoren beschäftigen, sollten Sie grundlegende Vektoroperationen in Betracht ziehen, anstatt sie in Winkel in einem bestimmten Frame umzuwandeln.
Bei einem Abfragevektor
v
und einer Menge von Einheitsvektorens
ist der am meisten ausgerichtete Vektor der Vektors_i
, der maximiertdot(v,s_i)
. Dies liegt daran, dass das für die Parameter festgelegte Skalarprodukt ein Maximum für Vektoren mit derselben Richtung und ein Minimum für Vektoren mit entgegengesetzten Richtungen aufweist, die sich gleichmäßig dazwischen ändern.Dies verallgemeinert sich trivial in mehr als zwei Dimensionen, ist mit beliebigen Richtungen erweiterbar und leidet nicht an rahmenspezifischen Problemen wie unendlichen Verläufen.
In Bezug auf die Implementierung würde dies darauf hinauslaufen, ausgehend von einem Vektor in jeder Himmelsrichtung einen Bezeichner (enum, string, was auch immer Sie benötigen) zuzuordnen, der diese Richtung darstellt. Sie würden dann eine Schleife über Ihren Richtungssatz ziehen und den mit dem höchsten Skalarprodukt finden.
quelle
map
mitfloat2
als Schlüssel? Das sieht nicht sehr ernst aus.Eine Möglichkeit, die hier nicht erwähnt wurde, besteht darin, die Vektoren als komplexe Zahlen zu behandeln. Sie erfordern keine Trigonometrie und können sehr intuitiv zum Hinzufügen, Multiplizieren oder Runden von Rotationen verwendet werden, zumal Ihre Überschriften bereits als Zahlenpaare dargestellt sind.
Falls Sie mit ihnen nicht vertraut sind, werden die Richtungen in Form von a + b (i) ausgedrückt, wobei a die reale Komponente ist und b (i) die imaginäre. Wenn Sie sich die kartesische Ebene vorstellen, bei der X real und Y imaginär ist, wäre 1 östlich (rechts), ich wäre nördlich.
Hier ist der Schlüsselteil: Die 8 Himmelsrichtungen werden ausschließlich mit den Zahlen 1, -1 oder 0 für ihre realen und imaginären Komponenten dargestellt.Alles, was Sie tun müssen, ist, Ihre X-, Y-Koordinaten als Verhältnis zu reduzieren und beide auf die nächste ganze Zahl zu runden, um die Richtung zu erhalten.
Reduzieren Sie für die Konvertierung von Überschrift zu nächster Diagonale X und Y proportional, sodass der größere Wert genau 1 oder -1 ist. einstellen
Wenn Sie beide Komponenten von dem, was ursprünglich (10, -2) war, runden, erhalten Sie 1 + 0 (i) oder 1. Die nächste Richtung ist also Ost.
Das obige erfordert nicht die Verwendung einer komplexen Zahlenstruktur, aber wenn man sich diese als solche ansieht, ist es schneller, die 8 Himmelsrichtungen zu finden. Sie können Vektormathematik auf die übliche Weise ausführen, wenn Sie die Netzüberschrift von zwei oder mehr Vektoren erhalten möchten. (Als komplexe Zahlen addieren Sie nicht, sondern multiplizieren das Ergebnis.)
quelle
Max(x, y)
sollte seinMax(Abs(x, y))
, für die negativen Quadranten zu arbeiten. Ich habe es ausprobiert und das gleiche Ergebnis wie bei izb erhalten - dies ändert die Kompassrichtung in den falschen Winkeln. Ich würde vermuten, dass es wechseln würde, wenn überschreitet Heading.y / Heading.x 0,5 (so dass der gerundete Wert von 0 auf 1 wechselt), was Arctan (0,5) = 26,565 ° ist.das scheint zu funktionieren:
quelle
E = 0, NE = 1, N = 2, NW = 3, W = 4, SW = 5, S = 6, SE = 7
f (x, y) = mod ((4-2 * (1 + Vorzeichen (x)) * (1-Vorzeichen (y ^ 2)) - (2 + Vorzeichen (x)) * Vorzeichen (y)
quelle
Wenn Sie eine Zeichenfolge möchten:
Dies gibt Ihnen Konstanten durch Verwendung von Bitfeldern:
Eine leichte Leistungsverbesserung wäre, die
<
-checks in den else-Zweig der entsprechenden>
-checks zu setzen, aber ich habe darauf verzichtet, weil dies die Lesbarkeit beeinträchtigt.quelle
if (x > 0.9) dir |= DIR_E
und dem Rest basiert . Es sollte besser sein als Phillipps Originalcode und ein bisschen billiger als die L2-Norm und atan2. Vielleicht, vielleicht auch nicht.