2013-09-28 4 views
3

Этот вопрос/ошибка напрямую связана с этим Angle Measurer in C#. Проблема в том, что тета ошибочна в углах больше 180 (я работаю в градусах, а не радиан).Ошибка при вычислении theta угла

Вот полезный снимок экрана. Эта фотография представляет собой накладной вид трех динозавров. Тело динозавров серое. Головы - белая точка. «Угол зрения» для каждого динозавра (не тот же для всех видов) - это синие линии.

enter image description here

Как вы можете увидеть облицовку каждого динозавра является правильным. Тета для угла между Джоном и Джули выглядит правильно. Тем не менее, углы от Джули до Джона и Муффи до Джона совершенно неправильны. Каждый должен быть> 180 градусов.

Вот фрагмент кода:

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); 

Может ли из вас математической Boffins увидеть ошибку моего пути?

Спасибо!

Edit: захвата экрана, показывающий, что проекция точки 50 метров перед динозаврами вдоль их осей правильно:

enter image description here

Снимок экрана после последних изменений:

enter image description here

Это «мое определение» «углов динозавров» и что я ожидаю:

  • Muffie обращен почти к востоку (108 градусов). Джон почти прямо позади нее и немного слева. Я бы ожидал, что угол между Муффи и Джоном составит около 195 градусов.
  • Джули обращена к юго-западу (235 градусов). Джон почти прямо прав Джули. Я ожидал бы, что угол между Джули и Джоном составит около 87 градусов.
  • Джон смотрит почти прямо на Джули (Джули немного справа от головы). Я ожидал бы, что угол между Джоном и Джули будет около 7 градусов.

Интересно, правильны ли цифры, но нам нужно «нормализовать» их в направлении, с которым сталкивается «зритель-динозавр»? «Угол между динозаврами», который я хочу, относится к соответствующему динозавру.

В сущности, я пытаюсь определить, какие динозавры могут видеть, какие динозавры основаны на их видном уголке зрения.

+1

имен переменных низковольтные случае лучше использовать. Кодекс будет проще понять, и, как вы можете видеть, простой форматировщик SO-кода не будет путать их с типами :) – BartoszKP

+1

Вкратце: общедоступные вещи (типы, свойства и методы) - это PascalCase, а личные вещи (локальные переменные, поля , и параметры) являются camelCase. –

+0

Спасибо, я запомню это. Любая идея, почему тета-расчеты отключены в 2 из 3 случаев? – zetar

ответ

2

Проблема в том, что Math.Acos возвращает только углы в диапазоне [0, π]. Это связано с тем, что между двумя векторами всегда есть два угла, и ваши вычисления всегда будут возвращать меньший. Чтобы исправить это, вам нужно переопределить свое понятие «угол между динозаврами».Чтобы устранить эту неопределенность можно вычислить угол по часовой стрелке между векторами:

//... 
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; 
} 

Я нашел решение здесь: Direct way of computing clockwise angle between 2 vectors

+0

Код для проецирования точки 50 метров перед головой динозавра правильный (по крайней мере, работает), и это можно продемонстрировать, вычерчивая линию от этой точки до головы динозавра, которая показывает, что она находится на правильной оси. Ваш код, похоже, решил проблему для одного из динозавров, но не другого. Я могу опубликовать пару снимков экрана, чтобы продемонстрировать – zetar

+0

@zetar. Я исправил ответ, пожалуйста, проверьте сейчас. – BartoszKP

+0

Мы в радианах? Используя новый код, который я получаю, «угол между Джоном и Джули равен 0,31». что просто странно. – zetar

Смежные вопросы