3

This question / bug is directly related to this Angle Measurer in C#. The problem seems to be that the theta is wrong in angles greater than 180 (I'm working in degrees, not radians).

Here's a helpful screen shot. This picture represents an overhead view of three dinosaurs. The body of the dinosaurs are in gray. The heads are a white dot. The 'angle of vision' for each dinosaur (not the same for all species) are the blue lines.

enter image description here

As you can see the facing of each dinosaur is correct. The theta for the angle between John and Julie looks correct. However, the angles from Julie to John and Muffie to John are quite wrong. Each should be > 180 degrees.

Here's the code snippet:

double DinoAFacing = FindAngle(
     Dinosaurs[DinoA].Head.X,
     Dinosaurs[DinoA].Head.Y,
     Dinosaurs[DinoA].Location[Dinosaurs[DinoA].Location.Count - 1].X,
     Dinosaurs[DinoA].Location[Dinosaurs[DinoA].Location.Count - 1].Y);

int Specie = ReturnDinosaurSpecie(DinoA);

double x = 50 * Math.Cos((DinoAFacing - 90) * (Math.PI / 180.0));
double y = 50 * Math.Sin((DinoAFacing - 90) * (Math.PI / 180.0));

x += Dinosaurs[DinoA].Head.X;
y += Dinosaurs[DinoA].Head.Y;

System.Windows.Point A = new System.Windows.Point();

A.X = x - Dinosaurs[DinoA].Head.X;
A.Y = y - Dinosaurs[DinoA].Head.Y;

System.Windows.Point B = new System.Windows.Point();
B.X = Dinosaurs[DinoB].Head.X - Dinosaurs[DinoA].Head.X;
B.Y = Dinosaurs[DinoB].Head.Y - Dinosaurs[DinoA].Head.Y;

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));
double dotProduct = A.X * B.X + A.Y * B.Y;

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

slug = Dinosaurs[DinoA].PersonalName
     + " is facing: "
     + string.Format("{0:f2}", string.Format("{0:f2}", DinoAFacing))
     + "\nThe angle between "
     + Dinosaurs[DinoA].PersonalName
     + " and "
     + Dinosaurs[DinoB].PersonalName
     + " is "
     + string.Format("{0:f2}", Angle)
     + "\n"
     + Dinosaurs[DinoA].PersonalName
     + " CAN see "
     + Dinosaurs[DinoB].PersonalName;

System.Windows.MessageBox.Show(
    slug,
    "Dino vision",
    System.Windows.MessageBoxButton.OK);

Can any of you math boffins see the error of my ways?

Thanks!

Edit: Screen capture showing that the projection of a point 50 meters in front of the dinosaurs along their axis is correct:

enter image description here

Screen shot after the last changes:

enter image description here

This is 'my definition' of 'dinosaur angles' and what I would expect:

  • Muffie is facing almost east (108 degrees). John is almost directly behind her and little to the left. I would expect that the angle between Muffie and John would be about 195 degrees.
  • Julie is facing southwest (235 degrees). John is almost directly to Julie's right. I would expect that the angle between Julie and John would be about 87 degrees.
  • John is looking almost directly at Julie (Julie is a little to the right of 'head on'). I would expect that the angle between John and Julie would be about 7 degrees.

I wonder if the numbers are correct but we need to 'normalize' them to the direction that the 'viewer dinosaur' is facing? The 'angle between dinosaurs' that I want is relative to the respective dinosaur.

In essence, I'm trying to determine which dinosaurs can see which dinosaurs based on their species 'angle of vision'.

Community
  • 1
  • 1
zetar
  • 1,225
  • 2
  • 20
  • 45
  • 1
    Low-case variable names are better to use. The code would be easier to understand, and as you can see the simple SO code formatter would not confuse them with types :) – BartoszKP Sep 28 '13 at 17:23
  • 1
    In short: public things (types, properties and methods) are PascalCase, while private things (local variables, fields, and parameters) are camelCase. – Tim S. Sep 28 '13 at 17:32
  • Thanks, I'll remember that. Any idea why the theta calculations are off in 2 of the 3 cases? – zetar Sep 28 '13 at 17:38
  • Ad rem: I have a problem understanding what does the `A` vector stand for. Also, could you please define the "angle between dinosaurs"? In general there is no such thing as an angle between two points - so what is the third point here? – BartoszKP Sep 28 '13 at 17:38
  • There are 2 vectors for each calculation. Think of each dinosaur as a vector. The area actually 3 points here: the head of DinoA, a point 50 meters in direction facing by DinoA and the head of DinoB. – zetar Sep 28 '13 at 17:43

1 Answers1

2

The problem is that Math.Acos returns only angles in the range [0, π]. This is because there are always two angles between two vectors, and your calculations will always return the smaller one. To fix this you need to redefine your notion of "angle between dinosaurs". To resolve this ambiguity you can calculate a clockwise angle between vectors:

//...
double dotProduct = A.X * B.X + A.Y * B.Y;
double determinant = A.X * B.Y - A.Y * B.X;

double angle = (180 / Math.PI)
    * (Math.Atan2(determinant , dotProduct));

if (angle < 0)
{
    angle += 360;
}

I've found the solution here: Direct way of computing clockwise angle between 2 vectors

Community
  • 1
  • 1
BartoszKP
  • 34,786
  • 15
  • 102
  • 130
  • The code for projecting a point 50 meters in front of the dinosaur's head is correct (at least works) and this can be demonstrated by drawing a line from that point to the dinosaur's head which shows that it is on the correct axis. Your code seemed to solve the problem for one of the dinosaurs but not the other. I could post a couple of screen shots to demonstrate – zetar Sep 28 '13 at 18:10
  • @zetar I've fixed the answer, please check now. – BartoszKP Sep 28 '13 at 18:16
  • Are we in radians? Using the new code I'm getting, "The angle between John and Julie is 0.31." which is just weird. – zetar Sep 28 '13 at 18:21
  • @zetar Yes, sorry for that. I've fixed this also, now it's in degrees. – BartoszKP Sep 28 '13 at 18:22
  • Also note that I've added `+ Math.PI` term so the answer is in `[0, 2π]`. – BartoszKP Sep 28 '13 at 18:23
  • The new numbers: Julie to John is 257 degrees, which looks good. Muffie to John is 21.19 (this isn't right, should be about 230). John to Julie is 204 (which is wrong and it used to be right at 17). Hmmm – zetar Sep 28 '13 at 18:27
  • @zetar This seems correct - clockwise distance between John and Julie is greater than 180. Counterclockwise would be 17. Seems to me that your intuition about the expected results is incoherent. Or maybe you want another definition of "angle between the dinosaurs". – BartoszKP Sep 28 '13 at 18:48