Eckpunkt exzentrisch rotierender Rechtecke

Anfängerfragen zum Programmieren mit PureBasic.
Syntacks_Error
Beiträge: 107
Registriert: 08.03.2009 16:08

Eckpunkt exzentrisch rotierender Rechtecke

Beitrag von Syntacks_Error »

Hier gleich noch eine Frage:

Ich habe Rechtecke, die rotieren, und zwar praktischerweise nur um 90, 180 und 270 Grad.

ALso: Rechteck z.B. 10 * 6 (Immer gerade Werte). Die Eckpunkte (x/y) sind dann links 0/0, 0/6 (yAchse von unten nach oben) und rechts 10/0 und 10/6.
Zentrum wäre x = 5, y = 3.

Rotieren tut das Mistteil aber nicht um den Mittelpunkt 5 und 3, sondern z.B. um x = 6 und y = 2 (auch immer gerade Werte), wobei das natürlich unterschiedlich ist. Manche Rechtecke sind auch nur in einer Rotationsaxe exzentrisch.

Was ich brauche, sind die Eckpunkte des Rechtecks nach einer Rotation. Herauskommen müssen dabei gleichfalls grade Werte, grobe Näherung genügt, vieleicht geht das auch ohne Winkelfunktion?

Meine Versuchsrechtecke aus Papier haben mir da beim Verständnis leider nicht weitergeholfen. Millimeterpapier wäre vielleicht hilfreich gewesen.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Eckpunkt exzentrisch rotierender Rechtecke

Beitrag von NicTheQuick »

Konzentrier dich mal auf eine Ecke und schau in welchem Quadrat diese sich bei 90° Drehungen bewegt.
Bild
Benutzeravatar
helpy
Beiträge: 635
Registriert: 29.08.2004 13:29

Re: Eckpunkt exzentrisch rotierender Rechtecke

Beitrag von helpy »

NicTheQuick hat geschrieben:Konzentrier dich mal auf eine Ecke und schau in welchem Quadrat diese sich bei 90° Drehungen bewegt.
;-) Da muss man nur noch addieren/subtrahieren, um die neuen Eckpunkte zu bekommen!
Windows 10
PB Last Final / (Sometimes testing Beta versions)
Syntacks_Error
Beiträge: 107
Registriert: 08.03.2009 16:08

Re: Eckpunkt exzentrisch rotierender Rechtecke

Beitrag von Syntacks_Error »

Sooo trivial ist das nun auch nicht. Addieren und substrahieren bei nur einer exzentrischen Achse kriege ich auch hin. Aber die Exzentriken können auf beiden Achsen links, rechts, oberhalb oder unterhalb des Mittelpunktes liegen. Insgsamt gibt es wohl acht Möglichkeiten. Das verwirrt mich. Was addiere oder substrahiere ich da so, dass eine Formel herauskommt?

Und was mache ich, wenn einer den Rechtecken von einer Welt außerhalb der rechten Winkel erzählt und die dann doch damit ankommen? Gibt es dafür etwas Griffiges?
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Eckpunkt exzentrisch rotierender Rechtecke

Beitrag von ccode_new »

Hallo!

Kann das mal jemand überprüfen.

Ist das so korrekt ?

Code: Alles auswählen

If InitSprite() = 0 Or InitKeyboard() = 0
  MessageRequester("Error", "Geht nicht!", 0)
  End
EndIf

;Rechtecke rotieren ( oder das Leben in einem Kreis ;) )

Structure TKoord
  x.i
  y.i
EndStructure

Structure TEckpunkte
  A.TKoord
  B.TKoord
  C.TKoord
  D.TKoord
EndStructure

Global *Points.TEckpunkte

Global Grad = 0

;x = X-Position im Koordinatensystem
;y = Y-Position im Koordinatensystem
;b = Breite des Rechtecks
;h = Höhe des Rechtecks
;a = Drehwinkel in Grad (also: 0, 45, 90, ...)
;rx = Rotationspunkt X
;ry = Rotationspunkt Y

;A-------C
;|       |
;|       |
;B-------D

Procedure RotateRect(x, y, l, b, a, rx=0, ry=0)
  Protected pa.TKoord, pb.TKoord, pc.TKoord, pd.TKoord
  Protected *RectPoints.TEckpunkte
  *RectPoints = AllocateMemory(SizeOf(TEckpunkte))
  
  If (rx < 0) Or (rx > l) Or (ry < 0) Or (ry > b)
    Debug "Der Rotationspunkt muss im Rechteck liegen."
    ProcedureReturn -1
  EndIf
  
  ;Die Eckpunkte berechnen
  pa\x = (rx+(0-rx)*Cos(Radian(a))-(0-ry)*Sin(Radian(a)))+x
  pa\y = (ry+(0-rx)*Sin(Radian(a))+(0-ry)*Cos(Radian(a)))+y
  pb\x = (rx+(0-rx)*Cos(Radian(a))-(b-ry)*Sin(Radian(a)))+x
  pb\y = (ry+(0-rx)*Sin(Radian(a))+(b-ry)*Cos(Radian(a)))+y
  pc\x = (rx+(l-rx)*Cos(Radian(a))-(0-ry)*Sin(Radian(a)))+x
  pc\y = (ry+(l-rx)*Sin(Radian(a))+(0-ry)*Cos(Radian(a)))+y
  pd\x = (rx+(l-rx)*Cos(Radian(a))-(b-ry)*Sin(Radian(a)))+x
  pd\y = (ry+(l-rx)*Sin(Radian(a))+(b-ry)*Cos(Radian(a)))+y
  
  *RectPoints\A = pa : *RectPoints\B = pb
  *RectPoints\C = pc : *RectPoints\D = pd
  
  ProcedureReturn *RectPoints
EndProcedure

;Rechteck rotieren
*Points = RotateRect(0, 0, 10, 6, 90, 5, 3)
Debug "Punkt A: (" + Str(*Points\A\x) + "," + Str(*Points\A\y) + ")"
Debug "Punkt B: (" + Str(*Points\B\x) + "," + Str(*Points\B\y) + ")"
Debug "Punkt C: (" + Str(*Points\C\x) + "," + Str(*Points\C\y) + ")"
Debug "Punkt D: (" + Str(*Points\D\x) + "," + Str(*Points\D\y) + ")"

Procedure DrawBox(*P.TEckpunkte)
  If StartDrawing(ScreenOutput())
    LineXY((*P\A\x), (*P\A\y), (*P\B\x), (*P\B\y), RGB(255, 0, 155))
    LineXY((*P\B\x), (*P\B\y), (*P\D\x), (*P\D\y), RGB(255, 0, 155))
    LineXY((*P\C\x), (*P\C\y), (*P\D\x), (*P\D\y), RGB(255, 0, 155))
    LineXY((*P\C\x), (*P\C\y), (*P\A\x), (*P\A\y), RGB(255, 0, 155))
    StopDrawing()
  EndIf
EndProcedure

If OpenWindow(0, 0, 0, 300, 300, "Rechteck-Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  If OpenWindowedScreen(WindowID(0), 0, 0, 300, 300)
    AddWindowTimer(0, 123, 16)
  Else
    MessageRequester("Fehler", "Geht nicht!", 0)
    End
  EndIf
  Repeat
    Repeat
      Event = WindowEvent()
      Select Event 
        Case #PB_Event_CloseWindow
          End
        Case #PB_Event_Timer
          If EventTimer() = 123
            ExamineKeyboard()
            If Not KeyboardPushed(#PB_Key_P)
              If Grad < 360
                Grad + 1
              ElseIf Grad = 360
                Grad = 0
              EndIf
              FlipBuffers() 
              ClearScreen(RGB(0, 0, 0))
              *Points = RotateRect(WindowWidth(0)/2-50, WindowHeight(0)/2-30, 100, 60, Grad, 50, 30)
              Debug "Aktueller Winkel: "+Str(Grad)
              Debug "Punkt A: (" + Str(*Points\A\x) + "," + Str(*Points\A\y) + ")"
              Debug "Punkt B: (" + Str(*Points\B\x) + "," + Str(*Points\B\y) + ")"
              Debug "Punkt C: (" + Str(*Points\C\x) + "," + Str(*Points\C\y) + ")"
              Debug "Punkt D: (" + Str(*Points\D\x) + "," + Str(*Points\D\y) + ")"
              DrawBox(*Points)
            EndIf
          EndIf
      EndSelect
    Until Event = 0
    Delay(10)
  ForEver
EndIf
Zuletzt geändert von ccode_new am 20.05.2018 15:40, insgesamt 1-mal geändert.
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Benutzeravatar
helpy
Beiträge: 635
Registriert: 29.08.2004 13:29

Re: Eckpunkt exzentrisch rotierender Rechtecke

Beitrag von helpy »

Wenn es nur um 90°, 180° und 270° Drehung geht, dann reicht addieren/subtrahieren.
Hier das Rotieren eines Punktes p um den Dreh-/Rotationspunkt r:

Code: Alles auswählen

EnableExplicit

Enumeration enuRotate
	; clockwise
	#ROTATE_090_cw 
	#ROTATE_180_cw
	#ROTATE_270_cw
	; counter-clockwise
	#ROTATE_090_ccw = #ROTATE_270_cw
	#ROTATE_180_ccw = #ROTATE_180_cw
	#ROTATE_270_ccw = #ROTATE_090_cw
EndEnumeration

Procedure RotatePoint(*p.Point, *r.Point, Rotation)
	Protected pNew.Point, dx, dy
	dx = *p\x - *r\x
	dy = *p\y - *r\y
	
	Select Rotation
		Case #ROTATE_090_cw
			pNew\x = *r\x + dy
			pNew\y = *r\y - dx
			
		Case #ROTATE_180_cw
			pNew\x = *r\x - dx
			pNew\y = *r\y - dy
			
		Case #ROTATE_270_cw
			pNew\x = *r\x - dy
			pNew\y = *r\y + dx
			
		Default : ProcedureReturn
	EndSelect
	
	CopyStructure(@pNew, *p, Point)
EndProcedure

Define p.Point
p\x = 0
p\y	= 0

Define r.Point
r\x = 5
r\y = 3

Debug Str(p\x) + " / " + Str(p\y)

RotatePoint(p, r, #ROTATE_090_cw)
Debug Str(p\x) + " / " + Str(p\y)

RotatePoint(p, r, #ROTATE_090_cw)
Debug Str(p\x) + " / " + Str(p\y)

RotatePoint(p, r, #ROTATE_090_cw)
Debug Str(p\x) + " / " + Str(p\y)

RotatePoint(p, r, #ROTATE_090_cw)
Debug Str(p\x) + " / " + Str(p\y)
Windows 10
PB Last Final / (Sometimes testing Beta versions)
Syntacks_Error
Beiträge: 107
Registriert: 08.03.2009 16:08

Re: Eckpunkt exzentrisch rotierender Rechtecke

Beitrag von Syntacks_Error »

Werden da wirklich die Eckpunkte ausgegeben? Bei der Eingabe
RotateRect(0, 0, 10, 6, 0,4,3) (x-Roatationspunkt 1 links vom Zentrum, aber keine Rotation) wird ausgeben:
Punkt A: (1,0)
Punkt B: (9,0)
Punkt C: (1,6)
Punkt D: (9,6)

Ich hätte erwartet, dass gar nichts passiert, es gab ja noch keine Rotation. Auch ist das Rechteck jetzt nur noch 8 lang statt 10

Bei RotateRect(0, 0, 10, 6, 90,5,3) - 90 Grad rechts um das Zentrum - wird ausgegeben:
Punkt A: (8,-2)
Punkt B: (8,8)
Punkt C: (2,-2)
Punkt D: (2,8)

Ich hätte erwartet, das A bei 5,2 liegt und B (vormals rechte untere Ecke) entsprechend bei 2,-5. Der Punkt geht ja unter die y-Nulllinie.

Oder verstehe ich die Ausgabe falsch?
Benutzeravatar
Muttonhead
Beiträge: 20
Registriert: 25.06.2017 14:06
Computerausstattung: I7

Re: Eckpunkt exzentrisch rotierender Rechtecke

Beitrag von Muttonhead »

Code: Alles auswählen

                                  y
                                  ^
                                  |
                                  |
                                  |
                    o -2,3        -
                                  |
                                  |
                                  -                    o 3,2
                                  |
                                  |
                                  -
                                  |
                                  |
------|------|------|------|------+------|------|------|------|------|------|------> x
                                  |
                                  |
                                  -
                                  |
                                  |
      o -3,-2                     -
                                  |
                                  |
                                  -             o 2,-3
                                  |
                                  |
Drehrichtung gegen Uhrzeiger

90 grd:
Xgedreht= Y * -1
Ygedreht= X

180 grd:
Xgedreht= Y * -1
Ygedreht= X * -1

270 oder -90 grd:
Xgedreht= Y
Ygedreht= X * -1

Jeder dieser vier Punkte im Koordinatensystem ist das um 90 grad gedrehte Abbild seines Nachbarn
...vielleicht bin ich aber auch am Thema total vorbei

Muttonhead
PureBasic 5.62 (Windows 10 Home - x64) | i7 7700HQ | 32GB | HD Graphics 630 / GeForce GTX 1060 Max-Q
Benutzeravatar
helpy
Beiträge: 635
Registriert: 29.08.2004 13:29

Re: Eckpunkt exzentrisch rotierender Rechtecke

Beitrag von helpy »

Dieser Ansatz gilt nur für die Drehung um den Nullpunkt!

Das ist falsch:
Muttonhead hat geschrieben:180 grd:
Xgedreht= Y * -1
Ygedreht= X * -1
Richtig wäre:
180 grd:
Xgedreht= X * -1
Ygedreht= Y * -1
Drehung eines Punktes P um einen beliebigen Punkt R:
  1. Nullpunkt des Koordinatensystems in Punkt R verschieben:

    Code: Alles auswählen

    PXnull = PX - RX
    PYnull = PY - RY
  2. Punkt P0 drehen:

    Code: Alles auswählen

    Drehung um 90° im Uhrzeigersinn bzw. 270° gegen Uhrzeigersinn:
    PXnull_gedreht = PYnull
    PYnull_gedreht = -PXnull
    
    Drehung um 90° gegen Uhrzeigersinn bzw. 270° im Uhrzeigersinn:
    PXnull_gedreht = -PYnull
    PYnull_gedreht = PXnull
    
    Drehung um 180°:
    PXnull_gedreht = -PXnull
    PYnull_gedreht = -PYnull
  3. Nullpunkt des Koordinatensystem wieder zurück verschieben:

    Code: Alles auswählen

    PXgedreht = PXnull_gedreht + RX
    PYgedreht = PYnull_gedreht + RY
Die drei Schritte kann man zusammenfassen:

Code: Alles auswählen

Drehung um 90° im Uhrzeigersinn bzw. 270° gegen Uhrzeigersinn:
PXgedreht = (PY - RY) + RX
PYgedreht = -(PX - RX) + RY

Drehung um 90° gegen Uhrzeigersinn bzw. 270° im Uhrzeigersinn:
PXgedreht = -(PY - RY) + RX
PYgedreht = (PX - RX) + RY

Drehung um 180°:
PXgedreht = -(PX - RX) + RX
PYgedreht = -(PY - RY) + RY
Und noch weiter vereinfacht:

Code: Alles auswählen

dx = PX - RX
dy = PY - RY

Drehung um 90° im Uhrzeigersinn bzw. 270° gegen Uhrzeigersinn:
PXgedreht = RX + dy
PYgedreht = RY - dx

Drehung um 90° gegen Uhrzeigersinn bzw. 270° im Uhrzeigersinn:
PXgedreht = RX - dy
PYgedreht = RY + dx

Drehung um 180°:
PXgedreht = RX - dx
PYgedreht = RY - dy
Windows 10
PB Last Final / (Sometimes testing Beta versions)
Benutzeravatar
Muttonhead
Beiträge: 20
Registriert: 25.06.2017 14:06
Computerausstattung: I7

Re: Eckpunkt exzentrisch rotierender Rechtecke

Beitrag von Muttonhead »

Richtig wäre:

180 grd:
Xgedreht= X * -1
Ygedreht= Y * -1
Hast vollkommen recht :)
Mutton
PureBasic 5.62 (Windows 10 Home - x64) | i7 7700HQ | 32GB | HD Graphics 630 / GeForce GTX 1060 Max-Q
Antworten