3

我知道几年前就有人问过这个问题,但是所有答案都涉及使用 Google Maps API 来解决这个问题。我想知道现在是否有合适的方法来解决这个问题,现在 iOS8 已经出来了,它给原生 MapKit 带来了很多改进。

基本上我在路上画了一条折线,它由许多中间点组成。

    var locations = [CLLocation]()
    for item in list {
        locations.append(CLLocation(latitude: CLLocationDegrees(item["location"]["coordinate"]["x"].doubleValue), longitude: CLLocationDegrees(item["location"]["coordinate"]["y"].doubleValue)))
    }
    var coordinates = locations.map({(location: CLLocation!) -> CLLocationCoordinate2D in return location.coordinate})
    var polyline = MKPolyline(coordinates: &coordinates, count: locations.count)
    mapView.addOverlay(polyline)

一次在地图上有 5 到 30 个点。当折线将它们连接起来时,我或多或少地得到了旅行的公平表示。问题是:它不会粘在路上。

在此处输入图像描述

所以我不时地得到“粗糙”的边缘。即使我使用的是 Google Direction API,它也仅限于 8 路点,并且基本上会为您决定如何从 A 点到达 B 点,沿途绘制平滑的折线。此外,Directions API 限制为每 24 小时 2500 次使用。我需要做的就是将我当前的折线调整到最近的道路

非常感谢

4

3 回答 3

7

经过一番挖掘,我设法找到了这个问题的答案,尽管我不确定它对整体性能的影响是否会让苹果高兴,因为它发出了很多小MKDirectionsRequest的 's。对我来说 30+ 点工作得很好。

    var myRoute : MKRoute?
    var directionsRequest = MKDirectionsRequest()
    var placemarks = [MKMapItem]()
    for item in list {
        var placemark = MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: CLLocationDegrees(item["location"]["coordinate"]["x"].doubleValue), longitude: CLLocationDegrees(item["location"]["coordinate"]["y"].doubleValue)), addressDictionary: nil )
        placemarks.append(MKMapItem(placemark: placemark))
    }
    directionsRequest.transportType = MKDirectionsTransportType.Automobile
    for (k, item) in enumerate(placemarks) {
        if k < (placemarks.count - 1) {
            directionsRequest.setSource(item)
            directionsRequest.setDestination(placemarks[k+1])
            var directions = MKDirections(request: directionsRequest)
            directions.calculateDirectionsWithCompletionHandler { (response:MKDirectionsResponse!, error: NSError!) -> Void in
                if error == nil {
                    self.myRoute = response.routes[0] as? MKRoute
                    self.mapView.addOverlay(self.myRoute?.polyline)
                }
            }
        }
    }

特别感谢Anna为我指明了正确的方向。

在此处输入图像描述

于 2015-04-29T20:34:51.763 回答
1

我使用递归块来获得 72 点的路线。一直工作到 50 个请求然后 api 会抛出错误。我猜 50 是一分钟的限制。50 岁之后,我必须等待一段时间才能让 api 工作。

我使用谷歌地图绘制折线。所以下面的代码需要一个纬度、经度数组,并获取方向并将路径转换为点集并在谷歌地图上渲染。

//路径str是| 分开//让我知道这是否需要任何改进。// 我正在使用递归块,因为计算错误可能会在计算方向时引发错误,因此将其作为使用递归的顺序块。

NSArray *arr = [pathStr componentsSeparatedByString:@"|"];
    int pointsCount = (int)[arr count];
    NSMutableArray* pointsToUse = [[NSMutableArray alloc] init];

    for(NSString* locationStr in arr)
    {
        NSArray *locArr = [locationStr componentsSeparatedByString:@","];

        CLLocation *trackLocation = [[CLLocation alloc] initWithLatitude:[[locArr objectAtIndex:0] doubleValue] longitude:[[locArr objectAtIndex:1] doubleValue]];
        [pointsToUse addObject:trackLocation];
    }


    // __block declaration of the block makes it possible to call the block from within itself
    __block void (^urlFetchBlock)();


    __block int urlIndex = 0;

    // the 'recursive' block
    urlFetchBlock = [^void () {

        MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
        NSLog(@"Index Value:::%d", urlIndex);
        if(urlIndex < (pointsCount - 5))
        {
            MKPlacemark *sourcePlacemark = [[MKPlacemark alloc] initWithCoordinate:((CLLocation*)pointsToUse[urlIndex]).coordinate addressDictionary:nil];
            MKMapItem *sourceMapItem = [[MKMapItem alloc] initWithPlacemark:sourcePlacemark];
            [request setSource:sourceMapItem];

            MKPlacemark *destPlacemark = [[MKPlacemark alloc] initWithCoordinate:((CLLocation*)pointsToUse[urlIndex + 5]).coordinate addressDictionary:nil];
            MKMapItem *destMapItem = [[MKMapItem alloc] initWithPlacemark:destPlacemark];

            [request setDestination:destMapItem];
            //            NSLog(@"Source:%f ::%f, Dest: %f :: %f", ((CLLocation*)pointsToUse[i]).coordinate.latitude,((CLLocation*)pointsToUse[i]).coordinate.longitude, ((CLLocation*)pointsToUse[i+1]).coordinate.latitude, ((CLLocation*)pointsToUse[i+1]).coordinate.longitude);

            [request setTransportType:MKDirectionsTransportTypeAny];

            request.requestsAlternateRoutes = NO;

            MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
            [directions calculateDirectionsWithCompletionHandler:
             ^(MKDirectionsResponse *response, NSError *error) {
                 if (error) {
                     // Handle Error
                     NSLog(@"Error for this particular call");
                     urlIndex +=5;
                     urlFetchBlock();
                 } else {

                     for (MKRoute * route in response.routes) {

                         NSUInteger pointCount = route.polyline.pointCount;

                         NSLog(@"%lu", (unsigned long)pointCount);
                         //allocate a C array to hold this many points/coordinates...
                         CLLocationCoordinate2D *routeCoordinates
                         = malloc(pointCount * sizeof(CLLocationCoordinate2D));

                         //get the coordinates (all of them)...
                         [route.polyline getCoordinates:routeCoordinates
                                                  range:NSMakeRange(0, pointCount)];

                         GMSMutablePath *path = [GMSMutablePath path];

                         //this part just shows how to use the results...
                         for (int c=0; c < pointCount; c++)
                         {
                             [path addLatitude:routeCoordinates[c].latitude longitude:routeCoordinates[c].longitude];

                         }
                         GMSPolyline *polyline = [GMSPolyline polylineWithPath: path];

                         polyline.tappable  =  YES;
                         polyline.strokeWidth = width;

                         //                        polyline.strokeColor = [UIColor redColor];
                         polyline.geodesic = YES;
                         //    polyline.title = @"Driving route";
                         polyline.map = gMapView;
                         polyline.spans = @[[GMSStyleSpan spanWithColor:[UIColor redColor]]];
                     }
                     urlIndex +=5;
                     urlFetchBlock();

                 }
             }];

        }
    } copy];

    // initiate the url requests
    urlFetchBlock();
于 2016-03-28T22:41:29.433 回答
0

我尝试了很多代码,最后得到如下代码:

在此处输入图像描述

获取完整代码: https ://github.com/javedmultani16/MapKitWithPolyLine

这是相同的代码:

  var locRoute : MKRoute?
    var directionsRequest = MKDirections.Request()
    var arrayPlacemarks = [MKMapItem]()

    var selectedPin:MKPlacemark? = nil
    let locationManager = CLLocationManager()

并在 ViewDidLoad() 上编写以下代码:

    override func viewDidLoad() {
        super.viewDidLoad()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.requestLocation()


        locationSearchTable.mapView = mapView
        mapView.delegate = self
    }

现在去委托方法:


extension ViewController : MKMapViewDelegate {
    func mapView(_: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?{
        if annotation is MKUserLocation {
            //return nil so map view draws "blue dot" for standard user location

            //Add source location as user location
            let arrayPlacemarksource = MKPlacemark(coordinate: annotation.coordinate, addressDictionary: nil)
            arrayPlacemarks.append(MKMapItem(placemark: arrayPlacemarksource))
            return nil
        }
        let reuseId = "pin"
        var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
        pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
        pinView?.pinTintColor = UIColor.orange
        pinView?.canShowCallout = true
        let smallSquare = CGSize(width: 30, height: 30)
        let button = UIButton(frame: CGRect(origin: CGPoint(x: 0,y :0), size: smallSquare))
        button.setBackgroundImage(UIImage(named: "car"), for: .normal)
        button.addTarget(self, action: #selector(ViewController.getDirections), for: .touchUpInside)
        pinView?.leftCalloutAccessoryView = button
        return pinView
    }
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        if overlay.isKind(of: MKPolyline.self){
                var polylineRenderer = MKPolylineRenderer(overlay: overlay)
                polylineRenderer.fillColor = UIColor.blue
                polylineRenderer.strokeColor = UIColor.blue
                polylineRenderer.lineWidth = 2

            return polylineRenderer
     }
        return MKOverlayRenderer(overlay: overlay)
    }

}

绘制折线,如:


        //Add destination placemark...
        arrayPlacemarks.append(MKMapItem(placemark: placemark))

        directionsRequest.transportType = MKDirectionsTransportType.automobile

        //Draw polyline by using MKRoute so it follows the street roads...
        for (k, item) in arrayPlacemarks.enumerated() {
            if k < (arrayPlacemarks.count - 1) {
                directionsRequest.source = item
                directionsRequest.destination = arrayPlacemarks[k+1]

                let directions = MKDirections(request: directionsRequest)
          directions.calculate { (response:MKDirections.Response!, error: Error!) -> Void in
                    if error == nil {
                        self.locRoute = response.routes[0] as? MKRoute
                        let geodesic:MKPolyline = self.locRoute!.polyline
                        self.mapView.addOverlay(geodesic)
                    }
                }
            }
        }

        mapView.addAnnotation(annotation)
        let span = MKCoordinateSpan.init(latitudeDelta: 0.05, longitudeDelta: 0.05) //MKCoordinateSpanMake(0.05, 0.05)
        let region = MKCoordinateRegion.init(center: placemark.coordinate, span: span)
        mapView.setRegion(region, animated: true)
于 2019-10-24T04:12:15.993 回答