Hi,
folgendes Problem:
Im Kreis (0°-359°) wird in einer beliebigen Ausrichtung gestartet.
Von diesem Punkt aus wird ein Minimum (start-45°) und Maximum
(start+45°) berechnet. Soweit so gut.
Jetzt kommt eine Eingabe a: 0°-359°. Wie kann man feststellen, ob diese
Eingabe zwischen dem Minimum und Maximum liegt. Im normalen Zahlenraum
wäre das ja trivial: if(a > min && a < max) ...
Wie macht man das beim Kreis?
Danke
kreis schrieb:> Im Kreis (0°-359°) wird in einer beliebigen Ausrichtung gestartet.> Von diesem Punkt aus wird ein Minimum (start-45°) und Maximum> (start+45°) berechnet.
Keine Ahnung warum ein Minimum bei Start-45 und ein maximum bei Start+45
sein soll aber egal.
kreis schrieb:> Jetzt kommt eine Eingabe a: 0°-359°. Wie kann man feststellen, ob diese> Eingabe zwischen dem Minimum und Maximum liegt. Im normalen Zahlenraum> wäre das ja trivial: if(a > min && a < max) ...
Ebenfalls mit '<' und '>'. Du musst nur alle Werten die hereinkommen
oder die du berechnest normieren. Also auf einen Wert von 0 - 360 oder
-180 - +180 bringen.
Das mit dem Minimum ist Applikationsabhängig.
Die Werte kommen ja schon normiert rein, oder ich verstehe dich falsch.
Beispiel:
Start: 30°
Min: 30-45 = 344°
Max: 30+45 = 75°
Jetzt kommt zb 0° rein. Das lässt sich noch prüfen: min< 0 < max
Klappt aber bei 350° so nicht mehr: min < 350 !< max
U. B. schrieb im Beitrag #3158534:
> sein läßt, statt auf eine positive Gradzahl umzurechnen, dann "überlebt"> die Eigenschaft daß min < max ist und>> (min == -15) < (start == 30 ) < (max == 75)>> schaut dann doch gut aus.
Ein Winkel von 350° würde in diesem 90° Sektor liegen. Aber für 350 gilt
nicht
340 > min && 340 < max
> ...im Zweifel erzähl einfach ein bissl mehr vom Kontext, dann wird wohl> vielleicht noch deutlicher was Du brauchst...
Jep.
Die ganze Sache kann am Kreis tatsächlich sehr unangenehm sein.
Manchmal ist es möglich einen Schritt zurückzutreten, und geometrische
Operationen am Kreis von vorne herein gleich zu vermeiden. Kommt aber
auf die eigentliche Aufgabenstellung an.
Im Falle des TO wird es auf eine Fallunterscheidung rauslaufen, ob man
ausgehend von start die 0° für die Berechnung von min oder max
überschreiten musste oder nicht. Je nachdem muss dann auch der
Winkelvergleich anders ausfallen.
Aber wie gesagt: Gerade in der Geometrie lassen sich solche Dinge
vermeiden, indem man nicht über Winkel rechnet, sondern in die
Vektoralgebra mit Kreuz- und Skalarprodukt eintaucht.
Karl Heinz Buchegger schrieb:> Im Falle des TO wird es auf eine Fallunterscheidung rauslaufen, ob man> ausgehend von start die 0° für die Berechnung von min oder max> überschreiten musste oder nicht. Je nachdem muss dann auch der> Winkelvergleich anders ausfallen.
Ohne das jetzt komplett durchdacht zu haben:
Du rechnest dir min und max gar nicht explizit aus, sondern merkst dir
nur start.
Was du, anschaulich erklärt, dann mit deinem zu untersuchenden Winkel
machst ist folgendes:
Stell dir vor, du hättest eine drehbare Pappscheibe. Auf der markierst
du erst mal den Winkel 'start'. Dann trägst du auch noch den zu
untersuchenden Winkel ein. Anschliessend drehst du die Scheibe so, dass
'start' auf 0° zu liegen kommt und siehst dir an, ob der dadurch
ebenfalls mitgedrehte zu untersuchende WInkel im Bereich +45° bis -45°
zu liegen kommt.
Also
// Scheibe drehen
verdreht = winkel - start
// den so verdrehten Winkel wieder auf 0 ... 360 normieren
while verdreht > 360
verdreht -= 360
while verdreht < 0
verdreht += 360
// und feststellen ob der verdrehte Winkel im 90° Sektor liegt
if( verdreht < 45 && verdreht > (360-45) )
.... liegt drinnen
Ich denke das müsste klappen, habs aber nicht ausprobiert.
Wenn dir die Abfrage zu seltsam vorkommt (obwohl sie ganz logisch ist,
wenn man sich die Sache aufzeichnet), kannst du auch den verdrehten
Winkel auf -180 bis +180 normieren. Dann wird die Abfrage zu
while verdreht > 180
verdreht -= 360
while verdreht < -180
verdreht += 360
if( verdreht > -45 && verdreht < +45 )
...
Karl Heinz Buchegger schrieb:> // und feststellen ob der verdrehte Winkel im 90° Sektor liegt> if( verdreht < 45 && verdreht > (360-45) )> .... liegt drinnen>> Ich denke das müsste klappen, habs aber nicht ausprobiert.
Eher nicht. Es dürfte selten vorkommen, daß der Wert gleichzeitig
kleiner als 45 und größer als 360-45 ist. Ich würde deshalb auch die
Normierung auf +/-180° vorschlagen, da es etwas intuitiver ist.
Rolf Magnus schrieb:> Karl Heinz Buchegger schrieb:>> // und feststellen ob der verdrehte Winkel im 90° Sektor liegt>> if( verdreht < 45 && verdreht > (360-45) )>> .... liegt drinnen>>>> Ich denke das müsste klappen, habs aber nicht ausprobiert.>> Eher nicht. Es dürfte selten vorkommen, daß der Wert gleichzeitig> kleiner als 45 und größer als 360-45 ist.
Shit.
Du hast natürlich recht. Da müsste ein Oder rein.
if( verdreht < 45 || verdreht > (360-45) )
Kann man nicht intern einfach mit einen Ofset arbeiten?
Ich würde da einfach immer 720 oder auch gleich 1000 dazuadieren.
Da bleibt man immer im positiven Bereich.
Selbst wenn Min = Start -359 und sogar Start selber = -359 ist
Jürgen D. schrieb:> Kann man nicht intern einfach mit einen Ofset arbeiten?> Ich würde da einfach immer 720 oder auch gleich 1000 dazuadieren.> Da bleibt man immer im positiven Bereich.
Ob du den Durchgang durch den 0-Winkel jetzt bei 0 oder 360 hast, spielt
keine Rolle. Das Problem bleibt weiterhin, dass du jeden Winkel durch
beliebige Vielfache von Winkel + n*360 ausdrücken kannst. Und damit hast
du dann das Problem, dass dein Minimum aus StartWinkel-45 und
Startwinkel+45 numerisch größer als das Maximum sein kann.
Bei solchen Sachen: Ausnahmslos immer mit konkreten Zahlenwerten
durchprobieren und dabei nicht nur auf den Fall achten, in dem alles wie
vorgesehen funktioniert, sondern speziell auch versuchen die Systematik
zu Fall zu bringen. Meist wird man dabei recht schnell fündig.
Das lässt sich durch anderes "Verdrehen" vereinfachen.
Die von Karl Heinz eingebrachte Pappscheibe wird nicht so verdreht, daß
"Start" auf 0° zu liegen kommt, sondern daß "Start - 45°" auf 0° zu
liegen kommt.
Um zu testen, ob der gewünschte Winkel im Segment [Start - 45°] bis
[Start + 45°] liegt, muss vom gewünschten Winkel also "Start - 45°"
abgezogen werden. Das Ergebnis kann nun auf 360° normiert werden - ist
es negativ, wird so lange 360 addiert, bis es positiv ist, ist es größer
als 360, wird so lange 360 abgezogen, bis es kleiner als 360 ist.
Damit dieses Resultat nun im Testsegment zu liegen kommt, muss es also
kleiner sein als 90°.
Beispiel:
Start beträgt 75°, der zu testende Winkel beträgt 713°.
Das Bezugssystem wird um 75° - 45° gedreht, also um 30°. Diese 30°
werden von den 713° abgezogen, also ergeben sich 683°.
Das ist noch etwas größer als 360°, die werden also auch noch davon
abgezogen.
Resultat sind 323°. Das ist größer als 90°, also gibt es keinen Treffer.
Zweites Beispiel:
Der zu testende Winkel beträgt -323°
Durch die Rotation des Bezugssystemes werden daraus -353°.
Da das negativ ist, werden 360° addiert, was 7° ergibt.
Das ist größer als 0°, und kleiner als 90° -> Treffer.
Rufus Τ. Firefly schrieb:> Das lässt sich durch anderes "Verdrehen" vereinfachen.>> Die von Karl Heinz eingebrachte Pappscheibe wird nicht so verdreht, daß> "Start" auf 0° zu liegen kommt, sondern daß "Start - 45°" auf 0° zu> liegen kommt.
gute Idee!
Ich hab mich zu sehr auf die Symetrie um 0 herum gestürzt.
kreis schrieb:> Das funktioniert noch besser - danke! Zumal in meiner Anwendung die> Winkel sich nur zwischen 0 und 359 bewegen können
schon klar.
Aber durch ein Additionen und Subtraktionen bist du schnell mal aus dem
Bereich draussen.
Nimm start mal mit 350 an und dann teste ob 10 deinen Test bestehen
wird. Du wirst negative Zwischenergebnisse kriegen.
Daher auch der Rat, sowas immer mit konkreten Zahlenwerten am Papier
durchzuprobieren. Nach den ersten paar selbst durchgerechneten (und
durchüberlegten) Beispielen wird schnell klar, welche Zwischenergebnisse
Probleme machen werden - wie die Zahlenkonstellation sein muss, damit
man zwischendurch unangenehme Zwischenergebnisse kriegt.
Geht in die gleiche Richtung, deswegen frage ich mal auch hier:
Wenn eine Eingabe in Grad kommt, wie kann man feststellen, ob der
kürzere Weg links oder rechts herum ist?
Ich hab´s im Moment so gelöst, bin aber nicht sicher, obs richtig ist:
Start= aktuelle Position
Max= start+180
offset=0
if(max>360) max=max-360
if(start>max) offset=360-start
ziel=offset+eingabe
if(ziel<start) DREHE LINKS
if(ziel>start && ziel>max) DREHE LINKS
if(ziel>start && ziel<max) DREHE RECHTS
auf Papier scheints zu klappen, evtl findet jemand da einen Fehler?
kreis schrieb:> Geht in die gleiche Richtung, deswegen frage ich mal auch hier:>> Wenn eine Eingabe in Grad kommt, wie kann man feststellen, ob der> kürzere Weg links oder rechts herum ist?
Wenn ich nachher sowieso auf Vektoren gehe, dann wandle ich die Grad
sofort mal in einen Vektor um. Das Vorzeichen des Kreuzproduktes von
Zielvektor und Startvektor verrät mir dann die gesuchte Information.
Ansonsten: Differenz bilden. Auf 0..360 normieren. Bei 180 ist die
Grenze, in welcher Richtung der kürzere Bogen liegt.
PS: "Differenz bilden" ist im Grunde schon wieder mal nichts anderes als
die bewusste Pappscheibe, die so gedreht wird, dass eine Markierung bei
0 zu liegen kommt und die andere Markierung mitgedreht wird.
Anschaulich: wenn dann die andere Markierung zwischen 0 und 180 liegt,
dann ist der Bogen gegen den Uhrzeiger kürzer, ansonsten der andere.
Edit:
Dieses Konzept: verändere die Situation, so dass ein wesentlicher
Parameter zu 0 wird (0-Lage, 0-Rotation)
findet sich oft in der geometrischen Arbeit. Du solltest seine
Möglichkeiten nicht unterschätzen! Überleg dir, ob dein 'Problem'
besonders einfach wird, wenn das Problemumfeld in 'Ausgangslage' (also
0-Koordinaten, 0-Lage, 0-Rotation) vorliegen würde. Wenn du da sofort
eine (zumindest konzeptionell richtige) Lösung angeben kannst, dann ist
genau das der Weg, den man geht.
Zb: Schnittpunkte zwischen 2 beliebigen Kreisen in der Ebene finden.
Hätte einer der beiden Kreise seinen Mittelpunkt im Koordinatenursprung,
dann wird das Problem einfacher zu lösen. Liegt der Mittelpunkt des
anderen Kreises dann auch noch zb auf der X-Achse, dann vereinfacht sich
alles nochmal. Im allgemeinen Fall, mit beliebigen Mittelpunkten werden
die Gleichungen ekelhaft, aber durch Verschieben eines Kreises in den
Ursprung wird alles wieder einfacher handhabbar. Natürlich muss man die
gefundenen Schnittpunkte dann wieder zurückverschieben. Aber im
Vergleich zu den ekelhaften Gleichungen im allgemeinen Fall sind das
Peanuts.