0

I want to make a tool that can measure angles between two user defined spots on a form. I have no code to do this at the moment, so any code would be appreciated.

Thanks

UPDATE

It needs to be in Degrees and my points are 3 pictureboxes, each with different colours on each of the three points for the angle to be measured.

UPDATE

This is my new current code:

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

        int Dotter = 0;

        private void button1_Click(object sender, EventArgs e)
        {
            Dotter = 1;
        }

        public int Distance2D(int x1, int y1, int x2, int y2)
        {    
            int result = 0;
            double part1 = Math.Pow((x2 - x1), 2);

            double part2 = Math.Pow((y2 - y1), 2);
            double underRadical = part1 + part2;
            result = (int)Math.Sqrt(underRadical);

            return result;
        }

        private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
        {
            if (Dotter == 1)
            {
                dot1.Visible = true;
                dot1.Location = e.Location;
                Dotter = 2;
            }
            else if (Dotter == 2)
            {
                dot2.Visible = true;
                dot2.Location = e.Location;
                Dotter = 3;
            }
            else if (Dotter == 3)
            {
                dot3.Visible = true;
                dot3.Location = e.Location;
                Dotter = 4;
            }
            else if (Dotter == 4)
            {
                dot1.Visible = false;
                dot2.Visible = false;
                dot3.Visible = false;
                Dotter = 1;
            }

            anglesize.Text = Convert
                .ToInt32(Distance2D(
                             dot1.Location,
                             dot2.Location,
                             dot3.Location))
                .ToString();
        }
    }
}

and my problem is the line of actually putting the size of the angle in the label I have made called anglesize.

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
Chris Bacon
  • 995
  • 8
  • 30
  • 42
  • In what unit? Degrees? Radian? Also how do you want to measure the angle between two spots?!! There has to be a third one too! :D Or between two lines...? – Maghoumi Nov 11 '10 at 21:03
  • What is your "spot"? Is it a point? And how is it defined? – Albin Sunnanbo Nov 11 '10 at 21:03
  • To add what M2X and Albin Sunnanbo has said, what coordinate system are you using? Are you doing this in raw pixels, or are you using some other unit of measure? Do you have a basic understanding of trigonometry? – In silico Nov 11 '10 at 21:04
  • @Chris Bacon: "my points are 2 pictureboxes, each with different colours on each of the two points for the angle to be measured." - I'm sorry to say but that makes no sense at all. – In silico Nov 11 '10 at 21:16
  • And you still need 3 points to define an angle. – CodesInChaos Nov 11 '10 at 21:18
  • @Chris Bacon: Okay so you actually do have three points. Are you assuming `dot2` is the [vertex angle](http://mathworld.wolfram.com/VertexAngle.html)? Do you need a "directed" angle, or do you just want to find the positive angle between the lines without any regard for orientation? – In silico Nov 11 '10 at 21:48
  • That is correct, dot2 is the vertex angle, and i need a positive angle between the lines without any regard for orientation, but at the moment i don't know how to include this vertex angle in the calcualtion – Chris Bacon Nov 11 '10 at 21:57
  • @Chris Bacon: I have updated my answer to hopefully make it easier to translate vector-speak to code-speak. :-) – In silico Nov 11 '10 at 22:00
  • @Chris Bacom: Oops, I meant angle's vertex. – In silico Nov 11 '10 at 22:07

6 Answers6

17

To find the angle formed by three points, you can use the dot product. Say you have the three points set up like this:

     dot1        
     /
  A /
   /
  / theta
dot2-------dot3
       B

I assume you want to find the angle theta between the lines created by points dot1, dot2 and dot3, where they're points that you've collected from the user. Then, you can define two vectors A and B:

A = dot1 - dot2
B = dot3 - dot2

Subtraction of two points simply means that you subtract each corresponding component. So it might look like this in code:

// I'll just use another point to represent a vector
Point A = new Point();
A.X = dot1.X - dot2.X;
A.Y = dot1.Y - dot2.Y;

Point B = new Point();
B.X = dot3.X - dot2.X;
B.Y = dot3.Y - dot2.Y;

The angle between these two vectors as defined by the dot product is:

                A * B
theta = acos(-----------)
             ||A|| ||B||

Where ||A|| and ||B|| are the lengths of the vectors A and B respectively, which is the square root of the sum of the squares of the components (which is simply the distance formula).

double ALen = Math.Sqrt( Math.Pow(A.X, 2) + Math.Pow(A.Y, 2) );
double BLen = Math.Sqrt( Math.Pow(B.X, 2) + Math.Pow(B.Y, 2) );

The dot product A * B is simply the sum of the products of the components, so it might look like this in code:

double dotProduct = A.X * B.X + A.Y * B.Y;

So you may perhaps have a dot product defined like this:

double theta = (180/Math.PI) * Math.Acos(dotProduct / (ALen * BLen));

This gives you the angle in degrees (remember that Math.Acos() returns the angle in radians).

In silico
  • 51,091
  • 10
  • 150
  • 143
  • This only calculated the undirected angle. In many applications it matters if the angle is +30deg or -30deg. – CodesInChaos Nov 11 '10 at 21:10
  • 1
    @CodeInChaos: Right, but unfortunately the OP's question is really lacking in details, so I gave the "most obvious" answer. I will update my answer once the OP actually gives us a clue as to what is needed. – In silico Nov 11 '10 at 21:15
  • So where does this fit in with my code, do i need to make a separate function in my program to make it work? – Chris Bacon Nov 11 '10 at 22:05
  • @Chris Bacon: That's up to you. You can certainly put it in a separate function. – In silico Nov 11 '10 at 22:09
  • +1 This is answered a few times on stackoverflow, but this answer is miles ahead. To bad the question isn't very clear. The ascii art drawing is awesome!! oh - dotProduct, and ALen/BLen should be double – itchi Nov 22 '10 at 07:54
  • @itchi: Thanks for the feedback! The values of `A.X`, `B.X`, etc. are integers (they're pixels!), so storing the `dotProduct` as an `int` is fine since the dot product involves only addition and multiplication of integers. I've changed it to a `double` though, to avoid further confusion, although the results should be the same. – In silico Nov 22 '10 at 09:25
2

similar to In silico's answer, you can use a combination of a dot product and cross product to get the angle, and not just the undirected angle.

where a and b are vectors run from the point you want to calculate the angle from to the corners of your picture boxes, respectively.

a*b = |a| |b| cos theta

axb = |a| |b| sin theta

axb / a*b = tan theta

atan2(axb, a*b) = theta

tbischel
  • 6,337
  • 11
  • 51
  • 73
0

To measure an angle you need three points or a base direction.

Math.Atan2(y, x) can be used to measure the angle to the x-axis.

Note that y is the first param and not the second. Unlike other versions of this function it is safe with x=0

To transform the result which is given in radians to degrees you need to multiply with (180/Math.PI)

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
0

Hey this seems like a homework question so I won't answer directly but you can find something here:

http://msdn.microsoft.com/en-us/library/system.math.atan.aspx

Sam
  • 565
  • 3
  • 8
  • It's not necessarily a homework question. I used sin/cos/acos2 as blackbox functions to convert from (x,y) to (angle,length) and back before I learned trigonometry. For example this problem occurs even in very simple games. – CodesInChaos Nov 11 '10 at 21:24
0

There's always atan2(dy2, dx2) - atan2(dy1, dx1) suitably massaged.

Mike Dunlavey
  • 40,059
  • 14
  • 91
  • 135
-1

First you need to measure the distance between your points:

    public int Distance2D(int x1, int y1, int x2, int y2)
    {

        int result = 0;
        double part1 = Math.Pow((x2 - x1), 2);

        double part2 = Math.Pow((y2 - y1), 2);
        double underRadical = part1 + part2;
        result = (int)Math.Sqrt(underRadical);

       return result;
  }
dexter
  • 7,063
  • 9
  • 54
  • 71