Results 1 to 7 of 7

Thread: [RESOLVED] How to use RotateTransform and TranslateTransform to draw list of ellipses on bitmap

  1. #1

    Thread Starter
    Member
    Join Date
    Sep 2017
    Location
    Port St Lucie, Florida, United States
    Posts
    51

    Resolved [RESOLVED] How to use RotateTransform and TranslateTransform to draw list of ellipses on bitmap

    I'm drawing on a (square) bitmap on a Windows form a list of objects that include ellipses. I'm generating many properties for these objects randomly. I want to rotate the ellipses to give them more variation than the plain horizontal and vertical look. I'm giving each ellipse a random number between 0 and 360 to use to rotate them. To rotate them, I'm trying to use RotateTransform. The relevant part of the code can be seen below under the "ElseIf" part of the "If" statement, where I'm drawing the ellipses.

    If I just use RotateTransform as I have it here, many of the ellipses get drawn. But it looks to me that the rotation is taking place around the (0,0) point of origin. (I'm not sure.) If so, then I think the only ellipses I see drawn are the ones that have a rotation number (of the 360 number that I'm using) that allows them to hit the bitmap. Most of them aren't getting drawn on the bitmap.

    What I thought I should be doing is have the Location point of each ellipse fall somewhere on the square bitmap, which I'm doing, but then have the rotation take place around that Location point, so the Location point isn't moved somewhere by the RotateTransform. I thought that TranslateTransform would allow me to do that, but I've tried to use it with no success. If I'm lucky, I might see one or two ellipses drawn out of dozens that are in the list. I'm not sure how to use it.

    My question is this: What is a correct way to rotate my ellipses so that they are all kept on the bitmap and drawn on the bitmap. Thanks for any help.

    By the way, this line,

    Code:
     objGraphics.RotateTransform(-Form1.ListOfLines(drawindex).EllipseRotation)
    which appears in the code below, seems to be needed because without it, it seems that the rotation affects where the other (non-ellipse) objects (in the first part of the "If" statement) get drawn. It's as if I have to undo the rotation (the negative sign) after I do it so it doesn't mess everything up.


    Code:
    For drawindex = 0 To Form1.ListOfLines.Count - 1
    
                If Form1.ListOfLines(drawindex).Name = "Object 1" Or Form1.ListOfLines(drawindex).Name = "Object 2" Then
    
                    Form1.myPen = New Pen(Drawing.Color.FromArgb(Form1.ListOfLines(drawindex).Alpha, Form1.ListOfLines(drawindex).R,
                                                           Form1.ListOfLines(drawindex).G, Form1.ListOfLines(drawindex).B)) With
                                                           {.Width = Form1.ListOfLines(drawindex).Thickness,
                                                            .CustomEndCap = New Drawing2D.AdjustableArrowCap(Form1.ListOfLines(drawindex).CapNum1,
                                                                                                             Form1.ListOfLines(drawindex).CapNum2, False)}
    
    
                    objGraphics.DrawLine(Form1.myPen, Form1.ListOfLines(drawindex).StartPoint, Form1.ListOfLines(drawindex).EndPoint)
    
                    Form1.PictureBox1.Invalidate()
    
                ElseIf Form1.ListOfLines(drawindex).Name = "Ellipse" Then
    
                    Form1.myPen = New Pen(Color.FromArgb(Form1.ListOfLines(drawindex).Alpha, Form1.ListOfLines(drawindex).R,
                                                                     Form1.ListOfLines(drawindex).G, Form1.ListOfLines(drawindex).B)) With
                                                                     {.Width = Form1.ListOfLines(drawindex).Thickness}
    
                    ' This line is commented out. objGraphics.TranslateTransform(Form1.ListOfLines(drawindex).EllipseLocationX,
                                                                               Form1.ListOfLines(drawindex).EllipseLocationY)
                    
                    objGraphics.RotateTransform(Form1.ListOfLines(drawindex).EllipseRotation)
    
    
                    objGraphics.DrawEllipse(Form1.myPen, Form1.ListOfLines(drawindex).EllipseLocationX, Form1.ListOfLines(drawindex).EllipseLocationY,
                                            Form1.ListOfLines(drawindex).EllipseWidth, Form1.ListOfLines(drawindex).EllipseHeight)
    
    
                    objGraphics.RotateTransform(-Form1.ListOfLines(drawindex).EllipseRotation)
    
                    Form1.PictureBox1.Invalidate()
                End If
            Next

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: How to use RotateTransform and TranslateTransform to draw list of ellipses on bit

    Quote Originally Posted by dwigley View Post
    If I just use RotateTransform as I have it here, many of the ellipses get drawn. But it looks to me that the rotation is taking place around the (0,0) point of origin. (I'm not sure.) If so, then I think the only ellipses I see drawn are the ones that have a rotation number (of the 360 number that I'm using) that allows them to hit the bitmap. Most of them aren't getting drawn on the bitmap.
    You're absolutely right. Your Bitmap is like the bottom, right quadrant of a Cartesian plane, i.e. the origin is at the top, left corner. Any rotation of 90 degrees or more is going to shift your drawing outside of that quadrant completely and thus out of view.

    What I would suggest is that you write code that draws an ellipse based on its centre point, e.g. if the ellipse is 50 wide and 100 high then you draw it from -25 to 25 in the horizontal and -50 to 50 in the vertical. Any rotation you then perform will be around the centre of the ellipse. Here's some example code that will draw randomly-sized ellipses where the dimensions are no bigger than the Bitmap to draw on and the centre is guaranteed to be within the Bitmap:
    vb.net Code:
    1. Private ReadOnly rng As New Random
    2.  
    3. Private Sub DrawEllipse(bmp As Bitmap)
    4.     Dim xShift = rng.Next(0, bmp.Width)
    5.     Dim yShift = rng.Next(0, bmp.Height)
    6.     Dim angle = rng.Next(0, 360)
    7.     Dim width = rng.Next(1, bmp.Width)
    8.     Dim height = rng.Next(1, bmp.Height)
    9.  
    10.     Using g = Graphics.FromImage(bmp)
    11.         g.TranslateTransform(xShift, yShift)
    12.         g.RotateTransform(angle)
    13.         g.DrawEllipse(Pens.Black, -width \ 2, -height \ 2, width, height)
    14.     End Using
    15. End Sub
    If you want to draw multiple ellipses with random translations and rotations then call ResetTransform in between to reset the origin each time:
    vb.net Code:
    1. Private ReadOnly rng As New Random
    2.  
    3. Private Sub DrawEllipses(bmp As Bitmap, count As Integer)
    4.     Using g = Graphics.FromImage(bmp)
    5.         For i = 1 To count
    6.             Dim xShift = rng.Next(0, bmp.Width)
    7.             Dim yShift = rng.Next(0, bmp.Height)
    8.             Dim angle = rng.Next(0, 360)
    9.             Dim width = rng.Next(1, bmp.Width)
    10.             Dim height = rng.Next(1, bmp.Height)
    11.  
    12.             g.TranslateTransform(xShift, yShift)
    13.             g.RotateTransform(angle)
    14.             g.DrawEllipse(Pens.Black, -width \ 2, -height \ 2, width, height)
    15.             g.ResetTransform()
    16.         Next
    17.     End Using
    18. End Sub
    Also note that it is important to call TranslateTransform before RotateTransform. Doing so ensures that the original origin stays within the bounds of the Bitmap. If you do it the other way around, you could end up with your ellipse completely outside the Bitmap again.
    Last edited by jmcilhinney; Feb 8th, 2018 at 10:21 PM. Reason: Added missing negation (-) symbols.

  3. #3
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: How to use RotateTransform and TranslateTransform to draw list of ellipses on bit

    Hmmm... I just tested that code and it doesn't quite work as I expected. Hopefully you get the idea and can play with it yourself to get it to work. If not, post back and I can have a closer look myself.

  4. #4
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: How to use RotateTransform and TranslateTransform to draw list of ellipses on bit

    I fixed the issue. I had failed to make the location coordinates for the ellipses negative.

  5. #5

    Thread Starter
    Member
    Join Date
    Sep 2017
    Location
    Port St Lucie, Florida, United States
    Posts
    51

    Re: How to use RotateTransform and TranslateTransform to draw list of ellipses on bit

    Thank you very much for the quick response. I'll examine your code and give it a try.

    It was very easy to fix incorporating your suggestions, and it works great.

    If I understand what is going on, the TranslateTransfrom X and Y work as the new upper left corner of the bounding rectangle for the ellipse, and that is also the point of rotation. Then the -Width \ 2 and -Height \ 2 shift the center of the ellipse over to the TranslateTransform point (where the upper left corner of the bounding rectangle was) to be drawn.

    If that isn't what's going on, then I'm fuzzy about what's going on.

    Those backward slashes are handy! -- avoids a narrowing conversion problem. Thanks.
    Last edited by dwigley; Feb 9th, 2018 at 01:11 AM.

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

    Re: How to use RotateTransform and TranslateTransform to draw list of ellipses on bit

    That is essentially what is going on, but it isn't just the upper left corner of the bounding rectangle of the ellipse.
    The way I look at it is that you're moving the (0,0) point of the window from the upper left corner to somewhere else, so all your drawing coordinates are relative to that point.

    That means you're always drawing the ellipse centered at (0,0), but where (0,0) is in the window has changed.

    Some examples of using transform and rotate and scale that you might find interesting to investigate.

    The first example has a step mode that explains what the code is doing step by step, while allowing you to still interact with it to observe what happens to the drawing up to that step with user interaction.
    More description and a link to the example is found in post #3 of this thread.

    Three more examples that might be interesting can be found in this post.
    Last edited by passel; Feb 9th, 2018 at 05:01 AM.

  7. #7

    Thread Starter
    Member
    Join Date
    Sep 2017
    Location
    Port St Lucie, Florida, United States
    Posts
    51

    Re: How to use RotateTransform and TranslateTransform to draw list of ellipses on bit

    I see passel. The TranslateTransform moves the 0,0 origin point to wherever you want it. In my case, I first move it to the location point of the bounding rectangle of the ellipse. Then the RotateTransform rotates everything around the new 0,0 point. Then in the DrawEllipse, I move the location of the bounding rectangle relative to the new 0,0 point and rotation, so that the 0,0 point is the center of the ellipse. The ellipse is drawn on the Bitmap. Finally, one uses the resetTransform to reset everything back, and draw the next ellipse.

    Making the center of the ellipse the new 0,0 point helps control the location of the ellipse.

    Thanks for the suggestions about where to find more about transform and rotate. Now you mention scale! I’ll check it out.

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