我知道几年前就已经问过这个问题,但所有答案都涉及使用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次使用。我需要做的就是将我当前的折线调整到最近的道路
非常感谢
答案 0 :(得分:1)
我使用递归块来获得72分的路线。总是它工作到50请求然后api抛出我的错误。我猜50是一分钟的限制。 50后我必须等待一段时间才能完成api工作。
我使用谷歌地图绘制折线。所以下面的代码采用lat,long数组并获取方向并将路径转换为一组点并在Google地图上呈现。
// Pathstr是|分离 //如果需要改进,请告诉我。 //我正在使用递归块,因为错误计算可能会在计算方向时产生错误,因此将其作为使用递归的顺序块。
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();
答案 1 :(得分: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)