Аннотации по маршруту в MapKit

Я использую MapKit для отображения направлений между местоположениями, и я ищу способ добавить аннотацию, которая работает аналогично аннотации маршрута в приложении Apple Maps, где аннотации показывают каждое время прохождения маршрута (как показано на рисунке на изображении ниже). Я уже правильно рисую направления, проблема заключается в том, как вычислить пару координат вдоль маршрута. То есть, где нужно отказаться от аннотации.

Я подумал о том, чтобы каким-то образом использовать MKDirection (который содержит полные указания, шаг за шагом), но я не уверен, как бы я создал пару координат, которые находятся где-то посередине маршрута.

Я не смог найти какую-либо поддержку для этого в документации MapKit. Любые идеи?

enter image description here

Вот как я генерирую маршрут и показываю его.

- (void)generateRoute {
    MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
    request.source = [MKMapItem mapItemForCurrentLocation];
    request.destination = self.destinationMapItem;
    MKDirections *directions = [[MKDirections alloc] initWithRequest:request];

    [directions calculateDirectionsWithCompletionHandler:
     ^(MKDirectionsResponse *response, NSError *error) {
         if (error) {
             // Handle Error
         } else {
             [self showRoute:response];
         }
     }];
}

- (void)showRoute:(MKDirectionsResponse *)response {
    [self.mapView removeOverlays:self.mapView.overlays];
    for (MKRoute *route in response.routes)
    {
        [self.mapView addOverlay:route.polyline level:MKOverlayLevelAboveRoads];
    }
    [self fitRegionToRoute];
}

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id < MKOverlay >)overlay
{
    MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
    renderer.strokeColor = [UIColor blueColor];
    renderer.alpha = 0.7;
    renderer.lineWidth = 4.0;

    return renderer;
}

Ответ 1

Редактор комментариев:

Наконец, это помогло с помощью этого ответа. Я добавил это к приведенному ниже коду, где говорится: "Делайте магию:

MKMapPoint middlePoint = route.polyline.points[route.polyline.pointCount/2];
[self createAndAddAnnotationForCoordinate:MKCoordinateForMapPoint(middlePoint)];

Оригинальный ответ:

Я не знаю, будет ли это работать или нет. Просто моя идея по твоему вопросу.

Я предполагаю, что вы создали маршруты следующим образом: (проверьте мои встроенные комментарии)

MKDirectionsRequest *request = 
       [[MKDirectionsRequest alloc] init];
request.source = [MKMapItem mapItemForCurrentLocation];
request.destination = _destination;
request.requestsAlternateRoutes = NO;
MKDirections *directions = 
       [[MKDirections alloc] initWithRequest:request];

    [directions calculateDirectionsWithCompletionHandler:
 ^(MKDirectionsResponse *response, NSError *error) {
     if (error) {
         // Handle error
     } else {
         for (MKRoute *route in response.routes)
         {
             [_routeMap addOverlay:route.polyline level:MKOverlayLevelAboveRoads];
             //Here do the magic
             //MKPolyline confronts to MKOverlay so you can get the coordinate like 
             //route.polyline.coordinate once you get the coordinate then you can build
             //a annotation. A annotation is nothing but a coordinate with some title.
             //According to MKOverlay coordinate property it justs gives you the 
             //center point of the overlay area
             [self createAndAddAnnotationForCoordinate:route.polyline.coordinate]
         }
     }
 }];

Добавление аннотации

-(void) createAndAddAnnotationForCoordinate : (CLLocationCoordinate2D) coordinate{
    MyAnnotation* annotation= [[MyAnnotation alloc] init];
    annotation.coordinate = coordinate;

    annotation.title = @"Any Title";
    annotation.subtitle = @"Any Subtitle";

   [yourMap addAnnotation: annotation];

}

Ответ 2

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

Даже если линия дико изогнута, средняя точка будет находиться между концами. Некоторая точка на дикой кривой наиболее близка к этой внешней средней точке и, вероятно, является хорошим местом для размещения аннотации.

Ответ 3

Как только у вас есть MKRoute, приблизительную точку центра можно найти, используя:

route.polyline.coordinate

Это возвращает CLLocationCoordinate2D, который вы можете использовать для центрирования аннотации.

Оцените, что это старый вопрос, но я некоторое время искал что-то подобное и закончил вычислять центр вручную. Оказывается, это очень просто, поскольку iOS 8.

Ответ 4

Если вы хотите знать середину для быстрого, вы можете использовать следующий код:

MKCoordinateForMapPoint(route.polyline.points()[route.polyline.pointCount/2])

Пример использования:

directions.calculateDirectionsWithCompletionHandler ({
     (response: MKDirectionsResponse?, error: NSError?) in

     if error == nil {
        self.showRoute(response!)
     }
     else{
        print("some error")    
     }
})

func showRoute(response:MKDirectionsResponse){
    for route in response.routes {
        self.map.addOverlay(route.polyline, level: MKOverlayLevel.AboveRoads)
        self.map.setCenterCoordinate(route.polyline.coordinate, animated: true)
        self.map.setRegion(MKCoordinateRegionMakeWithDistance(route.polyline.coordinate, route.distance*0.75, route.distance*0.75), animated: true)

        let routeAnnotation = MKPointAnnotation()
        routeAnnotation.coordinate = MKCoordinateForMapPoint(route.polyline.points()[route.polyline.pointCount/2])
        map.addAnnotation(routeAnnotation)
    }
}

Ответ 5

Я предлагаю вам увидеть this, интегрированный с маршрутизацией.