Rotierte Box-Mausklick Abrage

Für allgemeine Fragen zur Programmierung mit PureBasic.
Lambda
Beiträge: 526
Registriert: 16.06.2011 14:38

Rotierte Box-Mausklick Abrage

Beitrag von Lambda »

Nachdem man ein Bild drehen kann verändert sich die Kollisionsbox. Was ohne Rotation noch einfach ist indem man die Koordinaten mit der Maus mit der der Box und dessen Breite sowie Höhe vergleicht.

Wie prüfe ich jetzt ob die Maus innerhalb der rotierten Box ist? (Bild wird durch GDI+ gezeichnet)
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Rotierte Box-Mausklick Abrage

Beitrag von Danilo »

Du nimmst Deine Mauskoordinaten (x,y) und drehst diese dann um den gleichen Drehpunkt
wie das Bild, nur Rückwärts, also um "-Grad_um_die_das_Bild_gedreht_wurde".
Dann vergleichst Du diese zurückgedrehten Koordinaten (x,y) mit den ungedrehten
Bildkoordinaten.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7039
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Rotierte Box-Mausklick Abrage

Beitrag von STARGÅTE »

Das gleiche wie Danilo sagt, nur etwas anders formuliert:

Du hast dein Bild ja verschoben (es ist nicht bei 0,0) und gedreht (um einen Rotationspunkt).

Wenn du nun mit den Mauskoordinaten die gleichen Transformationen rückwärts machst,
also erst zurückdrehen und dann noch zurückschieben,
dann kannst du diese neuen Koordinaten direkt mit der Bildgröße vergleichen.

Hier n Prozedur zum Drehen:

Code: Alles auswählen

Structure PointF
	X.f
	Y.f
EndStructure

Procedure Rotate(*PointF.PointF, Angle.f, *Center.PointF=#Null)
	Protected X.f, Y.f
	Protected Sin.f = Sin(Radian(Angle)), Cos.f = Cos(Radian(Angle))
	If *Center
		X = *PointF\X - *Center\X
		Y = *PointF\Y - *Center\Y
	EndIf
	*PointF\X = Cos*X - Sin*Y
	*PointF\Y = Sin*X + Cos*Y
	If *Center
		*PointF\X + *Center\X
		*PointF\Y + *Center\Y
	EndIf
	ProcedureReturn *PointF
EndProcedure

Define Mouse.PointF  : Mouse\X = 200  : Mouse\Y = 300
Define Center.PointF : Center\X = 300 : Center\Y = 300

Rotate(@Mouse, 90, @Center)

Debug "nach einer Drehung um 90°:"
Debug Mouse\X
Debug Mouse\Y
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Rotierte Box-Mausklick Abrage

Beitrag von Danilo »

Hier mal visuell:

Code: Alles auswählen

Structure POINTF
    x.f : y.f
EndStructure

Procedure RotatePoint(*center.POINTF, *point.POINTF, angle.f, *result.POINTF)
    *result\x = (*point\x-*center\x) * Cos(angle) - (*point\y-*center\y) * Sin(angle) + *center\x
    *result\y = (*point\x-*center\x) * Sin(angle) + (*point\y-*center\y) * Cos(angle) + *center\y
EndProcedure

OpenWindow(0,0,0,800,600,"Drehung",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CanvasGadget(0,0,0,800,600)

If StartDrawing(CanvasOutput(0))
    Define.POINTF p, p2, center
    
    center\x = 400
    center\y = 300
    
    p\x = 500
    p\y = 300

    Circle(center\x,center\y,2,RGB(0,0,0))

    Circle(p\x,p\y,2,RGB(0,0,0))

    For degree = 0 To 250 Step 5
        RotatePoint(center,p,Radian(degree),p2)
        Circle(p2\x,p2\y,2,RGB(degree,0,0))
    Next

    StopDrawing()
EndIf


Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow
Du mußt also nur ein RotatePoint(center,mausXY,Radian(-degree),resultat) machen.
Aber wie STARGÅTE anmerkte, mußt Du vor dem Vergleich noch BildX und BildY
von resultat\x und \y abziehen.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Lambda
Beiträge: 526
Registriert: 16.06.2011 14:38

Re: Rotierte Box-Mausklick Abrage

Beitrag von Lambda »

Ok, danke euch beiden das hat mir geholfen :D
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Rotierte Box-Mausklick Abrage

Beitrag von Danilo »

cOoki3druqs hat geschrieben:Ok, danke euch beiden das hat mir geholfen :D
Zu spät, aber hier trotzdem noch ein komplettes Beispiel mit rotierter Box:

Code: Alles auswählen

Structure POINTF
    x.f : y.f
EndStructure

Procedure RotatePoint(*center.POINTF, *point.POINTF, angle.f, *result.POINTF)
    *result\x = (*point\x-*center\x) * Cos(angle) - (*point\y-*center\y) * Sin(angle) + *center\x
    *result\y = (*point\x-*center\x) * Sin(angle) + (*point\y-*center\y) * Cos(angle) + *center\y
EndProcedure

Procedure DrawRotatedRect(*center.POINTF,*rect.RECT,angle.f,color=0)
    Protected.POINTF p1,p2,p3,p4
    Dim points.POINTF(4)
    points(1)\x = *rect\left
    points(1)\y = *rect\top
    points(2)\x = *rect\right
    points(2)\y = *rect\top
    points(3)\x = *rect\right
    points(3)\y = *rect\bottom
    points(4)\x = *rect\left
    points(4)\y = *rect\bottom

    RotatePoint(*center,@points(1),angle,p1)
    RotatePoint(*center,@points(2),angle,p2)
    RotatePoint(*center,@points(3),angle,p3)
    RotatePoint(*center,@points(4),angle,p4)
    
    LineXY(p1\x,p1\y,p2\x,p2\y,color)
    LineXY(p2\x,p2\y,p3\x,p3\y,color)
    LineXY(p3\x,p3\y,p4\x,p4\y,color)
    LineXY(p4\x,p4\y,p1\x,p1\y,color)
EndProcedure

degree = 45

OpenWindow(0,0,0,800,600,"Drehung",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CanvasGadget(0,0,0,800,600)

If StartDrawing(CanvasOutput(0))
    Define.POINTF center
    Define.RECT   rect
    
    center\x = 400
    center\y = 300
    
    rect\left = 300
    rect\right= 500
    rect\top  = 200
    rect\bottom = 400
    
    Box(0,0,rect\right-rect\left,rect\bottom-rect\top,0)
    
    DrawRotatedRect(center,rect,Radian(degree))

    StopDrawing()
EndIf


Repeat
    Select WaitWindowEvent()
        Case #PB_Event_CloseWindow : End
        Case #PB_Event_Gadget
            If EventGadget()=0
                If EventType()=#PB_EventType_MouseMove
                   Define.POINTF mouse, result
                   
                   ; Mauskoordinaten holen
                   mouse\x = GetGadgetAttribute(0,#PB_Canvas_MouseX)
                   mouse\y = GetGadgetAttribute(0,#PB_Canvas_MouseY)

                   ; Mauskoordinaten zurück rotieren
                   RotatePoint(center,mouse,Radian(-degree),result)
                   
                   ; checken ob (zurück-rotierte) Mauskoordinaten in der (unrotierten!) Box
                   If result\x >= rect\left And result\x <= rect\right
                       If result\y >= rect\top  And result\y <= rect\bottom
                          If StartDrawing(CanvasOutput(0))
                              ; Box bei 0,0
                              Box(0,0,rect\right-rect\left,rect\bottom-rect\top,0)
                              ; Mauskoordinate auf die Box bei 0,0
                              Plot(result\x - rect\left, result\y - rect\top, RGB($FF,$FF,$00))
                              StopDrawing()
                          EndIf
                       EndIf
                   EndIf
                EndIf
            EndIf
    EndSelect
ForEver
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Antworten