Results 1 to 15 of 15

Thread: How to get the coordinates of the 4 corners of a coaxial rectangle on the circle

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2020
    Posts
    1,620

    How to get the coordinates of the 4 corners of a coaxial rectangle on the circle

    Assuming that the short side of the rectangle A=10CM, the long side B=20CM, the diameter of the circle is the diagonal of the rectangle (hypotenuse)
    At 0 degrees, the coordinates of the four corners of the rectangle relative to the center of the circle are X1, Y1 (X2, Y2), (X3, Y3), (X4, Y4)
    When rotating at any angle, what are the coordinates of the four corners relative to the center coordinate system?

    Trigonometric functions and arcs are all forgotten, and I donít know how to write this formula.
    The main purpose is to obtain the required canvas size when a rectangular picture is rotated at any angle.

    Name:  2230 旋转.jpg
Views: 180
Size:  34.4 KB

  2. #2
    Fanatic Member
    Join Date
    Sep 2010
    Location
    Italy
    Posts
    585

    Re: How to get the coordinates of the 4 corners of a coaxial rectangle on the circle

    0)
    Code:
    X1= B/2 = 10, Y1 = A/2 = 5  
    X2= X1 = 10, Y2 = - Y1 = - 5
    1) Apply 2D rotation on the "relative to center"-coordinates of 2 points of the Rectangle (Not in the diagonal)
    https://matthew-brett.github.io/teac...tation_2d.html
    https://danceswithcode.net/engineeri...ons_in_2d.html

    2) make these Rotated X Y coordinates Absolute values (Abs)
    Code:
    RotX2 = Abs (RotX2)
    3) Find Max(x) and Max(y)
    Code:
    if RotX2 > RotX1 then
        maxRX = RotX2
    else
        maxRX = RotX1
    End if
    4) new rectangle will be -maxRX to maxRX, -maxRY to maxRY

    PS:
    Not tested
    Just tought on the fly


    Edit:
    other sources
    https://www.google.com/search?q=boun...ated+rectangle
    https://gamedev.stackexchange.com/qu...d-rectangle-2d
    https://math.stackexchange.com/quest...a-bounding-box

  3. #3

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2020
    Posts
    1,620

    Re: How to get the coordinates of the 4 corners of a coaxial rectangle on the circle

    Thanks a lot. However, my technical level is limited, too advanced, did not understand.

    Yours is correct.

    In fact, I want to calculate it like this. Rectangle picture is rotated arbitrarily. If you want to draw it to a control.This control needs how many big squares, mainly wants to solve this problem.

    I now have a more complex matrix algorithm for rotating pictures. It requires an image frame as a carrier. But often four weeks will have a superfluous blank.

    Because I created that square of diagonal length.Manual rotation of the image in the middle of the image will not run out, but there will be excess white edge.

    Maybe there's another way. You can rotate the picture in pure code and save it.

  4. #4
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,374

    Re: How to get the coordinates of the 4 corners of a coaxial rectangle on the circle

    If you're using GDIplus to do the image rotation, you should be able to use the Matrix involved to convert an array of points, i.e. you pass it an array of the four corners and it will return an array of the points rotated.

    The caveat is that I haven't done this with GDIplus. I've done it in .Net whose graphics are based on GDI+.
    If it can be done in a .Net language, it should be doable using GDIplus with VB6.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  5. #5
    Hyperactive Member
    Join Date
    Jul 2020
    Posts
    283

    Re: How to get the coordinates of the 4 corners of a coaxial rectangle on the circle

    An example is here:
    https://www.vbforums.com/showthread....-ROTATION-only
    Rotating the rectangle will inevitably leave unpainted parts of the canvas.

  6. #6

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2020
    Posts
    1,620

    Re: How to get the coordinates of the 4 corners of a coaxial rectangle on the circle

    Quote Originally Posted by Argus19 View Post
    An example is here:
    https://www.vbforums.com/showthread....-ROTATION-only
    Rotating the rectangle will inevitably leave unpainted parts of the canvas.
    As long as you calculate the coordinates of the four points of the rotated rectangle, you can make the most perfect canvas, and then paint it without any extra white edge.

  7. #7
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,374

    Re: How to get the coordinates of the 4 corners of a coaxial rectangle on the circle

    I went ahead and looked up the gdip method GdipTransformPoints and played around with it a bit.
    Since "The trick" already provided an example at the link in post #5, I used it as the playground.

    I added the declarations
    Code:
    Private Enum CoordinateSpace
       CoordinateSpaceworld     ' 0
       CoordinateSpacepage      ' 1
       CoordinateSpacedevice     ' 2
    End Enum
    Private Type POINTF
       X As Single
       Y As Single
    End Type
    
    Private Declare Function GdipTransformPoints Lib "gdiplus" (ByVal graphics As Long, ByVal destSpace As CoordinateSpace, ByVal srcSpace As CoordinateSpace, Points As POINTF, ByVal count As Long) As Long
    And I added code to the Draw sub to fill the array (which could have been done in Form_load since the values wouldn't change if the size of the picture doesn't change), a call to the transformPoints method, and a debug.print to print out the values, and added code to plot the points.

    Since the values are relative to 0,0, the points plotted will always be around the center point of rotation.

    If you move the picture to center on that center of rotation, then the four plotted points should rotate along with the corners of the picture, showing that the transformPoints method is transforming those four fixed corners to the points the current matrix that is part of the graphics object is using to draw with at that time.
    Code:
        Dim tstPoints(0 To 3) As POINTF
        tstPoints(0).X = -iWidth / 2
        tstPoints(0).Y = -iHeight / 2
        tstPoints(1).X = iWidth / 2
        tstPoints(1).Y = -iHeight / 2
        tstPoints(2).X = iWidth / 2
        tstPoints(2).Y = iHeight / 2
        tstPoints(3).X = -iWidth / 2
        tstPoints(3).Y = iHeight / 2
        GdipTransformPoints graphics, CoordinateSpacedevice, CoordinateSpaceworld, tstPoints(0), 4
        Debug.Print tstPoints(0).X; , ; tstPoints(0).Y,
        Debug.Print tstPoints(1).X; , ; tstPoints(1).Y,
        Debug.Print tstPoints(2).X; , ; tstPoints(2).Y,
        Debug.Print tstPoints(3).X; , ; tstPoints(3).Y
    '...
        GdipDrawEllipse graphics, Pen, tstPoints(0).X, tstPoints(0).Y, 5, 5
        GdipDrawEllipse graphics, Pen, tstPoints(1).X, tstPoints(1).Y, 5, 5
        GdipDrawEllipse graphics, Pen, tstPoints(2).X, tstPoints(2).Y, 5, 5
        GdipDrawEllipse graphics, Pen, tstPoints(3).X, tstPoints(3).Y, 5, 5
    "The trick"'s complete example code source with modifications...
    Code:
    Private Type GdiplusStartupInput
        GdiplusVersion              As Long
        DebugEventCallback          As Long
        SuppressBackgroundThread    As Long
        SuppressExternalCodecs      As Long
    End Type
    
    Private Enum CoordinateSpace
       CoordinateSpaceworld     ' 0
       CoordinateSpacepage      ' 1
       CoordinateSpacedevice     ' 2
    End Enum
    Private Type POINTF
       X As Single
       Y As Single
    End Type
    
    Private Const UnitPixel                     As Long = 2
    Private Const InterpolationModeHighQuality  As Long = 2
    
    Private Declare Function GdipDrawImageRect Lib "gdiplus" (ByVal graphics As Long, ByVal image As Long, ByVal X As Single, ByVal Y As Single, ByVal Width As Single, ByVal Height As Single) As Long
    Private Declare Function GdipGetImageWidth Lib "gdiplus" (ByVal image As Long, Width As Long) As Long
    Private Declare Function GdipGetImageHeight Lib "gdiplus" (ByVal image As Long, Height As Long) As Long
    Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal image As Long) As Long
    Private Declare Function GdiplusStartup Lib "gdiplus" (token As Long, inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As Long = 0) As Long
    Private Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hdc As Long, graphics As Long) As Long
    Private Declare Function GdipDeleteGraphics Lib "gdiplus" (ByVal graphics As Long) As Long
    Private Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As Long
    Private Declare Function GdipTranslateWorldTransform Lib "gdiplus" (ByVal graphics As Long, ByVal dx As Single, ByVal dy As Single, ByVal order As Long) As Long
    Private Declare Function GdipRotateWorldTransform Lib "gdiplus" (ByVal graphics As Long, ByVal angle As Single, ByVal order As Long) As Long
    Private Declare Function GdipCreatePen1 Lib "gdiplus" (ByVal color As Long, ByVal Width As Single, ByVal unit As Long, Pen As Long) As Long
    Private Declare Function GdipDeletePen Lib "gdiplus" (ByVal Pen As Long) As Long
    Private Declare Function GdipCreateBitmapFromHBITMAP Lib "gdiplus" (ByVal hbm As Long, ByVal hpal As Long, Bitmap As Long) As Long
    Private Declare Function GdipGraphicsClear Lib "gdiplus" (ByVal graphics As Long, ByVal lColor As Long) As Long
    Private Declare Function GdipDrawEllipse Lib "gdiplus" (ByVal graphics As Long, ByVal Pen As Long, ByVal X As Single, ByVal Y As Single, ByVal Width As Single, ByVal Height As Single) As Long
    Private Declare Function GdipResetWorldTransform Lib "gdiplus" (ByVal graphics As Long) As Long
    
    Private Declare Function GdipTransformPoints Lib "gdiplus" (ByVal graphics As Long, ByVal destSpace As CoordinateSpace, ByVal srcSpace As CoordinateSpace, Points As POINTF, ByVal count As Long) As Long
    
    Dim SrcPicture  As StdPicture
    Dim Bitmap      As Long
    Dim graphics    As Long
    Dim GpInput     As GdiplusStartupInput
    Dim token       As Long
    Dim Pen         As Long
    
    Private Sub Form_Load()
        picOut.AutoRedraw = True
        
        Set SrcPicture = picSrc.Picture
        
        hsclXPos.Max = picSrc.ScaleWidth
        vsclYPos.Max = picSrc.ScaleHeight
        
        GpInput.GdiplusVersion = 1
        GdiplusStartup token, GpInput
        
        GdipCreateFromHDC picOut.hdc, graphics
    
        GdipCreateBitmapFromHBITMAP SrcPicture.Handle, SrcPicture.hpal, Bitmap
        GdipCreatePen1 vbCyan Or &HFF000000, 4, UnitPixel, Pen
        DrawCenter
        Draw
        
    End Sub
    
    Private Sub DrawCenter()
        picSrc.PaintPicture SrcPicture, 0, 0
        picSrc.PSet (hsclXPos.Value, vsclYPos.Value)
        picSrc.Refresh
    End Sub
    
    Private Sub Draw()
        Dim iWidth As Long, iHeight As Long
        
        GdipRotateWorldTransform graphics, hsclAnle.Value, 1
        GdipTranslateWorldTransform graphics, picOut.ScaleWidth / 2, picOut.ScaleHeight / 2, 1
        GdipGraphicsClear graphics, &HFFFFFFFF
        GdipGetImageWidth Bitmap, iWidth
        GdipGetImageHeight Bitmap, iHeight
        GdipDrawImageRect graphics, Bitmap, -hsclXPos.Value, -vsclYPos.Value, iWidth, iHeight
        Dim tstPoints(0 To 3) As POINTF
        tstPoints(0).X = -iWidth / 2
        tstPoints(0).Y = -iHeight / 2
        tstPoints(1).X = iWidth / 2
        tstPoints(1).Y = -iHeight / 2
        tstPoints(2).X = iWidth / 2
        tstPoints(2).Y = iHeight / 2
        tstPoints(3).X = -iWidth / 2
        tstPoints(3).Y = iHeight / 2
        GdipTransformPoints graphics, CoordinateSpacedevice, CoordinateSpaceworld, tstPoints(0), 4
        Debug.Print tstPoints(0).X; , ; tstPoints(0).Y,
        Debug.Print tstPoints(1).X; , ; tstPoints(1).Y,
        Debug.Print tstPoints(2).X; , ; tstPoints(2).Y,
        Debug.Print tstPoints(3).X; , ; tstPoints(3).Y
        
        GdipResetWorldTransform graphics
        GdipDrawEllipse graphics, Pen, picOut.ScaleWidth / 2, picOut.ScaleHeight / 2, 3, 3
        
        GdipDrawEllipse graphics, Pen, tstPoints(0).X, tstPoints(0).Y, 5, 5
        GdipDrawEllipse graphics, Pen, tstPoints(1).X, tstPoints(1).Y, 5, 5
        GdipDrawEllipse graphics, Pen, tstPoints(2).X, tstPoints(2).Y, 5, 5
        GdipDrawEllipse graphics, Pen, tstPoints(3).X, tstPoints(3).Y, 5, 5
        
        picOut.Refresh
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
        GdipDeleteGraphics graphics
        GdipDeletePen Pen
        GdipDisposeImage (Bitmap)
        GdiplusShutdown (token)
    End Sub
    
    Private Sub hsclAnle_Change()
        Draw
        DrawCenter
    End Sub
    
    Private Sub hsclAnle_Scroll()
        hsclAnle_Change
    End Sub
    
    Private Sub hsclXPos_Change()
        Draw
        DrawCenter
    End Sub
    
    Private Sub hsclXPos_Scroll()
        hsclXPos_Change
    End Sub
    
    Private Sub vsclYPos_Change()
        Draw
        DrawCenter
    End Sub
    
    Private Sub vsclYPos_Scroll()
        vsclYPos_Change
    End Sub
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  8. #8

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2020
    Posts
    1,620

    Re: How to get the coordinates of the 4 corners of a coaxial rectangle on the circle

    How to use GDIPLUS to rotate a picture 90 degrees, 180 degrees, 270 degrees, this kind of code is very rare.
    How to rotate at any angle, this kind of code has not been found after searching hundreds of pages on the Internet.
    Input file 1.PNG, set to rotate 35 degrees, save as 2.png

  9. #9
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,374

    Re: How to get the coordinates of the 4 corners of a coaxial rectangle on the circle

    I don't understand your comment.
    The Tricks code rotates at any angle you choose. If you want to rotate 90, 180 or 270, just choose those angles.

    If you wanted the code in VB.Net, I might whip it out, but I probably won't.
    If you want it in VB6, I would have to research, and I'm pretty sure I won't.
    I know there should be plenty of examples of reading in png and writing png files from VB6, and you can modify "The trick" code to do the rotation you want, and the modification I did to figure out the size of the bitmap needed.

    You could also have figured the bitmap sizing based on what reexre posted as well since it should give you essentially the same answer for the four corners.

    So, find the pieces and put it together.
    1. Load 1.PNG into a bitmap.

    2. Either use reexre's code to calculate the four corners at 35 degrees to determine the size of the bitmap you need or you could create the transforms with Gdip in a graphics object and determine the four corners from that. You don't actually have to draw before you use the graphics object's transformation matrix to figure out the four corners.

    3. Create a bitmap the size needed based on step 2.

    4. Get a graphics object for the bitmap created in step 3, apply the transforms to that graphics object and draw the original bitmap into that bitmap.

    5. Save that bitmap to 2.png
    Last edited by passel; Sep 10th, 2021 at 09:18 AM.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  10. #10
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,602

    Re: How to get the coordinates of the 4 corners of a coaxial rectangle on the circle

    Quote Originally Posted by passel View Post
    If you want it in VB6, I would have to research, ...
    ...what the OP wants is probably this (RC5/RC6-based):
    Code:
    Public Function GetRotatedSurface(SrcSrf As cCairoSurface, ByVal AngDeg As Double) As cCairoSurface
      Dim CC As cCairoContext, x1#, y1#, x2#, y2#, SrcPat As cCairoPattern
      
      'first, a "measure"-context is used to retrieve the Bounding-Rect
      Set CC = SrcSrf.CreateContext
          CC.Rectangle 0, 0, SrcSrf.Width, SrcSrf.Height
          CC.RotateDrawingsDeg -AngDeg
          CC.GetPathExtents x1, y1, x2, y2 '<- retrieve TopLeft- and BottomRight-points of the Bounding-Rect
        
      'now use the right size to create the ResultSurface-Context, to render the rotated SrcSrf (wrapped in a Pattern)
      Set CC = Cairo.CreateSurface(Abs(x1 - x2), Abs(y1 - y2)).CreateContext
      Set SrcPat = SrcSrf.CreateSurfacePattern() 'a thin wrapper, to be able to apply the transforms in the next line
      Set SrcPat.Matrix = SrcPat.Matrix.RotateCoordsDeg(-AngDeg).TranslateCoords(x1, y1)
      CC.Paint 1, SrcPat 'render the (Src)pattern to the properly resized result-surface-context
          
      Set GetRotatedSurface = CC.Surface 'return the result
    End Function
    The above routine expects a Source-Surface -
    and returns the result as another (usually larger, after rotation) ImageSurface-Object.
    And since any cCairoSurface can be written to Png or JPG (just using a method-call on the Result-Surface),
    the whole task could be wrapped-up without larger issues.

    Olaf

  11. #11
    PowerPoster
    Join Date
    Feb 2006
    Posts
    22,825

    Re: How to get the coordinates of the 4 corners of a coaxial rectangle on the circle

    Maybe look at GdipImageRotateFlip()? Should be faster than the fine rotation calls.

  12. #12
    PowerPoster
    Join Date
    Feb 2017
    Posts
    3,392

    Re: How to get the coordinates of the 4 corners of a coaxial rectangle on the circle

    Code:
    Private Type POINTAPI
        X As Long
        Y As Long
    End Type
    
    Private Function RotatePoints(nSource() As POINTAPI, ByVal nAngleDegrees As Single) As POINTAPI()
        Dim iCenter As POINTAPI
        Dim iLeft As Long
        Dim iTop As Long
        Dim iRight As Long
        Dim iBottom As Long
        Dim c As Long
        Dim iUb As Long
        Dim iAngleInRadians As Single
        Dim iCos As Single
        Dim iSin As Single
        Dim iRet() As POINTAPI
        
        If nAngleDegrees > 360 Then nAngleDegrees = nAngleDegrees Mod 360
        If nAngleDegrees < 0 Then nAngleDegrees = 360 + nAngleDegrees Mod -360
        
        iAngleInRadians = nAngleDegrees * 3.14159265359 / 180
        iCos = Cos(iAngleInRadians)
        iSin = Sin(iAngleInRadians)
        
        iUb = UBound(nSource)
        ReDim iRet(iUb)
        
        iLeft = nSource(0).X
        iRight = nSource(0).X
        iTop = nSource(0).Y
        iBottom = nSource(0).Y
        
        For c = 1 To iUb
            If nSource(c).X < iLeft Then iLeft = nSource(c).X
            If nSource(c).X > iRight Then iRight = nSource(c).X
            If nSource(c).Y < iTop Then iTop = nSource(c).Y
            If nSource(c).Y > iBottom Then iBottom = nSource(c).Y
        Next
        
        iCenter.X = (iLeft + iRight) / 2
        iCenter.Y = (iTop + iBottom) / 2
        
        For c = 0 To iUb
            iRet(c).X = (nSource(c).X - iCenter.X) * iCos - (nSource(c).Y - iCenter.Y) * iSin + iCenter.X
            iRet(c).Y = (nSource(c).X - iCenter.X) * iSin + (nSource(c).Y - iCenter.Y) * iCos + iCenter.Y
        Next
        RotatePoints = iRet
    End Function
    Attached Files Attached Files

  13. #13
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,602

    Re: How to get the coordinates of the 4 corners of a coaxial rectangle on the circle

    Quote Originally Posted by Eduardo- View Post
    Private Function RotatePoints(nSource() As POINTAPI, ByVal nAngleDegrees As Single) As POINTAPI()
    The OPs question was (IMO) not about the rotation itself, but about "finding the bounding-box":
    https://stackoverflow.com/questions/...lement-via-jav

    reexre tried to cover that as well in his reply (and links) in #2.

    Olaf

  14. #14
    PowerPoster
    Join Date
    Feb 2017
    Posts
    3,392

    Re: How to get the coordinates of the 4 corners of a coaxial rectangle on the circle

    Quote Originally Posted by Schmidt View Post
    The OPs question was (IMO) not about the rotation itself, but about "finding the bounding-box":
    https://stackoverflow.com/questions/...lement-via-jav

    reexre tried to cover that as well in his reply (and links) in #2.

    Olaf
    OK, this can be achieved with another auxiliary function:

    Code:
    Private Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
    End Type
    
    Private Function FindBoundingBoxPointsRotated(nPoints() As POINTAPI, ByVal nAngleDegrees As Single) As RECT
        Dim iRotated() As POINTAPI
        Dim c As Long
        
        iRotated = RotatePoints(nPoints, nAngleDegrees)
        FindBoundingBoxPointsRotated.Left = iRotated(0).X
        FindBoundingBoxPointsRotated.Right = iRotated(0).X
        FindBoundingBoxPointsRotated.Top = iRotated(0).Y
        FindBoundingBoxPointsRotated.Bottom = iRotated(0).Y
        For c = 1 To UBound(iRotated)
            If iRotated(c).X < FindBoundingBoxPointsRotated.Left Then FindBoundingBoxPointsRotated.Left = iRotated(c).X
            If iRotated(c).X > FindBoundingBoxPointsRotated.Right Then FindBoundingBoxPointsRotated.Right = iRotated(c).X
            If iRotated(c).Y < FindBoundingBoxPointsRotated.Top Then FindBoundingBoxPointsRotated.Top = iRotated(c).Y
            If iRotated(c).Y > FindBoundingBoxPointsRotated.Bottom Then FindBoundingBoxPointsRotated.Bottom = iRotated(c).Y
        Next
    End Function
    Attached Files Attached Files

  15. #15

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2020
    Posts
    1,620

    Re: How to get the coordinates of the 4 corners of a coaxial rectangle on the circle

    For rotations, paths, textures, brushes, etc. Maybe it's like rc6.dll. It takes 100 pages of help to learn most of the tricks.(for gdiplus.dll)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width