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

All times are UTC + 1 hour




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: Corner of rotated box
PostPosted: Wed Jun 12, 2019 9:29 am 
Offline
Enthusiast
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)
    AddPathBox(*b\x, *b\y, *b\w, *b\h) 
    VectorSourceColor(RGBA(0, 0, 255, 255))
    StrokePath(1)
    StopVectorDrawing()
  EndIf
EndProcedure

Procedure OnCanvasEvents()
  Select EventType()
    Case #PB_EventType_KeyDown
      Select GetGadgetAttribute(0, #PB_Canvas_Key)
        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)
  BindGadgetEvent(0, @OnCanvasEvents(), #PB_All)
  DrawCanvas()
  SetActiveGadget(0)
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf


Top
 Profile  
Reply with quote  
 Post subject: Re: Corner of rotated box
PostPosted: Wed Jun 12, 2019 10:01 am 
Offline
Enthusiast
Enthusiast
User avatar

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
 Profile  
Reply with quote  
 Post subject: Re: Corner of rotated box
PostPosted: Wed Jun 12, 2019 10:07 am 
Offline
Enthusiast
Enthusiast

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

Thanks for your reply and code.

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
 Profile  
Reply with quote  
 Post subject: Re: Corner of rotated box
PostPosted: Wed Jun 12, 2019 10:18 am 
Offline
Enthusiast
Enthusiast
User avatar

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
 Profile  
Reply with quote  
 Post subject: Re: Corner of rotated box
PostPosted: Wed Jun 12, 2019 10:30 am 
Offline
Enthusiast
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.

Image


Top
 Profile  
Reply with quote  
 Post subject: Re: Corner of rotated box
PostPosted: Wed Jun 12, 2019 11:18 am 
Offline
Enthusiast
Enthusiast
User avatar

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
 Profile  
Reply with quote  
 Post subject: Re: Corner of rotated box
PostPosted: Wed Jun 12, 2019 12:19 pm 
Offline
Addict
Addict

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
 Profile  
Reply with quote  
 Post subject: Re: Corner of rotated box
PostPosted: Thu Jun 13, 2019 2:24 am 
Offline
Enthusiast
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
  angle_sin = Sin(Radian(angle))
  angle_cos = Cos(Radian(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

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)
    AddPathBox(*b\x, *b\y, *b\w, *b\h) 
    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
      mx = GetGadgetAttribute(0, #PB_Canvas_MouseX)
      my = GetGadgetAttribute(0, #PB_Canvas_MouseY)
      If mx => *b\rotatedHandle\x And mx < *b\rotatedHandle\x + 5 And my => *b\rotatedHandle\y And my < *b\rotatedHandle\y + 5
        SetGadgetAttribute(0, #PB_Canvas_Cursor, #PB_Cursor_LeftRight)
      Else
        SetGadgetAttribute(0, #PB_Canvas_Cursor, #PB_Cursor_Default)
      EndIf
    Case #PB_EventType_KeyDown
      Select GetGadgetAttribute(0, #PB_Canvas_Key)
        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)
  BindGadgetEvent(0, @OnCanvasEvents(), #PB_All)
  DrawCanvas()
  SetActiveGadget(0)
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf


Top
 Profile  
Reply with quote  
 Post subject: Re: Corner of rotated box
PostPosted: Thu Jun 13, 2019 3:09 am 
Offline
Enthusiast
Enthusiast
User avatar

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
      mx = GetGadgetAttribute(0, #PB_Canvas_MouseX)
      my = GetGadgetAttribute(0, #PB_Canvas_MouseY)
      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
          SetGadgetAttribute(0, #PB_Canvas_Cursor, #PB_Cursor_LeftRight)
        Else
          If (*b\angle > 45 And *b\angle < 90) Or (*b\angle < 315 And *b\angle > 270)
            SetGadgetAttribute(0, #PB_Canvas_Cursor, #PB_Cursor_UpDown)
          Else
            SetGadgetAttribute(0, #PB_Canvas_Cursor, #PB_Cursor_Default)
          EndIf
        EndIf
;...


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 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 forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye