Results 1 to 9 of 9

Thread: [RESOLVED] Graphing a Circle in a Coordinate Plane with inputs Center and Radius

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Aug 2012
    Posts
    30

    Resolved [RESOLVED] Graphing a Circle in a Coordinate Plane with inputs Center and Radius

    I'm trying to plot a circle on a Coordinate Plane. Now my problem is that whenever I'm trying to input something (for example, C:0,0 R:10), it doesn't plot correctly in the cartesian coordinate plane.

    I've been trying to solve this for like hours but it seems like I can't fix this on my own. I think my problem lies within the Button1_Click event, I've tried changing the values of variables x, y and r but still can't get it right. Any help would be appreciated. Thanks.

    My Code so far:

    Code:
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
            g = Me.CreateGraphics()
        End Sub
    
        Private Sub Form1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles Me.Paint   //the drawing of Cartesian Plane
            e.Graphics.FillRectangle(Brushes.White, New Rectangle(300, 10, 500, 491))
            e.Graphics.DrawLine(Pens.Black, New Point(555, 10), New Point(555, 500))
            e.Graphics.DrawLine(Pens.Black, New Point(300, 250), New Point(800, 250))
    
        End Sub
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            If TextBox1.TextLength <> 0 And TextBox2.TextLength <> 0 And TextBox3.TextLength <> 0 Then
                Click = True
                g.Clear(DefaultBackColor)
                g.FillRectangle(Brushes.White, New Rectangle(300, 10, 500, 491))
                g.DrawLine(Pens.Black, New Point(555, 10), New Point(555, 500))
                g.DrawLine(Pens.Black, New Point(300, 250), New Point(800, 250))
                x = CType(TextBox1.Text, Integer) * distance
                y = CType(TextBox2.Text, Integer) * distance
                r = CType(TextBox3.Text, Integer) * distance
                g.FillEllipse(Brushes.Black, x, y, 7, 7)
                g.DrawEllipse(Pens.Black, x, y, r, r)
    
            Else
                MessageBox.Show("Please Complete All Fields Before Plotting!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
            End If
        End Sub
    Last edited by angel06; Oct 17th, 2015 at 11:07 AM.

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

    Re: Graphing a Circle in a Coordinate Plane with inputs Center and Radius

    You should do all your drawing from the Form1_Paint event handler.
    If you draw using Me.CreateGraphics, that is only temporary on the screen area of the form, and is not the way you are suppose to be drawing.
    In the Button click you can just set a flag indicating that the drawing is valid, and then Invalidate the form.
    In the Paint event, after you draw you rectangle and line, check the flag to see if it is set, and if so, do the drawing code (moved) that you had in your button.
    I haven't tested the code yet to see if there is a problem with your drawing, so I will give that a try since you haven't really given a description of what it is drawing and what you expect it to be drawing.
    Code:
    Public Class Form1
    
        Private x As Integer
        Private y As Integer
        Private r As Integer
        Private distance As Integer = 5
        Private blackPen As New Pen(Color.Red, 1)
    
        Private DrawIt as Boolean
    
        Private Sub Form1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles Me.Paint   //the drawing of Cartesian Plane
            e.Graphics.FillRectangle(Brushes.White, New Rectangle(300, 10, 500, 491))
            e.Graphics.DrawLine(Pens.Black, New Point(555, 10), New Point(555, 500))
            e.Graphics.DrawLine(Pens.Black, New Point(300, 250), New Point(800, 250))
    
            If DrawIt then
                x = CType(TextBox1.Text, Integer) * distance
                y = CType(TextBox2.Text, Integer) * distance
                r = CType(TextBox3.Text, Integer) * distance
                g.FillEllipse(Brushes.Black, x, y, 7, 7)
                g.DrawEllipse(Pens.Black, x, y, r, r)
            End If
        End Sub
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            If TextBox1.TextLength <> 0 And TextBox2.TextLength <> 0 And TextBox3.TextLength <> 0 Then
                DrawIt = True
                Click = True
                Invalidate()
            Else
                MessageBox.Show("Please Complete All Fields Before Plotting!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
            End If
        End Sub
    End Class
    If your problem is just that the circle isn't centered at X,Y that is because X,Y defines the upperLeft corner of the bounding box, and width and height are the size of the bounding box.
    To center the circle at X,Y offset your bounding box negatively by the radius and the width and height are the diameter, i.e. twice the radius
    g.FillEllipse(Brushes.Black, x-7, y-7, 2*7, 2*7)
    Last edited by passel; Oct 17th, 2015 at 07:28 AM.

  3. #3

    Thread Starter
    Junior Member
    Join Date
    Aug 2012
    Posts
    30

    Re: Graphing a Circle in a Coordinate Plane with inputs Center and Radius

    Quote Originally Posted by passel View Post
    You should do all your drawing from the Form1_Paint event handler.
    If you draw using Me.CreateGraphics, that is only temporary on the screen area of the form, and is not the way you are suppose to be drawing.
    In the Button click you can just set a flag indicating that the drawing is valid, and then Invalidate the form.
    In the Paint event, after you draw you rectangle and line, check the flag to see if it is set, and if so, do the drawing code (moved) that you had in your button.
    I haven't tested the code yet to see if there is a problem with your drawing, so I will give that a try since you haven't really given a description of what it is drawing and what you expect it to be drawing.
    Code:
    Public Class Form1
    
        Private x As Integer
        Private y As Integer
        Private r As Integer
        Private distance As Integer = 5
        Private blackPen As New Pen(Color.Red, 1)
    
        Private DrawIt as Boolean
    
        Private Sub Form1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles Me.Paint   //the drawing of Cartesian Plane
            e.Graphics.FillRectangle(Brushes.White, New Rectangle(300, 10, 500, 491))
            e.Graphics.DrawLine(Pens.Black, New Point(555, 10), New Point(555, 500))
            e.Graphics.DrawLine(Pens.Black, New Point(300, 250), New Point(800, 250))
    
            If DrawIt then
                x = CType(TextBox1.Text, Integer) * distance
                y = CType(TextBox2.Text, Integer) * distance
                r = CType(TextBox3.Text, Integer) * distance
                g.FillEllipse(Brushes.Black, x, y, 7, 7)
                g.DrawEllipse(Pens.Black, x, y, r, r)
            End If
        End Sub
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            If TextBox1.TextLength <> 0 And TextBox2.TextLength <> 0 And TextBox3.TextLength <> 0 Then
                DrawIt = True
                Click = True
                Invalidate()
            Else
                MessageBox.Show("Please Complete All Fields Before Plotting!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
            End If
        End Sub
    End Class
    If your problem is just that the circle isn't centered at X,Y that is because X,Y defines the upperLeft corner of the bounding box, and width and height are the size of the bounding box.
    To center the circle at X,Y offset your bounding box negatively by the radius and the width and height are the diameter, i.e. twice the radius
    g.FillEllipse(Brushes.Black, x-7, y-7, 2*7, 2*7)
    I've tried your suggestion g.FillEllipse(Brushes.Black, x-7, y-7, 2*7, 2*7) and it worked. Now the problem is the circle is not plotted correctly on the coordinate plane that I drew. For example I input its center as (10,0) and its radius as 15, this graph of circle should be in the first quadrant. But in my case, it doesn't plot on the first quadrant.

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

    Re: Graphing a Circle in a Coordinate Plane with inputs Center and Radius

    Which quadrant to you consider the First (Upper/Left, Upper/Right, ?)

    In any case, what I would normally expect for a graph is that 0,0 be in the center where your lines cross, and that +,+ coordinates be in the upper right.
    My modification of your code to have that orientation would look like this. If you plot 0,0,20 then 0,0,20 shows up centered on the two axis and 100,100,20 shows up in the upper right.
    Code:
    Public Class Form1
    
      Private x As Integer
      Private y As Integer
      Private r As Integer
    
      Private DrawIt As Boolean
    
      Private Sub Form1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles Me.Paint  ' //the drawing of Cartesian Plane
        Dim g As Graphics = e.Graphics
        g.TranslateTransform(500, 310)   'Put 0,0 of the plot at pixel 500,310
        g.ScaleTransform(1, -1)          'Reverse the Y axis so +Y is above 0,0
    
        g.FillRectangle(Brushes.White, New Rectangle(-250, -250, 500, 500))  'a 500x500 area centered on the 0,0 coordinate
        g.DrawLine(Pens.Black, 0, -250, 0, 250)
        g.DrawLine(Pens.Black, -250, 0, 250, 0)
    
        If DrawIt Then
          x = CType(TextBox1.Text, Integer)
          y = CType(TextBox2.Text, Integer)
          r = CType(TextBox3.Text, Integer)
          FillCircle(g, x, y, 7, Brushes.Black)
          DrawCircle(g, x, y, r, Pens.Red)
        End If
      End Sub
    
      Private Sub DrawCircle(g As Graphics, x As Single, y As Single, r As Single, p As Pen)
        g.DrawEllipse(p, x - r, y - r, r * 2, r * 2)
      End Sub
    
      Private Sub FillCircle(g As Graphics, x As Single, y As Single, r As Single, b As Brush)
        g.FillEllipse(b, x - r, y - r, r * 2, r * 2)
      End Sub
    
      Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        If TextBox1.TextLength <> 0 And TextBox2.TextLength <> 0 And TextBox3.TextLength <> 0 Then
          DrawIt = True
          Invalidate()
        Else
          MessageBox.Show("Please Complete All Fields Before Plotting!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
        End If
      End Sub
    
    End Class

  5. #5

    Thread Starter
    Junior Member
    Join Date
    Aug 2012
    Posts
    30

    Re: Graphing a Circle in a Coordinate Plane with inputs Center and Radius

    Okay big thanks for helping and guiding me Sir. Now I'm trying to add a button to clear the fields. I ended up something like this but it throws an InvalidCastException starting on the line x = CType(TextBox1.Text, Integer)

    Code:
     Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            Click = False
            TextBox1.Clear()
            TextBox2.Clear()
            TextBox3.Clear()
            g.Clear(DefaultBackColor)
            g.TranslateTransform(500, 310)   'Put 0,0 of the plot at pixel 500,310
            g.ScaleTransform(1, -1)
            g.FillRectangle(Brushes.White, New Rectangle(-250, -250, 500, 500))  'a 500x500 area centered on the 0,0 coordinate
            g.DrawLine(Pens.Black, 0, -250, 0, 250)
            g.DrawLine(Pens.Black, -250, 0, 250, 0)
            x = CType(TextBox1.Text, Integer)
            y = CType(TextBox2.Text, Integer)
            r = CType(TextBox3.Text, Integer)
            FillCircle(g, x, y, 7, Brushes.Black)
            DrawCircle(g, x, y, r, Pens.Red)
        End Sub

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

    Re: Graphing a Circle in a Coordinate Plane with inputs Center and Radius

    I don't know what setting click=True or click=False is doing for you.

    Well, if you used my code then it would be...
    Code:
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            TextBox1.Clear()
            TextBox2.Clear()
            TextBox3.Clear()
            DrawIt = False  'Don't do the drawing on the graph
            Invalidate()    'Update the graph so the drawing portion is cleared
        End Sub
    I don't know what your full code looks like now, so can't really give a valid solution for that.
    But logically, since you just cleared the textboxes, you wouldn't want any of the code that tries to create lines from the values in the textboxes (there aren't any, and you shouldn't be drawing from the Button click events anyway).
    Last edited by passel; Oct 17th, 2015 at 08:44 AM.

  7. #7
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Graphing a Circle in a Coordinate Plane with inputs Center and Radius

    Quick appendix to passel's post:

    The reason that CType() fails is because you just cleared the TextBox. So its Text property is "", which isn't a number.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  8. #8

    Thread Starter
    Junior Member
    Join Date
    Aug 2012
    Posts
    30

    Re: Graphing a Circle in a Coordinate Plane with inputs Center and Radius

    Thank you very much Sir Passel! I'm halfway through in finishing my program, I think I can handle the rest.

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

    Re: Graphing a Circle in a Coordinate Plane with inputs Center and Radius

    Just so you know, because we invert the Y axis it means things that have an discernible orientation like a bitmap, or String will be seen to be drawn upside down.
    If you want to draw a string at a particular points in your plot, you will most likely want to temporarily re-invert the Y axis at that point before drawing the string (or likewise, when using DrawImage).

    One way this can be done is using a GraphicsContext object to save the current state of the Graphics object (what we're using to draw with), moving the 0,0 point to where you want to draw the object (e.g. the string, or a bitmap), invert the Y axis, draw the object at 0,0 (since we've moved 0,0 to that point), then restore the Graphics object back to what it was (0,0 at the center of the graph, the Y axis positive going Up) using the GraphicsContext object.

    As an example, I've modified your code (actually modified my modification of your code) to add the capability of inputting a string to be drawn at the coordinate in the textbox. Also, went ahead and added a minimal bit of List processing, so the Circle is added to a list, and another list is used to support the strings independently (could be used to label the axis, for instance).
    The remove buttons won't clear the textboxes any longer. They just remove the last entry added to the respective list, and redraw.
    Here's the code. I added another textbox for the string input and two buttons for string list processing (add and remove).

    p.s I also move the code that was processed in the Add buttons to subroutines that are called by the buttons, so that they can easily be called from other places besides the button click events. This is demonstrated by initializing the textboxes with some default values in the IDE, and calling the ProcessInput subs from the Form Load event handler to add an initial circle and string to the lists at startup.
    You can always just hit the remove buttons to remove the initial default circle and string before adding new ones.

    Also, got rid of the DrawIt boolean Flag. Since the circles and strings are drawn from lists, don't need the DrawIt flag. If there is nothing in the lists, there won't be an attempt to draw that object, so no need to branch around it. The DrawIt flag was superfluous.

    Also added a function (ParseSingle) to consolidate the parsing and error checking of a value from the textbox, so that the common parsing and error checking and raising a messagebox to inform the user of any problems with the input could be done in one place, and be a oneliner for where it is used.
    Code:
    Public Class Form1
    
      Private Class CircleType
        Public x As Single
        Public y As Single
        Public r As Single
      End Class
    
      Private Class StringType
        Public x As Single
        Public y As Single
        Public s As String
      End Class
    
      Private circleList As New List(Of CircleType)
      Private stringList As New List(Of StringType)
    
      Private Sub Form1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles Me.Paint  ' //the drawing of Cartesian Plane
        Dim g As Graphics = e.Graphics
        g.TranslateTransform(500, 310)   'Put 0,0 of the plot at pixel 500,310
        g.ScaleTransform(1, -1)          'Reverse the Y axis so +Y is above 0,0
    
        g.FillRectangle(Brushes.White, New Rectangle(-250, -250, 500, 500))  'a 500x500 area centered on the 0,0 coordinate
        g.DrawLine(Pens.Black, 0, -250, 0, 250)
        g.DrawLine(Pens.Black, -250, 0, 250, 0)
    
        For Each ct As CircleType In circleList            'For each circle in the circle list
          FillCircle(g, ct.x, ct.y, 7, Brushes.Black)      '  draw the circle
          DrawCircle(g, ct.x, ct.y, ct.r, Pens.Red)
        Next
    
        Dim gc As Drawing2D.GraphicsContainer
        For Each st As StringType In stringList
          gc = g.BeginContainer()                          'Save our current matrix state, so we can temporarily modify it
          g.TranslateTransform(st.x, st.y)                 'Move (0,0) point to our String Start Point (Y is + up)
          g.ScaleTransform(1, -1)                          'Flip the Y axis so string characters are not drawn upsidedown (Y is + down)
          g.DrawString(st.s, Me.Font, Brushes.Black, 7, 0) 'Draw String with bias 7 pixels in X so is outside the filled black dot (if at a circle)
          g.EndContainer(gc)                               'Restore our current matrix state, (0,0) back at the center, Y scale + up
        Next
      End Sub
    
      Private Sub DrawCircle(g As Graphics, x As Single, y As Single, r As Single, p As Pen)
        g.DrawEllipse(p, x - r, y - r, r * 2, r * 2)
      End Sub
    
      Private Sub FillCircle(g As Graphics, x As Single, y As Single, r As Single, b As Brush)
        g.FillEllipse(b, x - r, y - r, r * 2, r * 2)
      End Sub
    
      Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        ProcessCircleInputs()
      End Sub
    
      Private Sub ProcessCircleInputs()
        If TextBox1.TextLength <> 0 And TextBox2.TextLength <> 0 And TextBox3.TextLength <> 0 Then
          Dim ct As New CircleType
          Dim OK As Boolean
          OK = ParseSingle(ct.x, TextBox1.Text, "Input for X is not a number")
          OK = OK And ParseSingle(ct.y, TextBox2.Text, "Input for Y is not a number")
          OK = OK And ParseSingle(ct.r, TextBox3.Text, "Input for R is not a number")
          If OK Then                'If none of the inputs failed then
            circleList.Add(ct)      '  Add the circle to the list
            Invalidate()            '  Redraw the form
          End If
        Else
          MessageBox.Show("Please Complete All Fields Before Plotting!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
        End If
      End Sub
    
      Private Function ParseSingle(ByRef retVal As Single, strIn As String, ErrString As String) As Boolean
        If Single.TryParse(strIn, retVal) Then
          Return True
        Else
          MessageBox.Show(ErrString, "Input Error")
          Return False
        End If
      End Function
    
      Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
        If circleList.Count > 0 Then
          circleList.Remove(circleList.Last)
        End If
        Invalidate()
      End Sub
    
      Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
        ProcessStringInputs()
      End Sub
    
      Private Sub ProcessStringInputs()
        If TextBox4.Text.Length > 0 Then
          Dim st As New StringType
          Dim OK As Boolean
          OK = ParseSingle(st.x, TextBox1.Text, "Input for X is not a number")
          OK = OK And ParseSingle(st.y, TextBox2.Text, "Input for Y is not a number")
          If OK Then
            st.s = TextBox4.Text
            stringList.Add(st)
            Invalidate()
          End If
        End If
      End Sub
    
      Private Sub Button4_Click(sender As System.Object, e As System.EventArgs) Handles Button4.Click
        If stringList.Count > 0 Then
          stringList.Remove(stringList.Last)
          Invalidate()
        End If
      End Sub
    
      Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        ProcessCircleInputs()
        ProcessStringInputs()
      End Sub
    End Class
    For those that don't want to manually setup a project, adding the four buttons and textboxes, I've attach a solution project (VS 2010).
    Should have added labels to identify the X,Y and R textboxes, but the project solution is already zipped up, and I'm not going to bother now.
    Attached Files Attached Files
    Last edited by passel; Oct 18th, 2015 at 05:04 AM.

Tags for this Thread

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