2013-05-23 2 views
1

Я разрабатываю приложение iOS, которое должно показывать POI (точки интереса) в зависимости от заголовка устройства. Я использовал CLLocationManager, чтобы получить местоположение и заголовок пользователя. У меня есть одна пара координат назначения. Исходя из этого, я вычисляю, какой именно квартал, и возвращает значение плавающего отклонения с юга (0 градусов) в градусах. У меня -/+ 180 градусов на севере и 0 на юге. Вот фрагмент кода:Расчет угла между двумя векторами?

-(float)updateTargetLongitude:(float)lon Latitude:(float)lat{ 
// //longitude = x 
// //latitude = y 
     NSLog(@"current location = (%.5f, %.5f)", [[NSUserDefaults standardUserDefaults] doubleForKey:@"currentLongitude"], [[NSUserDefaults standardUserDefaults] doubleForKey:@"currentLatitude"]); 
     float x = lon - [[NSUserDefaults standardUserDefaults] doubleForKey:@"currentLongitude"]; 
     float y = lat - [[NSUserDefaults standardUserDefaults] doubleForKey:@"currentLatitude"]; 
     float angle; 
     NSLog(@"Searching angle from source (%.5f, %.5f) to destination (%.5f, %.5f)", locationManager.location.coordinate.longitude, locationManager.location.coordinate.latitude, lon, lat); 
     if (x == 0 && y == 0) { 
      NSLog(@"you're there already!"); 
      return -0.1; 
     } 
     if(x == 0 && y > 0){ 
      NSLog(@"look north"); 
      angle = 180.0; 
     } 
     if (x == 0 && y < 0) { 
      NSLog(@"look south"); 
      angle = 0; 
     } 
     if (x > 0 && y == 0) { 
      NSLog(@"look east"); 
      angle = 90.0; 
     } 
     if (x < 0 && y == 0) { 
      NSLog(@"look west"); 
      angle = -90; 
     } 
     if (x > 0 && y > 0) { 
      NSLog(@"first quarter"); 
      angle = -atan2f(y, x) - M_PI_2; 
     } 
     if (x < 0 && y > 0) { 
      NSLog(@"second quarter"); 
      angle = atan2f(y, x) + M_PI_2; 
     } 
     if (x < 0 && y < 0) { 
      NSLog(@"third quarter"); 
      angle = atan2f(x, y); 
     } 
     if (x > 0 && y < 0) { 
      NSLog(@"fourth quarter"); 
      angle = -atan2f(x, y); 
     } 
     NSLog(@"returning radians angle = %.4f for (%.5f, %.5f) :: degrees = %.3f", angle, y, x, angle * 180/M_PI); 
     return angle * 180/M_PI ; 
} 

Как-то у меня есть ситуации, когда цель находится в четвертом квартале, но -93 градусов с юга. Я потерян, и я не знаю, как это исправить ...

Редактировать: по кварталу Я имею в виду декартову систему координат, где + y - север, + x - восток и так далее!

p.s .: Я читал, что компас iPhone действительно плохой, но если это так, как приложение, подобное Google maps, работает правильно?

edit2: Я допустил ошибку с углами. Официально o имеют -90 градусов на востоке и 90 на западе.

+1

Сторона примечания. Тестирование плавающих точек для равенства может не дать вам ожидаемых результатов. – John

+0

Да, но точно глядя на N/S/E/W, точность устройства почти невозможна, поэтому это было строго для «математического» назначения. – raistlin

ответ

2

Если я вижу, это правильно, формула

angle = atan2(x, -y) * 180.0/M_PI; 

должен работать во всех квадрантах, делая все if заявления ненужными.


atan2(y, x) возвращает угол между вектором (x, y) и положительной осью х, возвращаемое значение всегда находится между -pi и pi.

Замена (y, x) от (x, -y) в аргументов означает, что вектор поворачивается на 90 градусов, поэтому результат приведенной выше формулы является угол, измеренный в отрицательном направлении оси у, которая является то, что вы хотите.


Обновления (в соответствии с "EDIT2" в вопросе): Если требование "к югу = 0 град", "восток = -90 град", "запад = +90 град", то формула будет

angle = atan2(-x, -y) * 180.0/M_PI; 
+0

лицом к югу У меня 0 градусов, к востоку - к западу +, поэтому я думаю, что он должен быть наконец atan2 (-x, -y), правильно? – raistlin

+0

@FilipChwastowski: При x> 0, y == 0 моя формула дает угол = 90 градусов, я думал, что это то, что вы хотели. –

+0

Нах, я упомянул, что у меня есть -/+ 180 градусов на севере;) пожалуйста, отредактируйте свой ответ, чтобы никто не потерялся, где, наконец, направление +/- градусов, поэтому я могу принять;) – raistlin

1

Функция atan2 уже учитывает квадрант. Другими словами, он «знает», что вы находитесь в третьем квадранте, если оба x и y отрицательны. Зная это, вы можете видеть, какой угловой выход для atan2(y, x), а затем изменить его на то, как вы хотите его отобразить.

Основная причина, по которой карты Google работают даже с относительно неточным компасом, заключается в том, что структуры дорог дают вам подсказки, поэтому вы можете пройти с большей ошибкой, чем если бы вы не знали, где дороги.

+0

вы уверены, что оно «знает»?что, если x * y> 0? это возможно в ситуациях: и < 0 or both > 0 ... – raistlin

+0

Да. Вот почему вы поставляете atan2 с двумя аргументами. Если 'x' и' y' оба отрицательные, вы находитесь в квадранте III. Если они оба позитивны, вы находитесь в квадранте I и т. Д. Выход atan2 будет находиться между pi и -pi (я думаю). Это целый круг. – John

+0

arctg (alfa) всегда находится между -pi/2 и pi/2;) – raistlin

0

На самом деле, решив, в каком квадранте я изменил код, всегда рассчитывать atan2 с положительными значениями x и y - теперь он работает!