2013-03-23 2 views
2

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

для расчета маршрута я использовал Google direction API. и для составления маршрута я использовал этот код

- (void) drawRoute:(NSArray *) path 
{ 
    NSInteger numberOfSteps = path.count; 
    [self.objMapView removeOverlays: self.objMapView.overlays]; 

    CLLocationCoordinate2D coordinates[numberOfSteps]; 
    for (NSInteger index = 0; index < numberOfSteps; index++) 
    { 
     CLLocation *location = [path objectAtIndex:index]; 
     CLLocationCoordinate2D coordinate = location.coordinate; 

     coordinates[index] = coordinate; 
    } 

    for(id <MKOverlay> ovr in [self.objMapView overlays]) 
    { 
     MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:ovr]; 


     if (polylineView.tag == 22) 
     { 
      [self.objMapView removeOverlay:ovr]; 
     } 
     [polylineView release]; 
    } 

    MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps]; 
    [self.objMapView addOverlay:polyLine]; 


} 

До сих пор всякая вещь okey.

Теперь я хочу, уведомление, если пользователь находится вне маршрута (более 100 метров) .И я могу получить уведомление также

ПРОБЛЕМА: ~ если дорога прямая (более 100mt), то я не могу получить точки на дороге. Для того, чтобы объяснить эту проблему я прилагаю изображение ...

ROUTE

В этом изображении допускают черную линию мой путь (ломаная) и красные круги точки я получил форму для Google API. но в прямом пути, показанном в виде синего круга, я не могу получить точки для сравнения, и на этом пути вызывается функция пересчета.

Может ли кто-нибудь сказать мне решение, из которого я могу получить все точки маршрута, даже если это прямая дорога.

+0

Обычно Google API возвращает поли точек на суставах или, кривые не по прямому пути, это даст начало и конец для прямой путь .. – iphonic

+0

Это проблема iphonic. OP нуждается в промежуточных точках вдоль прямой линии, когда она больше 100 м. –

+0

В этом случае вы можете узнать среднее расстояние между точками, если оно превышает расстояние между точками, поставить местоположение пользователя. – iphonic

ответ

3

Я знаю, что это старый поток, но в последнее время столкнулся с той же проблемой и нашел решение OK. Концепция заключается в том, что вы не вычисляете расстояние до КАЖДОГО сегмента линии, а только для двух сегментов, подключенных к ближайшей точке.

  1. вычислить расстояние от текущего местоположения до всех точек в MKPolyline и взять минимум от этого. (Возможно, есть какой-то хороший способ оптимизировать это. Как и повторение всех точек в каждом обновлении местоположения, но у меня нет времени вникать в это сейчас).
  2. Теперь вы знаете расстояние до ближайшей точки полилинии. Однако этот момент может быть еще далеко, тогда как сама полилиния (соединение этой точки и предыдущей или следующей точки) может быть ближе. Итак, вычислите расстояние между вашим текущим местоположением и этими двумя линейными сегментами, и у вас есть самое близкое расстояние.

Теперь это не является водонепроницаемым. Хотя в некоторых случаях он минимизирует количество вызовов api (если у вас есть сумасшедшие изгибы и кривые в MKPolyline), он может называть api, когда он не нужен, но эй, тогда одна и та же линия будет снова нарисована, никакого урона не будет. В моих тестах он работал нормально, и вы также можете настроить точность. Я установил его в 200 м (0,2 км) в приведенном ниже коде.

//Get Coordinates of points in MKPolyline 
NSUInteger pointCount = routeLineGuidanceTurn.pointCount; 
CLLocationCoordinate2D *routeCoordinates = malloc(pointCount * sizeof(CLLocationCoordinate2D)); 
[routeLineGuidanceTurn getCoordinates:routeCoordinates 
         range:NSMakeRange(0, pointCount)]; 
NSLog(@"route pointCount = %d", pointCount); 


//Determine Minimum Distance and GuidancePoints from 
double MinDistanceFromGuidanceInKM = 1000; 
CLLocationCoordinate2D prevPoint; 
CLLocationCoordinate2D pointWithMinDistance; 
CLLocationCoordinate2D nextPoint; 

for (int c=0; c < pointCount; c++) 
{ 
    double newDistanceInKM = [self distanceBetweentwoPoints:Currentcordinate.latitude longitude:Currentcordinate.longitude Old:routeCoordinates[c].latitude longitude:routeCoordinates[c].longitude]; 
    if (newDistanceInKM < MinDistanceFromGuidanceInKM) { 
     MinDistanceFromGuidanceInKM = newDistanceInKM; 
     prevPoint = routeCoordinates[MAX(c-1,0)]; 
     pointWithMinDistance = routeCoordinates[c]; 
     nextPoint = routeCoordinates[MIN(c+1,pointCount-1)]; 
    } 
} 
free(routeCoordinates); 


NSLog(@"MinDistanceBefore: %f",MinDistanceFromGuidanceInKM); 

//If minimum distance > 200m we might have to recalc GuidanceLine. 
//To be sure we take the two linesegments connected to the point with the shortest distance and calculate the distance from our current position to that linedistance. 
if (MinDistanceFromGuidanceInKM > 0.2) { 
    MinDistanceFromGuidanceInKM = MIN(MIN([self lineSegmentDistanceFromOrigin:Currentcordinate onLineSegmentPointA:prevPoint pointB:pointWithMinDistance], [self lineSegmentDistanceFromOrigin:Currentcordinate onLineSegmentPointA:pointWithMinDistance pointB:nextPoint]),MinDistanceFromGuidanceInKM); 

    if (MinDistanceFromGuidanceInKM > 0.2) { 
     // Call the API and redraw the polyline. 
    } 
} 

Здесь весело, чтобы рассчитать расстояние между двумя точками. Я знаю, что для него есть встроенная функция, но она уже была в моем коде.

-(double)distanceBetweentwoPoints:(double)Nlat longitude:(double)Nlon Old:(double)Olat longitude:(double)Olon { 
    //NSLog(@"distanceBetweentwoPoints"); 
    double Math=3.14159265; 
    double radlat1 = Math* Nlat/180; 
    double radlat2 = Math * Olat/180; 
    double theta = Nlon-Olon; 
    double radtheta = Math * theta/180; 
    double dist = sin(radlat1) * sin(radlat2) + cos(radlat1) * cos(radlat2) * cos(radtheta); 
    if (dist>1) {dist=1;} else if (dist<-1) {dist=-1;} 
    dist = acos(dist); 
    dist = dist * 180/Math; 
    dist = dist * 60 * 1.1515; 
    return dist * 1.609344; 
} 

И вот бит, который вычисляет расстояние между точкой и отрезком линии между двумя другими точками. Я получил это отсюда: https://stackoverflow.com/a/28028023/3139134 Изменено немного для работы с CLLocationCoordinate2D и возврата расстояния.

- (CGFloat)lineSegmentDistanceFromOrigin:(CLLocationCoordinate2D)origin onLineSegmentPointA:(CLLocationCoordinate2D)pointA pointB:(CLLocationCoordinate2D)pointB { 

    CGPoint dAP = CGPointMake(origin.longitude - pointA.longitude, origin.latitude - pointA.latitude); 
    CGPoint dAB = CGPointMake(pointB.longitude - pointA.longitude, pointB.latitude - pointA.latitude); 
    CGFloat dot = dAP.x * dAB.x + dAP.y * dAB.y; 
    CGFloat squareLength = dAB.x * dAB.x + dAB.y * dAB.y; 
    CGFloat param = dot/squareLength; 

    CGPoint nearestPoint; 
    if (param < 0 || (pointA.longitude == pointB.longitude && pointA.latitude == pointB.latitude)) { 
     nearestPoint.x = pointA.longitude; 
     nearestPoint.y = pointA.latitude; 
    } else if (param > 1) { 
     nearestPoint.x = pointB.longitude; 
     nearestPoint.y = pointB.latitude; 
    } else { 
     nearestPoint.x = pointA.longitude + param * dAB.x; 
     nearestPoint.y = pointA.latitude + param * dAB.y; 
    } 

    CGFloat dx = origin.longitude - nearestPoint.x; 
    CGFloat dy = origin.latitude - nearestPoint.y; 
    return sqrtf(dx * dx + dy * dy) * 100; 

} 
+0

Я получаю смешанные результаты в КМ, кажется, что-то странно. Я также не понимаю * 100 в конце строкиSegmentDistanceFromOrigin. Вы можете это объяснить? –

+0

Hi Sjoerd. Можете ли вы рассказать о смешанных результатах? Что вы имеете в виду? Я честно не помню, почему было 100 человек. Возможно, я хотел получить результат на 100 метров. Не уверен. Лучше сделать некоторые тесты на этом самостоятельно, чтобы определить устройство, которое вы получаете от метода. – guido

+0

Я сравнил эту функцию с расстояниемFromLocation на CLLocation до двух точек. По какой-то причине я не смог получить результаты по ОК. Теперь я переключился на другое решение, которое использует MKMapPoints и получает лучшие результаты: http://stackoverflow.com/questions/26240183/how-to-determine-the-next-poi-in-a-navigation-route - Спасибо за ответ! –

2

Для каждой пары точек в каждом шаге, вы можете рассчитать расстояние между ними, используя теорему Пифагора:

distance = sqrt( pow((point1.x - point2.x), 2) + pow((point1.y - point2.y), 2) ) 

Тогда, если расстояние больше 100 м, добавить промежуточные точки вдоль отрезка.

+0

Спасибо за ответ. Но я новичок в картах. так что вы могли бы объяснить, как получить промежуточные точки вдоль сегмента линии. –

+0

Спасибо, я получил все точки через алгоритм рисования линии. Но я столкнулся с еще одной проблемой, пожалуйста, см. [ЭТОТ ВОПРОС] (http://stackoverflow.com/questions/15585711/draw-poly-line-on-the-read-in-mkmap-view-iphone), пожалуйста, помогите мне –

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