Recent

Author Topic: Rectangle: Calculate Centre of rotation  (Read 4964 times)

JasonLugg

  • Jr. Member
  • **
  • Posts: 67
Rectangle: Calculate Centre of rotation
« on: November 18, 2018, 12:13:22 pm »
Hi All

Thanks for any help in advance.

I am tring to code a focus/selection rectangle that is sizeable and can be rotated using the mouse. So far so good but I have hit a maths wall.

When the rectangle is rotated and is then sized with one of the corners or sides being dragged, I want to ensure its position at the opposite sides remains still.

What I wish to workout is, given I know the size of the rectangle and its angle of rotation, given any corner, how can I calculate the centre position? This would allow me to reposition as it is sized ensuring a corner stays ‘fixed’.

I wish to write a procedure that, passed a certain corner (NW,NE,SW,SE), I can position its centre relative to this corner point.

Sorry for the long winded text, hope it makes sense?

sash

  • Sr. Member
  • ****
  • Posts: 366
Re: Rectangle: Calculate Centre of rotation
« Reply #1 on: November 18, 2018, 12:34:08 pm »
Quote
hope it makes sense?
I'm sorry, but no.

What do you need to do: calculate COR (based on what) ? resize? rotate (around arbitrary point)?

I feel like you need something very standard, but I can't figure out a description of your task.
Please draw an illustration, it could help.
Lazarus 2.0.10 FPC 3.2.0 x86_64-linux-gtk2 @ Ubuntu 20.04 XFCE

wp

  • Hero Member
  • *****
  • Posts: 11853
Re: Rectangle: Calculate Centre of rotation
« Reply #2 on: November 18, 2018, 12:46:09 pm »
If you have any rectangle on a sheet of paper you'd find its center by drawing its diagonals and looking at their intersection. In a calculation you take the coordinates of opposite corners and calculate their average. So, assume that the corner points are in the array P[0..3] then the center is
Code: Pascal  [Select][+][-]
  1. C.X := (P[0].X + P[2].X) div 2;
  2. C.Y := (P[0].Y + P[2].Y) div 2);

JasonLugg

  • Jr. Member
  • **
  • Posts: 67
Re: Rectangle: Calculate Centre of rotation
« Reply #3 on: November 18, 2018, 12:52:04 pm »
Sash, et al, As you can see I am a little lost.

Okay lets try again.

Rectangle on screen with corner and side ‘Handles’ and a rotator arm so it can be rotated (like this)

     O
      |
O—#—O
|         |
#        #
|         |
O—#—O

when this is rotated, the user can resize this rectangle by dragging a side handle ‘#’ or a corner handle ‘O’ whether rotated or not.

When sized using a ‘#’ I want the opposite side to remain in a fixed location. When sized using an ‘O’, I want the opposite corner ‘O’ to remain in a fixed location. The rectangle is position based uponits centre.

When horizontal and the left side ‘#’ is dragged to the left, the rectangle gets wider to the left. This changes the x position of the centre by ChangeInWidth div 2. Repositioning the rectangle based upon this ensure the opposite ‘right’ side remains in a fixed position.

So in my simple mind if I can grab a corner (x,y -> my fixed point), resize and then calculate where the new centre would be in reference to the fixed point I could reposition so that it would keep the fixed point fixed.

I can do this for zero degrees but cannot work it out how to do this when the rectangle is rotated.

Does this help?

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Rectangle: Calculate Centre of rotation
« Reply #4 on: November 18, 2018, 02:03:27 pm »
I think you are confused about whether you are resizing or rotating the shape. You can only do one at a time.

If resizing you have two scenarios: dragging # alters the rectangle in one dimension; dragging O alters the rectangle in two dimensions.

If rotating, what is the centre of rotation? It is not the centre of the rectangle (since you want one of the corners to remain fixed). The centre of rotation is the fixed corner. Isn't the position of the rectangle's centre irrelevant? But perhaps I've misunderstood what you want.

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Rectangle: Calculate Centre of rotation
« Reply #5 on: November 18, 2018, 03:09:07 pm »
I believe the issue at play here is to how to log the corner plots when the square is rotated.

So It would be simple to hold the four corners in a array and when you rotate the square you shuffle the
values in this array, rotate them in the array and keep a variable handy to indicate where the first corner position
is in the array.

 So when doing sizing calculations you use the same indexes in the array as you would for sizing as if the
box isn't rotated.

 There are a number of ways to do this actually but keeping items in an array that can be rotated works.

The only true wisdom is knowing you know nothing

HeavyUser

  • Sr. Member
  • ****
  • Posts: 397
Re: Rectangle: Calculate Centre of rotation
« Reply #6 on: November 18, 2018, 04:54:13 pm »
Hi All

Thanks for any help in advance.

I am tring to code a focus/selection rectangle that is sizeable and can be rotated using the mouse. So far so good but I have hit a maths wall.

When the rectangle is rotated and is then sized with one of the corners or sides being dragged, I want to ensure its position at the opposite sides remains still.

What I wish to workout is, given I know the size of the rectangle and its angle of rotation, given any corner, how can I calculate the centre position? This would allow me to reposition as it is sized ensuring a corner stays ‘fixed’.

I wish to write a procedure that, passed a certain corner (NW,NE,SW,SE), I can position its centre relative to this corner point.

Sorry for the long winded text, hope it makes sense?

What type of information you save for the rectangle? top, left and  bottom right or width, height? I assume that you rotate the rectangle every time you paint it on screen in which case once rotated by the user you must save the rotation point to the rectangles internal structure along with the angle of rotation. That point will change only when the user rotates the rectangle again.

that's all assumptions keep your eye sharp.

sash

  • Sr. Member
  • ****
  • Posts: 366
Re: Rectangle: Calculate Centre of rotation
« Reply #7 on: November 18, 2018, 05:20:56 pm »
Quote from: JasonLugg
As you can see I am a little lost.
That's why I said "draw illustration". Of each feature/operation: what should it look like before and after.

I could guess you meant orthogonal resize (in local object coordinates), but again - draw it.

Also, what kind of visualization (rendering) do you use (TCanvas, SDL, Opengl/GLScene)? Some of them have some vector math included (transform matrix, primitives), that could help a lot.
Lazarus 2.0.10 FPC 3.2.0 x86_64-linux-gtk2 @ Ubuntu 20.04 XFCE

JasonLugg

  • Jr. Member
  • **
  • Posts: 67
Re: Rectangle: Calculate Centre of rotation
« Reply #8 on: November 19, 2018, 05:17:29 pm »
I have attached a video showing my selection rectangle with handles.

Graphics are drawn using a BGRABitmap BGLVirtualScreen.

with an ANGLE of 0 degrees
As can be seen, when the left side handle 'LS' is moved, the rectangle grows in width whilst the right side remains in a fixed position as I require.

The same can be seen when the Rightside RS handles is moved as is expected, and the Corner sizers NW,NE,SW,SE.

Also, The rotator arm works and the rectangle can be rotated using the mouse. All good thus far.

However, when the Angle is not Zero, I cannot get the opposite side to stay in place. As can be seen it moves so does not stay fixed (Fixed:=The hoped for outcome)!

The Rectangle is positioned using its Centre Position.

When at a non zero ANGLE (degrees), as the rectangle  changes size, how can I work out the new centre position based upon a corner position?

CURRENTLY:
Sizing is done as follows:
1] Rotate to Zero Degrees
2] Size the Rectangle
3] Rotate Back to require Degrees
4] Draw

This is how I represent the Selector Rectangle:
Code: Pascal  [Select][+][-]
  1.   aSpr = record
  2.     //SprImg: TBGLBitmap;
  3.     SprImg: TBGRABitmap;
  4.     Spr:IBGLTexture;
  5.     iCXPos, iCYPos: single;
  6.   end;
  7.  
  8.   //My Selector Type
  9.   aSelect = record
  10.     Centre: aVec2F;      //Centre Point Or Local Origin
  11.     //Size of Obj Select Rect
  12.     iW: integer;                                //Dims of Select Rectangle
  13.     iH: integer;
  14.     //Size of Sizer Sprs
  15.     iSizerSize: integer;
  16.     //Corner Sizers
  17.     NW: aSpr;            //Top Left Corner Sizer
  18.     NE: aSpr;                                           //Top Right Corner Sizer
  19.     SW: aSpr;                                           //Bottom Left Corner Sizer
  20.     SE: aSpr;                                           //Bottom Right Corner Selector
  21.     //Edge Sizers
  22.     LS: aSpr;                   //Left Sizer (Mid Height Left)
  23.     TS: aSpr;                   //Top Sizer (Mid Width Top)
  24.     RS: aSpr;                   //Right Sizer (Mid Height Right)
  25.     BS: aSpr;                   //Bottom Sizer (Mid Width Bottom)
  26.     //Rotator
  27.     Rotator: aSpr;              //Handle to Rotate with
  28.     fAngle: single;                     //Angle to draw at
  29.     bVisible: boolean;          //Is it Visible?
  30.  
  31.     //Standard Colours
  32.     tSelectorCol: TBGRAPixel;
  33.     tLineColor: TBGRAPixel;
  34.  
  35.     //Locked Colours (unable to size/move/rotate)
  36.  
  37.         end;
  38.  

Getting Balder (pulling hair out) by the minute!!  :(







 


soerensen3

  • Full Member
  • ***
  • Posts: 213
Re: Rectangle: Calculate Centre of rotation
« Reply #9 on: November 19, 2018, 10:28:22 pm »
Wow that looks complicated! I would simply store the center of the rectangle and width and height and the angle. This way you can simply calculate the corners rotation points (if you need) or all the locations of the handles.
Here you see the rotation matrix (Qz) for a 2D rotation:
https://wikimedia.org/api/rest_v1/media/math/render/svg/6e5a2cbae3353cfe1d1aa404c5aa38f405357e10
You can omit the last row and column and use a 2x2 matrix for simplicity.

This is a code for transforming a Position b by the 2x2 matrix a. For directions omit the last product. The numbers indicate the column and the row. You can use an array if you like. It is not important how you store your matrix but you need to remember how you do it and be consistent.
Code: Pascal  [Select][+][-]
  1. function TransformVec( a: TMat2x2; b: TVec2 ): TVec2;
  2. begin
  3.   Result.x:= ( b.x * a._00 ) + ( b.y * a._10 );
  4.   Result.y:= ( b.x * a._01 ) + ( b.y * a._11 );
  5. end;
  6.  

If you transform any point by the rotation matrix above it will be rotated around the origin 0,0. If you want a different origin you can subtract the origin (the center of your rectangle) transform the point and add the center to the coordinates again.

Code: Pascal  [Select][+][-]
  1. function TransformVecAroundCenter( a: TMat2x2; b: TVec2;  c: TVec2 ): TVec2;
  2. begin
  3.   Result.x:= (( b.x - c.x ) * a._00 ) + (( b.y - c.y ) * a._10 ) + c.x;
  4.   Result.y:= (( b.x - c.x ) * a._01 ) + (( b.y - c.y ) * a._11 ) + c.y;
  5. end;
  6.  

As a bonus you can also get the Left and Up axis for your rotated rectangle by using the first (X) and second (Y) column of your matrix.
If you need to only move one edge when resizing you need to also move the center of rectangle by half of the added size towards the direction of the edge. The direction of the edge is either the X or Y axis of your matrix multiplied by the half of the added size and multiplied by -1 if depending on the direction of edge. You can calculate all the locations of the handles this way.

Sorry I didn't test the code but it should compile fine.

Hope this helped!
Lazarus 1.9 with FPC 3.0.4
Target: Manjaro Linux 64 Bit (4.9.68-1-MANJARO)

sash

  • Sr. Member
  • ****
  • Posts: 366
Re: Rectangle: Calculate Centre of rotation
« Reply #10 on: November 20, 2018, 12:12:10 pm »
Although I still didn't get exactly, what author's problem is, given approach
Quote from: JasonLugg
CURRENTLY:
Sizing is done as follows:
1] Rotate to Zero Degrees Always store "Zero Degrees" shape
2] Size the Rectangle
3] Rotate Back to require Degrees
4] Draw

is (almost) exactly how they do with most scene-graph-based geometry engines.
Except you should not "Rotate (back) to Zero Degrees", you should always store original "Zero Degrees" (offscreen) shape (resized as needed in shape's local coordinates) and then apply required transformation (Rotation) to get a final result (in world/screen's coordinates).

This method benefits as not prone (unlike immediate state storage) to accumulation of rounding errors by complex (cascaded) transformations.

Lazarus 2.0.10 FPC 3.2.0 x86_64-linux-gtk2 @ Ubuntu 20.04 XFCE

JasonLugg

  • Jr. Member
  • **
  • Posts: 67
Re: Rectangle: Calculate Centre of rotation
« Reply #11 on: November 20, 2018, 03:27:47 pm »
Thank you so much soerensen3 and sash.

I do tend to over complicate when working out of my depth!

I thin what is happening is that, when rotated, as I pull the left side to enlarge the rectangle the following happens:
1] Rectangle Expands in Width.
2] As Rectangle is now bigger so obviously the Centre position moves.

As I position by the centre position, without making an allowance for the centre position difference as it sizes, when drawn the rectangle expands from the centre out i.e both sides 'expand'.

What I cannot get my head around is how to calculate the new centre position (at an angle) ensuring the opposite side remains in a fixed position?


wp

  • Hero Member
  • *****
  • Posts: 11853
Re: Rectangle: Calculate Centre of rotation
« Reply #12 on: November 20, 2018, 03:36:09 pm »
how to calculate the new centre position (at an angle) ensuring the opposite side remains in a fixed position?
Did you read my post in reply #2? The center is the average of the x and y coordinates of opposite corners of the rectangle. See code in reply #2.

 

TinyPortal © 2005-2018