locked
VB 2010 Rotate Text in graphics RRS feed

  • Question

  • My application plots graphics coordinate points in a picture box,  I have the matrix.rotate(-90) and a translateTransform that shows the point ellipse correctly in the coordinate positions X,Y  I also plot as a drawstring text offset lightly from the point, the associated database point number.  These point number strings now are oriented vertical.  I have tried everything I can research on getting them to show horizontal to no avail.   Any thoughts?

    Thanks

    Sunday, August 4, 2013 11:03 PM

Answers

  • To print the text un-rotated at the rotated point you have to calculate the text position taking the rotation into account then reset the transform before doing the printing. The calculation is simply the opposite of the rotate transform and then the opposite of the translate transform.

        '
        ' PAINT PANEL
        '
        Private Sub pb_map_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles pb_Map.Paint
            Dim maxnorth As Integer = 1200
            Dim maxeast As Integer = 1200
            pb_Map.Width = maxeast
            pb_Map.Height = maxnorth
    
            '************
            'graphics settings
            '***********************
            Dim gP As Graphics
            gP = e.Graphics
    
            Dim Ppt As Integer ' plot variable
            Dim Pnc, Pec As Double ' plot variable
            Dim plotEast, plotNorth As Integer ' holds scaled northing easting
            Dim offset As Integer = 4 ' pixel offset from actual point location so pt number does not plot on top of the pt ellipse
            '************ data inserted to make illustration easier
            Dim pt(9) As Double
            Dim nc(9) As Double
            Dim ec(9) As Double
    
            pt(1) = 100
            nc(1) = 100.1234
            ec(1) = 50.1234
            '
            pt(2) = 200
            nc(2) = 200.1234
            ec(2) = 50.1234
            '
            pt(3) = 302
            nc(3) = 200.1234
            ec(3) = 150.1234
            '
            pt(4) = 41
            nc(4) = 100.1234
            ec(4) = 175.1234
            '
            pt(5) = 56
            nc(5) = 150.1234
            ec(5) = 100.1234
            '
            pt(6) = 62
            nc(6) = 1000.1234
            ec(6) = 1050.1234
            '
            pt(7) = 73
            nc(7) = -1000.1234
            ec(7) = -1050.1234
            '
            pt(8) = 87
            nc(8) = 50.1234
            ec(8) = 1050.1234
            '
            pt(9) = 99
            nc(9) = 5.1234
            ec(9) = 5.1234
            '************************************
            Dim myFont As New Font("Arial", 8)
            For z As Integer = 1 To 9 ' cycle through point database to plot all points
                Ppt = pt(z)
                Pnc = nc(z)
                Pec = ec(z)
                '
                plotEast = Pec
                plotNorth = Pnc
                '
                Dim theta As Double = 90 * Math.PI / 180
                Dim y2 As Double = Math.Cos(theta) * plotEast - Math.Sin(theta) * plotNorth
                Dim x2 As Double = Math.Sin(theta) * plotEast - Math.Cos(theta) * plotNorth
                y2 = y2 + pb_Map.Height
                '
                Dim mx As New Matrix()
                mx.Rotate(-90) ' causes a need to plot y,x instead of x,y
                gP.Transform = mx
                gP.TranslateTransform(maxeast * -1, 0)
                gP.FillEllipse(Brushes.Red, plotNorth, plotEast, 6, 6)
                gP.ResetTransform()
                gP.DrawString(Ppt, myFont, Brushes.Black, x2 + offset, y2 + offset, StringFormat.GenericTypographic)
    
            Next
        End Sub

    • Marked as answer by El-sid Monday, August 5, 2013 1:06 PM
    Monday, August 5, 2013 3:38 AM
  • Thanks would have never got it with out your help.
    • Marked as answer by El-sid Monday, August 5, 2013 1:06 PM
    Monday, August 5, 2013 1:06 PM
  • I have struggle for weeks on finding the correct formula to allow "zooming In and zooming out" but orienting the point of interest in the center of the panel.

    You can't do that in one step.  The process I described assumes that zoom is always at the centre of the plot area.  That needs to be implemented as a first step.  Only when that is working can you consider zooming to a particular point.   It is done by combining a zoom with a scroll, but you can use a shortcut.  Before zooming, work out the centre point of the displayed image as a proportion of the available scroll range.  For instance an image at 100% (or less) will always be at (0.5,0.5) and has zero available scroll range because the display centre will be the coordinate centre.  An image zoomed to 2x could be offset between (0.25, 0.25) and (0.75,0.75) and therefore has a scroll range of 0.5.   

    If you take the available scroll range into account when calculating the position of the zoomed image as a proportion, then you can recalculate the required centre position at a different zoom by using the same proportion applied to the new available scroll range.  That was what I was referring to in the above description when I said that the scroll calculation has to relate to the current zoom level.

    I have changed the app in that I no longer want to use a bitmap as zooming only distorts the graphic.  I have created a selection box routine and it works the first time I select an area but to zoom in further things disappear.

    It sounds like you were resizing a bitmap to do the zooming, but you have discovered that won't work.  You must zoom by recalculating your coordinates and replotting.   You can zoom and scroll by creating an oversize bitmap, plotting everything, but displaying only a selected portion.  But if you do that you must place a limit on your zoom level in order to limit the bitmap size.  You still need to recalculate coordinates for zooming, but scrolling is much simplified.

    • Marked as answer by El-sid Monday, September 2, 2013 2:07 AM
    Friday, August 30, 2013 10:15 PM

All replies

  • These point number strings now are oriented vertical.

    Undo the rotate transform before drawing the text.  Or draw the text before doing the rotate transform (but you may have to take the translate transform into account for that).

    • Proposed as answer by Paul Ishak Monday, August 5, 2013 12:11 AM
    Sunday, August 4, 2013 11:13 PM
  • Tried every combination.  Not working.

    Any other options?  I found old code containing CreateRotatedFont option but does not work in 2010.

    Monday, August 5, 2013 12:13 AM
  • What did you try that didn't work? Show an example of the code where you draw the text without the rotate transform and then draw the points using the rotate.
    Monday, August 5, 2013 12:47 AM
  • Option Strict On
    Option Explicit On
    Option Infer Off
    Public Class Form1
        Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
            Dim StringSizeF As SizeF = e.Graphics.MeasureString("ThisisateststringN", New Font("Consolas", 8))
            Dim strSz As Size = New Size(CInt(StringSizeF.Width), CInt(StringSizeF.Height))
            e.Graphics.RotateTransform(90)
            e.Graphics.DrawString("Thisisateststring1", New Font("Consolas", 8), Brushes.Black, New Point(0, -strSz.Height))
            e.Graphics.ResetTransform()
            e.Graphics.DrawString("Thisisateststring2", New Font("Consolas", 8), Brushes.Black, New Point(0, strSz.Width))
            e.Graphics.RotateTransform(-90)
            e.Graphics.DrawString("Thisisateststring3", New Font("Consolas", 8), Brushes.Black, New Point(-strSz.Width - strSz.Height, strSz.Width))
            e.Graphics.ResetTransform()
            e.Graphics.RotateTransform(180)
            e.Graphics.DrawString("Thisisateststring4", New Font("Consolas", 8), Brushes.Black, New Point(-strSz.Width - strSz.Height, -strSz.Height))
            e.Graphics.ResetTransform()
        End Sub
    End Class


    “If you want something you've never had, you need to do something you've never done.”

    Don't forget to mark helpful posts and answers ! Answer an interesting question? Write a new article about it! My Articles
    *This post does not reflect the opinion of Microsoft, or its employees.

    Monday, August 5, 2013 12:58 AM
  • Thank you for your patience and assistance.

    I tried what you included above.  The issue is complicated by the need to plot the text at specific locations.   I have attached code.  The form has a panel pnl_map_drawing   and a picture box in the panel  pb_map.  I inserted the data to make it easier to reproduce. Thanks

      '
        ' PAINT PANEL
        '
        Private Sub pb_map_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles pb_Map.Paint
            Dim maxnorth As Integer = 1200
            Dim maxeast As Integer = 1200
            pb_Map.Width = maxeast
            pb_Map.Height = maxnorth
            
            '************
            'graphics settings
            '***********************
            Dim gP As Graphics
            gP = e.Graphics
            Dim mx As New Matrix()
            mx.Rotate(-90) ' causes a need to plot y,x instead of x,y
            gP.Transform = mx
            gP.TranslateTransform(maxeast * -1, 0)
    
            Dim Ppt As Integer ' plot variable
            Dim Pnc, Pec As Double ' plot variable
            Dim plotEast, plotNorth As Integer ' holds scaled northing easting
            Dim offset As Integer = 4 ' pixel offset from actual point location so pt number does not plot on top of the pt ellipse
            '************ data inserted to make illustration easier
            pt(1) = 100
            nc(1) = 100.1234
            ec(1) = 50.1234
            '
            pt(2) = 200
            nc(2) = 200.1234
            ec(2) = 50.1234
            '
            pt(3) = 302
            nc(3) = 200.1234
            ec(3) = 150.1234
            '
            pt(4) = 41
            nc(4) = 100.1234
            ec(4) = 175.1234
            '
            pt(5) = 56
            nc(5) = 150.1234
            ec(5) = 100.1234
            '
            pt(6) = 62
            nc(6) = 1000.1234
            ec(6) = 1050.1234
            '
            pt(7) = 73
            nc(7) = -1000.1234
            ec(7) = -1050.1234
            '
            pt(8) = 87
            nc(8) = 50.1234
            ec(8) = 1050.1234
            '
            pt(9) = 99
            nc(9) = 5.1234
            ec(9) = 5.1234
            '************************************
            For z As Integer = 1 To 9 ' cycle through point database to plot all points
                Ppt = pt(z)
                Pnc = nc(z)
                Pec = ec(z)
    
                Dim myFont As New Font("Arial", 8)
                '
                plotEast = Pec
                plotNorth = Pnc
                '
                gP.FillEllipse(Brushes.Red, plotNorth, plotEast, 6, 6)
                gP.DrawString(Ppt, myFont, Brushes.Black, plotNorth + offset, plotEast + offset, StringFormat.GenericTypographic)
            Next
        End Sub

    Monday, August 5, 2013 1:37 AM
  • To print the text un-rotated at the rotated point you have to calculate the text position taking the rotation into account then reset the transform before doing the printing. The calculation is simply the opposite of the rotate transform and then the opposite of the translate transform.

        '
        ' PAINT PANEL
        '
        Private Sub pb_map_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles pb_Map.Paint
            Dim maxnorth As Integer = 1200
            Dim maxeast As Integer = 1200
            pb_Map.Width = maxeast
            pb_Map.Height = maxnorth
    
            '************
            'graphics settings
            '***********************
            Dim gP As Graphics
            gP = e.Graphics
    
            Dim Ppt As Integer ' plot variable
            Dim Pnc, Pec As Double ' plot variable
            Dim plotEast, plotNorth As Integer ' holds scaled northing easting
            Dim offset As Integer = 4 ' pixel offset from actual point location so pt number does not plot on top of the pt ellipse
            '************ data inserted to make illustration easier
            Dim pt(9) As Double
            Dim nc(9) As Double
            Dim ec(9) As Double
    
            pt(1) = 100
            nc(1) = 100.1234
            ec(1) = 50.1234
            '
            pt(2) = 200
            nc(2) = 200.1234
            ec(2) = 50.1234
            '
            pt(3) = 302
            nc(3) = 200.1234
            ec(3) = 150.1234
            '
            pt(4) = 41
            nc(4) = 100.1234
            ec(4) = 175.1234
            '
            pt(5) = 56
            nc(5) = 150.1234
            ec(5) = 100.1234
            '
            pt(6) = 62
            nc(6) = 1000.1234
            ec(6) = 1050.1234
            '
            pt(7) = 73
            nc(7) = -1000.1234
            ec(7) = -1050.1234
            '
            pt(8) = 87
            nc(8) = 50.1234
            ec(8) = 1050.1234
            '
            pt(9) = 99
            nc(9) = 5.1234
            ec(9) = 5.1234
            '************************************
            Dim myFont As New Font("Arial", 8)
            For z As Integer = 1 To 9 ' cycle through point database to plot all points
                Ppt = pt(z)
                Pnc = nc(z)
                Pec = ec(z)
                '
                plotEast = Pec
                plotNorth = Pnc
                '
                Dim theta As Double = 90 * Math.PI / 180
                Dim y2 As Double = Math.Cos(theta) * plotEast - Math.Sin(theta) * plotNorth
                Dim x2 As Double = Math.Sin(theta) * plotEast - Math.Cos(theta) * plotNorth
                y2 = y2 + pb_Map.Height
                '
                Dim mx As New Matrix()
                mx.Rotate(-90) ' causes a need to plot y,x instead of x,y
                gP.Transform = mx
                gP.TranslateTransform(maxeast * -1, 0)
                gP.FillEllipse(Brushes.Red, plotNorth, plotEast, 6, 6)
                gP.ResetTransform()
                gP.DrawString(Ppt, myFont, Brushes.Black, x2 + offset, y2 + offset, StringFormat.GenericTypographic)
    
            Next
        End Sub

    • Marked as answer by El-sid Monday, August 5, 2013 1:06 PM
    Monday, August 5, 2013 3:38 AM
  • Thanks would have never got it with out your help.
    • Marked as answer by El-sid Monday, August 5, 2013 1:06 PM
    Monday, August 5, 2013 1:06 PM
  • Acamar,

    You seem to have an understanding of this plotting scenario, can I bother you with an extension to this plotting issue.  If I wanted to see all of the points at once in the panel, maintaining the font size how would I inject code to allow a "zoom extents" to show all points in the panel window, and also how would I vary the scale to "zoom in" to points that are very close together, still maintaining the font size? Of course I need to continue to relate to the "plotted coordinates" so that I could query the point with a mouse click.

    El sid

    Tuesday, August 6, 2013 12:25 AM
  • You currently have a couple of shortcuts that must be removed before you can consider zooming or scrolling.  When you have done that there is no need to be concerned about text size - the text will display at the correct size regardless of the zoom level.

    However, this process is difficult to combine with your use of the transforms.  In fact, getting rid of the transforms actually makes the subsequent extensions simpler, but there is still quite a bit involved.

    Currently you are sizing the window to the points range, and you are offsetting the plotting position, using information that you know about the points values.  You need to change this so that the point values are scaled to the window size.  So if the point X values range from -1000 to 1000 and your window is 100 pixels wide, you need a function that converts the plot point to the pixel position.  So a plot point X value of -500 would become 25, a position of 0 becomes 50, +500 is 75, and so on. 

    That formula will need to have the range or spread of the points values, and the minimum points value, as well as the current panel size.

    At the same time, you should change N to X and E to Y, to get the plot the right way up.  Those two changes do what you are currently doing by using a fixed size window and then doing a translation and  rotation.  The separate calculation of the text printing positions is no longer required (just the offset). 

    At the same time as you create those function, create the inverse function that you will use to translate a mouse click position within the panel into a plot point.

    Once that is in place and working you can add a control to zoom. Zooming is done by inserting another scaling calculation, based on the zoom factor, in between the pixel position calculated in the first scaling method and the actual pixel drawing.

    So you need a zoom scaling calculation that takes a  pixel position in the assumed window size, and scales it to a position in the zoomed window.  If the actual window is 100 pixels but the zoom factor is 2, then a pixel position of X becomes X + (50 - x) / 2 (do a few with pencil and paper to see why).

    You will also need the reverse of this method to convert the mouse click position back to an unzoomed pixel position so it can be converted back to a plot position.

    Once that is in place and working, you can consider scrolling.  This is another conversion, inserted between the zoomed pixel calculation and the actual drawing, that offsets (+ or -) the pixel position according to the corresponding scroll factor.  That calculation is simple, except that you have to carefully consider what the scroll factor means in terms of scrolling the whole image - it has to relate to the zoomed window state.  Start by assuming there's no zooming, and then see the effect that zooming has on the scrolling calculation to work out whether an adjustment is required. This problem comes about because a zoom operation should work on the centre of the displayed image, and that centre changes according to the scoll. If you want the zooming operation to respect the current scroll position, you will probably need a routine that saves the scroll position, does the zoom, and resets the scoll.

    Tuesday, August 6, 2013 2:23 AM
  • Not sure if my last reply got through, but thank you again for your advise.  I will try to make the adjustments.  I was using a picture box to do the plotting, do you think that I should eliminate that and work directly on the panel object?  I again thank you and will try not to trouble you again.
    Tuesday, August 6, 2013 11:34 PM
  • I was using a picture box to do the plotting, do you think that I should eliminate that and work directly on the panel object?

    My preference is always to work directly on the form, but the panel is effectively the same. The PictureBox offers no advantages over the panel, and comes with considerable irrelevant baggage.

    Please feel free to ask a new question at any time.

    Tuesday, August 6, 2013 11:48 PM

  • My preference is always to work directly on the form, but the panel is effectively the same. The PictureBox offers no advantages over the panel, and comes with considerable irrelevant baggage.

    Hi Acamar,  Hi  El-sid

    Just some added trivia. I think (depending on VS version), panels do not have double buffering option, but pictureboxes do.


    Leon C Stanley - - A dinky di VBer - - Code is like fresh baked bread - it goes stale after a while - - so why try to immortalize it ? and turn it into a Class? ^^ :-)

    Wednesday, August 7, 2013 8:00 AM
  • Acamar,  You have been so helpful with my previous problem, may I trouble you with your input on my current problem.  Still relating to graphics and the display of data points having real world coordinates and relating them back to display on the graphic object being a panel within a form.  I have struggle for weeks on finding the correct formula to allow "zooming In and zooming out" but orienting the point of interest in the center of the panel. I have my small example application in a zip file but not sure if you have time to address my issues.  I have changed the app in that I no longer want to use a bitmap as zooming only distorts the graphic.  I have created a selection box routine and it works the first time I select an area but to zoom in further things disappear.

    Let me know if you can help and how I might send you my zip file.

    El Sid

    Friday, August 30, 2013 1:07 PM
  • I have struggle for weeks on finding the correct formula to allow "zooming In and zooming out" but orienting the point of interest in the center of the panel.

    You can't do that in one step.  The process I described assumes that zoom is always at the centre of the plot area.  That needs to be implemented as a first step.  Only when that is working can you consider zooming to a particular point.   It is done by combining a zoom with a scroll, but you can use a shortcut.  Before zooming, work out the centre point of the displayed image as a proportion of the available scroll range.  For instance an image at 100% (or less) will always be at (0.5,0.5) and has zero available scroll range because the display centre will be the coordinate centre.  An image zoomed to 2x could be offset between (0.25, 0.25) and (0.75,0.75) and therefore has a scroll range of 0.5.   

    If you take the available scroll range into account when calculating the position of the zoomed image as a proportion, then you can recalculate the required centre position at a different zoom by using the same proportion applied to the new available scroll range.  That was what I was referring to in the above description when I said that the scroll calculation has to relate to the current zoom level.

    I have changed the app in that I no longer want to use a bitmap as zooming only distorts the graphic.  I have created a selection box routine and it works the first time I select an area but to zoom in further things disappear.

    It sounds like you were resizing a bitmap to do the zooming, but you have discovered that won't work.  You must zoom by recalculating your coordinates and replotting.   You can zoom and scroll by creating an oversize bitmap, plotting everything, but displaying only a selected portion.  But if you do that you must place a limit on your zoom level in order to limit the bitmap size.  You still need to recalculate coordinates for zooming, but scrolling is much simplified.

    • Marked as answer by El-sid Monday, September 2, 2013 2:07 AM
    Friday, August 30, 2013 10:15 PM
  • Thanks Again Acamar!  Finally understood what you were describing everything works like a charm.

    El Sid

    Monday, September 2, 2013 2:08 AM