user6425922
user6425922

Reputation: 47

select two point to Draw a circle

I am using visual studio c# windows form, I need help to draw a circle using the Mouse click.. first click will give me the center of the circle equal to the cursor position and the second click will give me a point on the border of the circle equal to the second position of the cursor, the distance between the to points will give me the radius..now I have radius and point ..I can draw a circle ..The code doesn't work because I only can get one position of the cursor no matter how many times I click the mouse

private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        int lastX = Cursor.Position.X;//the first click x cursor position
        int lastY = Cursor.Position.Y;//the first click y cursor  position,         

   //is there any way to reuse the Cursor.Position for different point ??
   int x = Cursor.Position.X;//the second click x cursor position
        int y = Cursor.Position.Y;//the second click y cursor  position
        Graphics g;
       double oradius=Math.Sqrt(((lastX-x)^2) +((lastY-y)^2));
        //double newy = Math.Sqrt(lastY);
       // int newxv = Convert.ToInt32(newx);
        int radius= Convert.ToInt32(oradius);
        g = this.CreateGraphics();

        Rectangle rectangle = new Rectangle();
        PaintEventArgs arg = new PaintEventArgs(g, rectangle);

        DrawCircle(arg, x, y,radius,radius);
    }


    private void DrawCircle(PaintEventArgs e, int x, int y, int width, int height)
    {
        System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.Red, 3);
        e.Graphics.DrawEllipse(pen, x - width / 2, y - height / 2, width, height);
    }
}

Upvotes: 0

Views: 1340

Answers (4)

Alper Şaldırak
Alper Şaldırak

Reputation: 1054

        private int _firstX;
        private int _firstY;
        private int _secondX;
        private int _secondY;

        private bool _isSecondClick;


    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        if (_isSecondClick)
        {
            _secondX = Cursor.Position.X;
            _secondY = Cursor.Position.Y;
            var radious1 = Math.Pow(_firstX - _secondX, 2);
            var radious2 = Math.Pow(_firstY - _secondY, 2);

            var radious = Math.Sqrt(radious1 + radious2);
            Graphics g = this.CreateGraphics();

            Rectangle rectangle = new Rectangle();
            PaintEventArgs arg = new PaintEventArgs(g, rectangle);
            DrawCircle(arg, _secondX, _secondY, radious, radious);
        }
        else
        {
            _firstX = Cursor.Position.X;
            _firstY = Cursor.Position.Y;
            _isSecondClick = true;
        }    
    }

    private void DrawCircle(PaintEventArgs arg, int x, int y, double width, double height)
    {
        System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.Red, 3);
        var xL = Convert.ToInt32(x - width / 2);
        var yL = Convert.ToInt32(y - height / 2);
        var hL = Convert.ToInt32(height);
        var wL = Convert.ToInt32(width);
        arg.Graphics.DrawEllipse(pen, xL, yL, wL, hL);
    }

Upvotes: 0

CamW
CamW

Reputation: 3363

There are many things fundamentally wrong with this code, here is a complete, working example.

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private Point clickCurrent = Point.Empty;
        private Point clickPrev = Point.Empty;

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            clickPrev = clickCurrent;
            clickCurrent = this.PointToClient(Cursor.Position);
            if (clickPrev == Point.Empty) return;    
            Graphics g;
            double oradius = Math.Sqrt((Math.Pow(clickPrev.X - clickCurrent.X, 2)) + (Math.Pow(clickPrev.Y - clickCurrent.Y, 2)));
            int radius = Convert.ToInt32(oradius);
            g = this.CreateGraphics();
            Rectangle rectangle = new Rectangle();
            PaintEventArgs arg = new PaintEventArgs(g, rectangle);
            DrawCircle(arg, clickPrev.X, clickPrev.Y, radius * 2, radius * 2);
            clickCurrent = Point.Empty;
        }


        private void DrawCircle(PaintEventArgs e, int x, int y, int width, int height)
        {
            System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.Red, 3);
            e.Graphics.DrawEllipse(pen, x - width / 2, y - height / 2, width, height);
        }
    }

Upvotes: 0

Zohar Peled
Zohar Peled

Reputation: 82474

Your lastX and lastY are local variables, and you initialize them in the beginning of the MouseDown event handler. They should be class level variables and should be populated at the end of the MouseDown event handler.
Also, you should test if they already have a value, and only if they have value then draw the circle and then clear them (so that the next circle will have it's own center).

Here is an improvement of your code. Note I've used the using keyword with the graphics object and with the pen - get used to use it every time you are using an instance of anything that's implementing the IDisposable interface.

private void Form1_MouseDown(object sender, MouseEventArgs e)
{
    if (_lastPosition != Point.Empty)
    {
        var currentPosition = Cursor.Position;
        var oradius = Math.Sqrt(((_lastPosition.X - currentPosition.X) ^ 2) + ((_lastPosition.Y - currentPosition.Y) ^ 2));
        var radius = Convert.ToInt32(oradius);
        using (var g = this.CreateGraphics())
        {
            var arg = new PaintEventArgs(g, new Rectangle());
            DrawCircle(arg, currentPosition, radius, radius);
        }
        _lastPosition = Point.Empty;
    }
    else
    {
        _lastPosition = Cursor.Position;
    }

}


private void DrawCircle(PaintEventArgs e, Point position, int width, int height)
{
    using (var pen = new System.Drawing.Pen(System.Drawing.Color.Red, 3))
    {
        e.Graphics.DrawEllipse(pen, position.X - width / 2, position.Y - height / 2, width, height);
    }
}

Note: This code can be improved even further.

Upvotes: 1

Pedro G. Dias
Pedro G. Dias

Reputation: 3222

You need to store the first click as well before you start doing the calculations. One way to do this is to create a class that simply throws an event every second time you pass it x and y coordinates like this:

public class CircleDrawer
{
    private int _firstX;
    private int _firstY;
    private int _secondX;
    private int _secondY;

    private bool _isSecondClick;

    private event EventHandler OnSecondClick;

    public void RegisterClick(int x, int y)
    {
           if(_isSecondClick)
           {
               _secondX = x;
               _secondY = y;
               if(OnSecondClick != null) 
                  OnSecondClick(this, null);
           }
           else
           {
               _firstX = x;
               _firstY = y;
               _isSecondClick = true;
           }    
    }
   }

You can then in your code simply call your methods:

private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        int lastX = Cursor.Position.X;//the first click x cursor position
        int lastY = Cursor.Position.Y;//the first click y cursor  position, 

        _circleDrawer.RegisterClick(lastX, lastY);
    }

And in your constuctor:

public MyForm()
{
   _circleDrawer = new CircleDrawer();
   _circleDrawer.OnSecondClick += DrawCircle();
}

public void DrawCircle()
{
   // Your drawing code
}

Upvotes: 2

Related Questions