Forum: PC-Programmierung Rechnen mit Gradzahlen


von kreis (Gast)


Lesenswert?

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

von Udo S. (urschmitt)


Lesenswert?

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.

von kreis (Gast)


Lesenswert?

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

von Heinervdm (Gast)


Lesenswert?

Wenn das Ergebnis kleiner als 0 ist, dann addierst du 360 zu deinem 
Ergebnis dazu und wenn es größer als 360 ist ziehst du 360 ab.
Ganz einfach.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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 )
     ...

von Rolf M. (rmagnus)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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) )

von kreis (Gast)


Lesenswert?

Hi,

danke für die Tipps. Die Idee mit der Drehung finde ich gut - probiere 
ich gleich mal aus!

von Jürgen D. (poster)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von kreis (Gast)


Lesenswert?

Das funktioniert noch besser - danke! Zumal in meiner Anwendung die 
Winkel sich nur zwischen 0 und 359 bewegen können

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Vuvuzelatus (Gast)


Lesenswert?

Eine mögliche Codierung dieser Bedingung:
1
((f(w-wmin)>0) & (f(w-wmax)<0)) | ((f(w-wmin+2*pi)>0) & (f(w-wmax+2*pi)<0))

wobei w den Testwinkel bezeichnet und die Funktion f definiert ist als
1
f(x) := x - 4*pi*Round(x/(4*pi))

von kreis (Gast)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.