PureBasic Forum

 It is currently Fri Oct 18, 2019 8:30 pm

 All times are UTC + 1 hour

 Page 1 of 1 [ 9 posts ]
 Print view Previous topic | Next topic
Author Message
 Post subject: Corner of rotated boxPosted: Wed Jun 12, 2019 9:29 am
 Enthusiast

Joined: Thu Dec 29, 2011 5:03 pm
Posts: 463
Hi,

I'm working towards implementing resizing shapes in my project, but I am unsure how to determine where the corners of the box are when its rotated. For example, when the box is rotated to 40 degrees, what was the bottom-right corner is now at the bottom. Is there a formula or something I can use to determine where the corners are?
Code:
EnableExplicit

Structure Box
x.i : y.i
w.i : h.i
angle.i
EndStructure

Global handleSize = 6

Global *b.Box = AllocateStructure(Box)
With *b
\x = 270 : \y = 178
\w = 100 : \h = 125
\angle = 0
EndWith

Procedure DrawCanvas()
Protected txt\$
txt\$ = ~"Left/right to rotate\n\n0 to reset\n\nEscape to end\n\n\nAngle: " + Str(*b\angle) + Chr(176)
If StartVectorDrawing(CanvasVectorOutput(0))
VectorSourceColor(RGBA(0, 0, 0, 255))
FillVectorOutput()
VectorSourceColor(RGBA(255, 255, 255, 255))
MovePathCursor(20, 20)
DrawVectorParagraph(txt\$, 200, 200)
RotateCoordinates(*b\x + *b\w / 2, *b\y + *b\h / 2, *b\angle)
VectorSourceColor(RGBA(0, 0, 255, 255))
StrokePath(1)
StopVectorDrawing()
EndIf
EndProcedure

Procedure OnCanvasEvents()
Select EventType()
Case #PB_EventType_KeyDown
Case #PB_Shortcut_Left
*b\angle - 3
If *b\angle < 0
*b\angle = 359
EndIf
If *b\angle > 359
*b\angle = 0
EndIf
Case #PB_Shortcut_Right
*b\angle + 3
If *b\angle < 0
*b\angle = 359
EndIf
If *b\angle > 359
*b\angle = 0
EndIf
Case #PB_Shortcut_0 : *b\angle = 0
Case #PB_Shortcut_Escape : End
EndSelect
DrawCanvas()
EndSelect
EndProcedure

If OpenWindow(0, 0, 0, 640, 480, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, 640, 480, #PB_Canvas_Keyboard)
DrawCanvas()
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

Top

 Post subject: Re: Corner of rotated boxPosted: Wed Jun 12, 2019 10:01 am
 Enthusiast

Joined: Sun Sep 11, 2016 2:17 pm
Posts: 533
U can just calculate the new positions.

This code for example rotates one point around another point (anchor):
Code:
Structure VECTOR_STRUCT
x.f
y.f
EndStructure

Procedure.i RotateAnchoredPoint(*Anchor.VECTOR_STRUCT,*Point.VECTOR_STRUCT,Angle.f,*Out.VECTOR_STRUCT)
Protected angle_sin.f
Protected angle_cos.f
Protected pos_x.f
Protected pos_y.f
angle_sin = Sin(angle)
angle_cos = Cos(angle)
pos_x = *Point\x - *Anchor\x
pos_y = *Point\y - *Anchor\y
*Out\x = (angle_cos * pos_x) - (angle_sin * pos_y) + *Anchor\x
*Out\y = (angle_sin * pos_x) + (angle_cos * pos_y) + *Anchor\y
ProcedureReturn #Null
EndProcedure

If you have a box just do this for all corner points (the anchor point would be the box center).

Top

 Post subject: Re: Corner of rotated boxPosted: Wed Jun 12, 2019 10:07 am
 Enthusiast

Joined: Thu Dec 29, 2011 5:03 pm
Posts: 463
Hi,

How would I know which corner does what - for example, if I want to change the mouse corner to #PB_Cursor_LeftUpRightDown when the mouse is over it?

Top

 Post subject: Re: Corner of rotated boxPosted: Wed Jun 12, 2019 10:18 am
 Enthusiast

Joined: Sun Sep 11, 2016 2:17 pm
Posts: 533
Im not sure if i understand you correctly - do you want to check if the mouse is inside the rectangle or just know where the corners are?

If u want to always know where which corner is u can either store the angle or mark at least two (diagonal) corner points.
Im not sure how to detect if a point is in a rotated rectangle i would need to look it up.

Top

 Post subject: Re: Corner of rotated boxPosted: Wed Jun 12, 2019 10:30 am
 Enthusiast

Joined: Thu Dec 29, 2011 5:03 pm
Posts: 463
Sorry for not being clearer.

With the first box, the black mark is at the top-right and I would change the cursor to #PB_Cursor_LeftDownRightUp. In the second, because the box has been rotated, it's at the bottom, so the cursor would need to be #PB_Cursor_UpDown.

Top

 Post subject: Re: Corner of rotated boxPosted: Wed Jun 12, 2019 11:18 am
 Enthusiast

Joined: Sun Sep 11, 2016 2:17 pm
Posts: 533
So you need to do both and see which corner is the closest in order to set the correct mouse cursor.

Top

 Post subject: Re: Corner of rotated boxPosted: Wed Jun 12, 2019 12:19 pm

Joined: Thu Aug 30, 2007 11:54 pm
Posts: 1109
Location: right here
You need to know your center of rotation. If you rotate your box around the center of the box, you would get the distance from that center to the unrotated corner. Then you can rotate that vector by the same amount by which you rotate the box, then add the center position again to the rotated vector and you have your new corner position.

For rotated box collision you can check this out:
Rotated Box Collision Detection 2d/3d

Similar to what I wrote above, for collision detection you can also get the distance from your center of rotation to the mouse position, then unrotate (reverse rotate) that relative mouse position vector by the amount of your box rotation, and then do a normal box collision check (point in rectangle, without rotation).

I hope that helps

Top

 Post subject: Re: Corner of rotated boxPosted: Thu Jun 13, 2019 2:24 am
 Enthusiast

Joined: Thu Dec 29, 2011 5:03 pm
Posts: 463
Thanks for your replies. What I am struggling to understand how to do is identify what a resize handle should be based on the rotation of the box. At 0º, the handle for changing the height is going to be at the bottom, whereas at 45º, it's shifted up and to the left.

If I reverse the rotation of the handle, that gives me its position at 0º, but that doesn't help me figure out what that handle should actually be. The position of the handle should always be on the outside of the box, but when the angle exceeds 90º, it starts to move inside the box.

The handle is correctly identified at 0º and 180º, but at any other angle, it would take on a different function. I am struggling to figure out how to identify what that function should be based on the rotation.
Code:
EnableExplicit

Structure PointF
x.f
y.f
EndStructure

Procedure.i RotateAnchoredPoint(*Anchor.PointF,*Point.PointF,Angle.f,*Out.PointF)
Protected angle_sin.f
Protected angle_cos.f
Protected pos_x.f
Protected pos_y.f
pos_x = *Point\x - *Anchor\x
pos_y = *Point\y - *Anchor\y
*Out\x = (angle_cos * pos_x) - (angle_sin * pos_y) + *Anchor\x
*Out\y = (angle_sin * pos_x) + (angle_cos * pos_y) + *Anchor\y
ProcedureReturn #Null
EndProcedure

Structure Box
x.i : y.i
w.i : h.i
angle.f
handle.PointF
rotatedHandle.PointF
EndStructure

Global handleSize = 6

Global *b.Box = AllocateStructure(Box)
With *b
\x = 270 : \y = 178
\w = 100 : \h = 125
\angle = 0
\handle\x = \x + \w
\handle\y = \y + (\h / 2)
EndWith

Procedure DrawCanvas()
Protected txt\$
txt\$ = ~"Left/right to rotate\n\n0 to reset\n\nEscape to end\n\n\nAngle: " + Str(*b\angle) + Chr(176)
If StartVectorDrawing(CanvasVectorOutput(0))
VectorSourceColor(RGBA(0, 0, 0, 255))
FillVectorOutput()
VectorSourceColor(RGBA(255, 255, 255, 255))
MovePathCursor(20, 20)
DrawVectorParagraph(txt\$, 200, 200)
RotateCoordinates(*b\x + *b\w / 2, *b\y + *b\h / 2, *b\angle)
VectorSourceColor(RGBA(0, 0, 255, 255))
StrokePath(1)
StopVectorDrawing()
If StartDrawing(CanvasOutput(0))
Define center.PointF, rotated.PointF
center\x = *b\x + *b\w / 2
center\y = *b\y + *b\h / 2
RotateAnchoredPoint(@center, @*b\handle, *b\angle, @*b\rotatedHandle)
Box(*b\rotatedHandle\x, *b\rotatedHandle\y, 5, 5, RGB(255, 255, 0))
StopDrawing()
EndIf
EndIf
EndProcedure

Procedure OnCanvasEvents()
Select EventType()
Case #PB_EventType_MouseMove
Define mx, my
If mx => *b\rotatedHandle\x And mx < *b\rotatedHandle\x + 5 And my => *b\rotatedHandle\y And my < *b\rotatedHandle\y + 5
Else
EndIf
Case #PB_EventType_KeyDown
Case #PB_Shortcut_Left
*b\angle - 3
If *b\angle < 0
*b\angle = 359
EndIf
If *b\angle > 359
*b\angle = 0
EndIf
Case #PB_Shortcut_Right
*b\angle + 3
If *b\angle < 0
*b\angle = 359
EndIf
If *b\angle > 359
*b\angle = 0
EndIf
Case #PB_Shortcut_0 : *b\angle = 0
Case #PB_Shortcut_Escape : End
EndSelect
DrawCanvas()
EndSelect
EndProcedure

If OpenWindow(0, 0, 0, 640, 480, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, 640, 480, #PB_Canvas_Keyboard)
DrawCanvas()
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

Top

 Post subject: Re: Corner of rotated boxPosted: Thu Jun 13, 2019 3:09 am
 Enthusiast

Joined: Sun Sep 11, 2016 2:17 pm
Posts: 533
Use the angle to decide what cursor is drawn:
Code:
Case #PB_EventType_MouseMove
Define mx, my
If mx => *b\rotatedHandle\x And mx < *b\rotatedHandle\x + 5 And my => *b\rotatedHandle\y And my < *b\rotatedHandle\y + 5
If *b\angle < 45 Or *b\angle > 315;example only covers 0° +- 90° & LeftRight + UpDown
Else
If (*b\angle > 45 And *b\angle < 90) Or (*b\angle < 315 And *b\angle > 270)
Else
EndIf
EndIf
;...

Top

 Display posts from previous: All posts1 day7 days2 weeks1 month3 months6 months1 year Sort by AuthorPost timeSubject AscendingDescending
 Page 1 of 1 [ 9 posts ]

 All times are UTC + 1 hour

Who is online

Users browsing this forum: Baidu [Spider] and 16 guests

 You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forum

Search for:
 Jump to:  Select a forum ------------------ PureBasic    Coding Questions    Game Programming    3D Programming    Assembly Programming    The PureBasic Editor    The PureBasic Form Designer    General Discussion    Feature Requests and Wishlists    Tricks 'n' Tips Bug Reports    Bugs - Windows    Bugs - Linux    Bugs - Mac OSX    Bugs - Documentation OS Specific    AmigaOS    Linux    Windows    Mac OSX Miscellaneous    Announcement    Off Topic Showcase    Applications - Feedback and Discussion    PureFORM & JaPBe    TailBite