Seite 1 von 1

Rotierte Box-Mausklick Abrage

Verfasst: 15.04.2012 19:56
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)

Re: Rotierte Box-Mausklick Abrage

Verfasst: 15.04.2012 20:06
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.

Re: Rotierte Box-Mausklick Abrage

Verfasst: 15.04.2012 20:31
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

Re: Rotierte Box-Mausklick Abrage

Verfasst: 15.04.2012 20:55
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.

Re: Rotierte Box-Mausklick Abrage

Verfasst: 15.04.2012 21:38
von Lambda
Ok, danke euch beiden das hat mir geholfen :D

Re: Rotierte Box-Mausklick Abrage

Verfasst: 15.04.2012 21:46
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