Results 1 to 12 of 12

Thread: Basic Graphics Logic Help

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Jan 2013
    Posts
    177

    Basic Graphics Logic Help

    Hi,

    I have been having a very hard time wrapping my head around drawing in vb.net

    Here is what I am doing,

    vb.net Code:
    1. Public Class Form1
    2.     Dim _Pen As Pen
    3.     Dim min As System.Drawing.Point = New Point(521, 211)
    4.     Dim max As System.Drawing.Point = New Point(1261, 1249)
    5.     Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    6.    
    7.         If max.X = 0 Then
    8.             Exit Sub
    9.         End If
    10.  
    11.         Dim Img As New Bitmap(max.X, max.Y)
    12.  
    13.         Dim g As Graphics = Graphics.FromImage(Img)
    14.  
    15.         g.Clear(Color.White)
    16.  
    17.  
    18.  
    19.         _Pen = New Pen(Brushes.LightBlue, 5)
    20.         _Pen.DashStyle = DashStyle.Dash
    21.  
    22.         g.DrawLine(_Pen, min.X, min.Y, max.X, max.Y)
    23.  
    24.  
    25.  
    26.         PictureBox1.Image = Img
    27.     End Sub
    28.  
    29. End Class

    So I am creating a image that is 1261 x 1249 and then I draw on this image a line from the bottom to the top.

    I then set this image to my picture box which has dimensions of 638 x 723. But the line never shows up or shows up at a random place. It is very furstrating lol.

    Does my logic make sense?

  2. #2
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,464

    Re: Basic Graphics Logic Help

    I tried your code. here's what it drew:

    Name:  12-08-2013 22.20.29.jpg
Views: 250
Size:  33.3 KB

  3. #3
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,711

    Re: Basic Graphics Logic Help

    The reason why it wouldn't show up is because you picturebox isn't big enough. It will appear off the visible portion of your picturebox. If you want to appear properly, then either resize your picturebox or set the SizeMode to AutoSize, StretchImage, or Zoom.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  4. #4
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Basic Graphics Logic Help

    You code makes sense to me. As far as I can see you are drawing a diagonal dashed light blue line from the top left (min) to the bottom right (max) corner of a rectangle. That should work correctly on the image Img.

    But there is one thing that you haven't said: what is the SizeMode setting of the PictureBox? It will determine how the Image Img will be displayed in the PictureBox. You can set the SizeMode in the Designer or in your code.

    For example, if you have SizeMode = None, you should be able to see part of your line. That's because the line doesn't start until (521, 211), which is near the right-hand side of the PictureBox. But if you set SizeMode = StretchImage you should be able to see the whole image compressed into the PictureBox. If you don't want to think about the SizeMode, you should start off with the image Img the same size as the PictureBox (to be more accurate, the PictureBox ClientRectangle, which excludes the border, if any).

    BB

    EDIT: actually dday9 said exactly what I meant in fewer words. I'm always too slow!

  5. #5

    Thread Starter
    Addicted Member
    Join Date
    Jan 2013
    Posts
    177

    Re: Basic Graphics Logic Help

    Thanks for the input guys. So If I want that line to run across the form and all of it to be visible?

    I would rather not use the SizeMode, as this screws up all the graphic paths I have and makes my objects unclickable :P

    Could someone assist me in the logic to convert all the values I have into the picturebox size?

    I tried this but it is still a bit off. I am multiplying all of my x and y values by (Height of picturebox/my max Y) and (Wdith of picturebox/my max x)
    Code:
    Imports System.Drawing.Drawing2D
    
    Public Class Form1
        Dim _Pen As Pen
        Dim min As System.Drawing.Point = New Point(521, 211)
        Dim max As System.Drawing.Point = New Point(1261, 1249)
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
       
            If max.X = 0 Then
                Exit Sub
            End If
    
            Dim Img As New Bitmap(PictureBox1.Height, PictureBox1.Width)
    
            Dim g As Graphics = Graphics.FromImage(Img)
    
            g.Clear(Color.White)
    
            Dim ratiox As Single = PictureBox1.Width / max.X
            Dim ratioy As Single = PictureBox1.Height / max.Y
    
            _Pen = New Pen(Brushes.LightBlue, 5)
            _Pen.DashStyle = DashStyle.Dash
    
            g.DrawLine(_Pen, min.X * ratiox, min.Y * ratioy, max.X * ratiox, max.Y * ratioy)
    
    
            PictureBox1.Image = Img
        End Sub
    
        Private Sub PictureBox1_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
            Label1.Text = "X : " & e.X & " Y : " & e.Y
        End Sub
    End Class

  6. #6
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Basic Graphics Logic Help

    To start with, you are not getting the line to fill the picture because you need to translate (shift) the coordinates as well as scale them. For a single line, you could simply set X=0 and Y=0 in Graphics.DrawLine. But if you are drawing more than 1 line or other shapes it would be pointless do that for each one separately. Instead you should transform the Graphics object, which will apply to all the lines etc.

    The reason dday and I mentioned SizeMode is because you are doing your drawing to a bitmap, and then using it as the PictureBox Image. That is the "easy" way of using a PictureBox, but it won't help you with hit-testing,. So I suggest you start by doing your graphics the Paint event of the PictureBox, instead of using a separate bitmap. Here's an example:

    Code:
    Public Class Form1
    
    	Private MinX, MinY, MaxX, MaxY As Integer
    	Private scaleX, scaleY As Single
    
    	Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    		'Calculate the minimum and maximum X and Y values of what you want to draw here. 
    		'For the while, let's just insert your test values.
    		MinX = 521
    		MinY = 211
    		MaxX = 1261
    		MaxY = 1249
    		'Calculate the X and Y scaling factors
    		scaleX = CSng(PictureBox1.ClientSize.Width / (MaxX - MinX))
    		scaleY = CSng(PictureBox1.ClientSize.Height / (MaxY - MinY))
                   'Trigger the Paint event with the new data.
    		PictureBox1.Invalidate()
    	End Sub
    
    	Private Sub PictureBox1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
    		If scaleX = 0 Then Exit Sub
                    'Transform the scale and the coordinates.
    		e.Graphics.ScaleTransform(scaleX, scaleY)
    		e.Graphics.TranslateTransform(-MinX, -MinY)
                    'Draw the lines etc.
    		Using _Pen As New Pen(Color.LightBlue, 5) With {.DashStyle = Drawing2D.DashStyle.Dash}
    			e.Graphics.DrawLine(_Pen, MinX, MinY, MaxX, MaxY)
    		End Using
    	End Sub
    
    End Class
    Note that I haven't used Points min and max, because if you have more than one line etc. the minimum and maximum values may not be the same points. It's a bit strange to use different scaling factors for the X and Y directions: normally you would use just one scaling factor. Maybe you have some good reason for doing that, but otherwise you can work out which scaling gives the best fit, the X direction or the Y direction.

    BB

  7. #7

    Thread Starter
    Addicted Member
    Join Date
    Jan 2013
    Posts
    177

    Re: Basic Graphics Logic Help

    Quote Originally Posted by boops boops View Post
    To start with, you are not getting the line to fill the picture because you need to translate (shift) the coordinates as well as scale them. For a single line, you could simply set X=0 and Y=0 in Graphics.DrawLine. But if you are drawing more than 1 line or other shapes it would be pointless do that for each one separately. Instead you should transform the Graphics object, which will apply to all the lines etc.

    The reason dday and I mentioned SizeMode is because you are doing your drawing to a bitmap, and then using it as the PictureBox Image. That is the "easy" way of using a PictureBox, but it won't help you with hit-testing,. So I suggest you start by doing your graphics the Paint event of the PictureBox, instead of using a separate bitmap. Here's an example:

    Code:
    Public Class Form1
    
    	Private MinX, MinY, MaxX, MaxY As Integer
    	Private scaleX, scaleY As Single
    
    	Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    		'Calculate the minimum and maximum X and Y values of what you want to draw here. 
    		'For the while, let's just insert your test values.
    		MinX = 521
    		MinY = 211
    		MaxX = 1261
    		MaxY = 1249
    		'Calculate the X and Y scaling factors
    		scaleX = CSng(PictureBox1.ClientSize.Width / (MaxX - MinX))
    		scaleY = CSng(PictureBox1.ClientSize.Height / (MaxY - MinY))
                   'Trigger the Paint event with the new data.
    		PictureBox1.Invalidate()
    	End Sub
    
    	Private Sub PictureBox1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
    		If scaleX = 0 Then Exit Sub
                    'Transform the scale and the coordinates.
    		e.Graphics.ScaleTransform(scaleX, scaleY)
    		e.Graphics.TranslateTransform(-MinX, -MinY)
                    'Draw the lines etc.
    		Using _Pen As New Pen(Color.LightBlue, 5) With {.DashStyle = Drawing2D.DashStyle.Dash}
    			e.Graphics.DrawLine(_Pen, MinX, MinY, MaxX, MaxY)
    		End Using
    	End Sub
    
    End Class
    Note that I haven't used Points min and max, because if you have more than one line etc. the minimum and maximum values may not be the same points. It's a bit strange to use different scaling factors for the X and Y directions: normally you would use just one scaling factor. Maybe you have some good reason for doing that, but otherwise you can work out which scaling gives the best fit, the X direction or the Y direction.

    BB
    Thank You very much for the explanation.

    When I used the transform and translate before my hittest were all wrong, but I guess that was because I was not redrawing the box?
    So if I were to add all of my drawings into the paint event, it should work even if I use the zoom sizemode?

    Let me explain what I am doing, the project above was just a test project.

    My program talks to another 3rd party through the COM interface, which is where I obtain the Mix and Max values. I get these to draw the basic outline of the system.
    In the program there are buttons to select specific paths, when a path is selected it is drawn in the picturebox and clicking on the path yields more info.

    So in order to get it working correctly now I will have to do the following:
    -I will calculate the scales at the beginning when the min and max from the program is obtained.
    -Move all of my graphics code into the paint even from the Picturebox and have it transformed to the scale.

    I am sorry I havent posted my code, but all of the graphics are mixed with other things that happens when a path is selected. I guess I will have to separate everything now.

    Hopefully this works. Thanks again

  8. #8

    Thread Starter
    Addicted Member
    Join Date
    Jan 2013
    Posts
    177

    Re: Basic Graphics Logic Help

    Almost there.

    My lines appear to be upside down and the HIT test dont work :\

    Here is the code now

    vb.net Code:
    1. Dim _SecondaryPaths As New List(Of System.Drawing.Drawing2D.GraphicsPath)
    2.     Dim _Paths As New List(Of System.Drawing.Drawing2D.GraphicsPath)
    3.     Dim namepath As New List(Of NamedPath)
    4.  
    5. Public Sub Draw()
    6.         scaleX = CSng(PictureBox1.ClientSize.Width / (max.X - min.X))
    7.         scaleY = CSng(PictureBox1.ClientSize.Height / (max.Y - min.Y))
    8.         PictureBox1.Invalidate()
    9. End sub
    10. Private Sub PictureBox1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
    11.  
    12.   e.Graphics.ScaleTransform(scaleX, scaleY)
    13.   e.Graphics.TranslateTransform(-min.X, -min.Y)
    14.  
    15.         _Pen = New Pen(Brushes.LightBlue, 5)
    16.         _Pen.DashStyle = DashStyle.Dash
    17.  
    18.         e.Graphics.DrawLine(_Pen, min.X, min.Y, min.X, max.Y)
    19.         e.Graphics.DrawLine(_Pen, min.X, max.Y, max.X, max.Y)
    20.         e.Graphics.DrawLine(_Pen, max.X, max.Y, max.X, min.Y)
    21.         e.Graphics.DrawLine(_Pen, max.X, min.Y, min.X, min.Y)
    22.  
    23.         Dim graphiccounter As Integer = 0
    24.  
    25.         _Paths.Clear()
    26.         namepath.Clear()
    27.  
    28.         For Each row As DataGridViewRow In DataGridView2.Rows
    29.  
    30.             If row.Visible = True Then
    31.  
    32.  
    33.                 _Paths.Add(New GraphicsPath)
    34.                 namepath.Add(New NamedPath)
    35.  
    36.                 _SecondaryPaths.Add(New GraphicsPath)
    37.  
    38.                 'Over here my program talks to other program and gets all the x,y co-ordinates.
    39.                 'For each path that I get from the other program, they are defined with multiple points
    40.                 'the number of points is stored in result
    41.  
    42.                 For k = 1 To result - 1
    43.  
    44.                     x_loc(k) = x(k)
    45.                     y_loc(k) = y(k)
    46.                     x_loc(k + 1) = x(k + 1)
    47.                     y_loc(k + 1) = y(k + 1)
    48.  
    49.  
    50.  
    51.                
    52.                     If drawtype = draw.onlypath Then
    53.                         _Paths(graphiccounter).AddLine(x_loc(k), y_loc(k), x_loc(k + 1), y_loc(k + 1))
    54.                         namepath(graphiccounter).Name = row.Cells("Id").Value
    55.                         namepath(graphiccounter).Path = _Paths(graphiccounter)
    56.                         'e.graphics.FillEllipse(Brushes.Black, x_loc(k + 1) - 4, y_loc(k + 1) - 4, 8, 8)
    57.                     ElseIf drawtype = draw.withpath Or drawtype = draw.pathwhenselected Then
    58.                         _SecondaryPaths(graphiccounter).AddLine(x_loc(k), y_loc(k), x_loc(k + 1), y_loc(k + 1))
    59.                     End If
    60.  
    61.                  
    62.                 Next
    63.  
    64. 'This draws a transparent line over the paths with a width thicker than the paths. This is what the hit test checks
    65.         For der = 0 To namepath.Count - 1
    66.  
    67.                     _Pen = New Pen(Brushes.Transparent, 20)
    68.             e.Graphics.DrawPath(_Pen, namepath(der).Path)
    69.             graphiccounter += 1
    70.  
    71.         Next
    72.  
    73.     Protected Sub OnMeouseClick(sender As Object, ByVal e As MouseEventArgs) Handles PictureBox1.MouseClick
    74.      
    75.  
    76.         Dim mp As New Point(e.X, e.Y)
    77.         For k = 0 To namepath.Count - 1
    78.             If Me.namepath(k).Path.IsOutlineVisible(mp, _Pen) = False Then
    79.                 Me._MouseIsOnLine = False
    80.             Else
    81.        'I Process what needs to be if the line is clicked
    82.                
    83.                 Me._MouseIsOnLine = True
    84.                 Exit For
    85.             End If
    86.         Next
    87.    
    88.    
    89.     End Sub



    EDIT: For some reason, even thought my graphics show up on the sheet, the paths for the hit test show up outside of the picture box

    Ok Say I have a path drawn from 200,200 to 1000,1000. When I click these numbers are stored in the paths array so it checks if the point I clicked on in on the given path. BUT because I used

    vb.net Code:
    1. e.Graphics.ScaleTransform(scaleX, scaleY)
    2.   e.Graphics.TranslateTransform(-min.X, -min.Y)

    All those points have been changed. I tried taking the point clicked and multiplying it by the scale and add the translate but it still is off :\

    Found this but still trying to figure out the the matrix stuff happening in the Paint Function

    http://stackoverflow.com/questions/1...nsformed-paths
    Last edited by Crzyrio; Aug 15th, 2013 at 09:22 AM.

  9. #9

    Thread Starter
    Addicted Member
    Join Date
    Jan 2013
    Posts
    177

    Re: Basic Graphics Logic Help

    SO CLOSE
    Thanks again guys, but just one more thing.

    For some reason the drawings are always ofset to much and does not fully display in the window.

    I cant find any reason why it would happen. Can anyone pinpoint it in my code? :S
    Attached Images Attached Images  
    Last edited by Crzyrio; Aug 15th, 2013 at 11:53 AM.

  10. #10
    PowerPoster dunfiddlin's Avatar
    Join Date
    Jun 2012
    Posts
    8,245

    Re: Basic Graphics Logic Help

    The Graphics Appear Fine, but when I do
    Well, don't do it then!

    You're essentially changing the order and/or time at which things are done which can effect things in a surprising (though entirely logical) way. It takes some getting used to.

    Butt my Graphics are all still upside down :\
    You have remembered that Y co-ordinates increase as you go down not up as in standard graphing so that the top left corner is 0,0?
    As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"

    Reviews: "dunfiddlin likes his DataTables" - jmcilhinney

    Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!

  11. #11

    Thread Starter
    Addicted Member
    Join Date
    Jan 2013
    Posts
    177

    Re: Basic Graphics Logic Help

    Quote Originally Posted by dunfiddlin View Post
    Well, don't do it then!

    You're essentially changing the order and/or time at which things are done which can effect things in a surprising (though entirely logical) way. It takes some getting used to.



    You have remembered that Y co-ordinates increase as you go down not up as in standard graphing so that the top left corner is 0,0?
    But I need to do it in order for the Hittest to work :|

    Thanks, I just changed all the values to

    Picturebox1.Height - original co-ordinate

    Now just working on figuring out why some of the graphics are getting cut off.

  12. #12
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Basic Graphics Logic Help

    Hi Cryzyrio, life is too short to get involved in the code you posted in #8, but I'd like to offer you a working example of how to do hit testing on GraphicsPaths in a transformed Graphics. To keep things simple I'll adapt the same code as I posted. The main differences are:
    1. it uses a path (gPath) with Graphics.DrawPath to draw the line instead of Graphics.DrawLine
    2. it uses two matrices, matrix and inverseMatrix. matrix is for transforming the Graphics in the Paint sub. The inverseMatrix is used in the MouseClick sub. It reverses the process, to find where the point actually clicked in the PictureBox is in "world" coordinates (the coordinates of the original data and the GraphicsPaths).
    3. it uses GraphicsPath.IsOutlineVisible to perform the hit test. This takes a pen as one of its argumentsl; only purpose is to widen the hit area to make it easier to use. This pen doesn't have to be the same as the one used for drawing

    Code:
    Public Class Form1
    
    	Private MinX, MinY, MaxX, MaxY As Integer
    	Private scaleX, scaleY As Single
    
    	Private gPath As New Drawing2D.GraphicsPath
    	Private matrix, inverseMatrix As New Drawing2D.Matrix
    
    	Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    		'Calculate the minimum and maximum X and Y values of what you want to draw here. 
    		'For the while, let's just insert your test values.
    		MinX = 521
    		MinY = 211
    		MaxX = 1261
    		MaxY = 1249
    
    		'Create the GraphicsPath
    		gPath.AddLine(MinX, MinY, MaxX, MaxY)
    
    		'Calculate the X and Y scaling factors
    		scaleX = CSng(PictureBox1.ClientSize.Width / (MaxX - MinX))
    		scaleY = CSng(PictureBox1.ClientSize.Height / (MaxY - MinY))
    
    		'create the matrix
    		matrix.Scale(scaleX, scaleY)
    		matrix.Translate(-MinX, -MinY)
    
    		'create the inverse matrix 
    		inverseMatrix = matrix.Clone
    		inverseMatrix.Invert()
    
    		'Trigger the Paint event with the new data.
    		PictureBox1.Invalidate()
    	End Sub
    
    	Private Sub PictureBox1_MouseClick(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseClick
    
    		'get the "world" equivalent of the mouse click position
    		Dim pts() As Point = {e.Location}
    		inverseMatrix.TransformPoints(pts)
    		Dim wLocation As Point = pts(0)
    
    		'hit test:
    		Using pn As New Pen(Color.Black, 10)
    			If gPath.IsOutlineVisible(wLocation, pn) Then
    				MessageBox.Show("click location = " & e.Location.ToString & vbCrLf & _
    				 "world location = " & wLocation.ToString)
    			End If
    		End Using
    
    	End Sub
    
    	Private Sub PictureBox1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
    
    		'Transform the scale and the coordinates.
    		e.Graphics.Transform = matrix
    
    		'Draw the lines etc.
    		Using _Pen As New Pen(Color.LightBlue, 5) With {.DashStyle = Drawing2D.DashStyle.Dash}
    			e.Graphics.DrawPath(_Pen, gPath)
    		End Using
    
    	End Sub
    
    End Class
    BB

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