緯度と経度の2つのポイントがあり、これらの2つのポイント間にMapKitのピンで線を引きたい。
私はグーグルしましたが、適切な解決策が見つかりませんでした。データポイントの配列でオーバーレイを描画していたためですが、これらの2つのポイントの間にポイントの配列がありません。
ちょうど2点で、これらの2点の間に線を引きたい場合。
助けてください。
まず、ビューコントローラーにMKMapViewDelegate
プロトコルを実装させ、必要なプロパティを宣言します。
_@property (nonatomic, retain) MKMapView *mapView; //this is your map view
@property (nonatomic, retain) MKPolyline *routeLine; //your line
@property (nonatomic, retain) MKPolylineView *routeLineView; //overlay view
_
次にviewDidLoad
内(たとえば、または初期化した場所)
_//initialize your map view and add it to your view hierarchy - **set its delegate to self***
CLLocationCoordinate2D coordinateArray[2];
coordinateArray[0] = CLLocationCoordinate2DMake(lat1, lon1);
coordinateArray[1] = CLLocationCoordinate2DMake(lat2, lon2);
self.routeLine = [MKPolyline polylineWithCoordinates:coordinateArray count:2];
[self.mapView setVisibleMapRect:[self.routeLine boundingMapRect]]; //If you want the route to be visible
[self.mapView addOverlay:self.routeLine];
_
次に、MKMapViewDelegate
のメソッド-(MKOverlayView *)mapView:viewForOverlay:
を実装します
_-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
if(overlay == self.routeLine)
{
if(nil == self.routeLineView)
{
self.routeLineView = [[[MKPolylineView alloc] initWithPolyline:self.routeLine] autorelease];
self.routeLineView.fillColor = [UIColor redColor];
self.routeLineView.strokeColor = [UIColor redColor];
self.routeLineView.lineWidth = 5;
}
return self.routeLineView;
}
return nil;
}
_
必要に応じてコードを調整できますが、2ポイント以上の場合は非常に簡単です。
#import <MapKit/MapKit.h>
- (void)viewDidLoad
{
[mapview setDelegate:self];
mapview.showsUserLocation = YES;
}
- (CLLocationCoordinate2D)coordinateWithLocation:(NSDictionary*)location
{
double latitude = [[location objectForKey:@"lat"] doubleValue];
double longitude = [[location objectForKey:@"lng"] doubleValue];
return CLLocationCoordinate2DMake(latitude, longitude);
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateSpan span = MKCoordinateSpanMake(0.005, 0.005);
MKCoordinateRegion region = MKCoordinateRegionMake(userLocation.location.coordinate, span);
[mapview setRegion:region];
[mapview setCenterCoordinate:userLocation.coordinate animated:YES];
NSString *baseUrl = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%@&sensor=true", mapview.userLocation.location.coordinate.latitude, mapview.userLocation.location.coordinate.longitude, @"24.1620661,72.394131"];
//http://maps.googleapis.com/maps/api/directions/json?origin=23.030000,72.580000&destination=23.400000,72.750000&sensor=true
NSURL *url = [NSURL URLWithString:[baseUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog(@"%@",url);
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSError *error = nil;
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSArray *routes = [result objectForKey:@"routes"];
NSLog(@"%@",routes);
NSDictionary *firstRoute = [routes objectAtIndex:0];
NSDictionary *leg = [[firstRoute objectForKey:@"legs"] objectAtIndex:0];
NSDictionary *end_location = [leg objectForKey:@"end_location"];
NSLog(@"dDDDDDD>>>>>>%@",leg);
double latitude = [[end_location objectForKey:@"lat"] doubleValue];
double longitude = [[end_location objectForKey:@"lng"] doubleValue];
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = coordinate;
point.title = [leg objectForKey:@"end_address"];
point.subtitle = @"I'm here!!!";
[self.mapview addAnnotation:point];
NSArray *steps = [leg objectForKey:@"steps"];
int stepIndex = 0;
CLLocationCoordinate2D stepCoordinates[1 + [steps count] + 1];
stepCoordinates[stepIndex] = userLocation.coordinate;
for (NSDictionary *step in steps) {
NSDictionary *start_location = [step objectForKey:@"start_location"];
stepCoordinates[++stepIndex] = [self coordinateWithLocation:start_location];
if ([steps count] == stepIndex){
NSDictionary *end_location = [step objectForKey:@"end_location"];
stepCoordinates[++stepIndex] = [self coordinateWithLocation:end_location];
}
}
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:stepCoordinates count:1 + stepIndex];
[mapview addOverlay:polyLine];
CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake((userLocation.location.coordinate.latitude + coordinate.latitude)/2, (userLocation.location.coordinate.longitude + coordinate.longitude)/2);
}];
}
次に、MKMapViewDelegateのメソッドを実装します-(MKOverlayView *)mapView:viewForOverlay:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor colorWithRed:204/255. green:45/255. blue:70/255. alpha:1.0];
polylineView.lineWidth = 1;
return polylineView;
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString *annotaionIdentifier=@"annotationIdentifier";
MKPinAnnotationView *aView=(MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:annotaionIdentifier ];
if (aView==nil) {
aView=[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:annotaionIdentifier];
aView.pinColor = MKPinAnnotationColorRed;
aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
// aView.image=[UIImage imageNamed:@"arrow"];
aView.animatesDrop=TRUE;
aView.canShowCallout = YES;
aView.calloutOffset = CGPointMake(-5, 5);
}
return aView;
}
Mkmapviewでポリラインまたはルートを描画するには、このチュートリアルを参照してください
2> ios4.0以上のバージョンから使用できます MKOverlayPathView See Apple Docs
サンプルコード:-
ポリラインを作成:-
-(void) loadRoute
{
NSString* filePath = [[NSBundle mainBundle] pathForResource:@”route” ofType:@”csv”];
NSString* fileContents = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
NSArray* pointStrings = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
MKMapPoint northEastPoint;
MKMapPoint southWestPoint;
MKMapPoint* pointArr = malloc(sizeof(CLLocationCoordinate2D) * pointStrings.count);
for(int idx = 0; idx < pointStrings.count; idx++)
{
NSString* currentPointString = [pointStrings objectAtIndex:idx];
NSArray* latLonArr = [currentPointString componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@","]];
CLLocationDegrees latitude = [[latLonArr objectAtIndex:0] doubleValue];
CLLocationDegrees longitude = [[latLonArr objectAtIndex:1] doubleValue];
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);
MKMapPoint point = MKMapPointForCoordinate(coordinate);
if (idx == 0) {
northEastPoint = point;
southWestPoint = point;
}
else
{
if (point.x > northEastPoint.x)
northEastPoint.x = point.x;
if(point.y > northEastPoint.y)
northEastPoint.y = point.y;
if (point.x < southWestPoint.x)
southWestPoint.x = point.x;
if (point.y < southWestPoint.y)
southWestPoint.y = point.y;
}
pointArr[idx] = point;
}
self.routeLine = [MKPolyline polylineWithPoints:pointArr count:pointStrings.count];
_routeRect = MKMapRectMake(southWestPoint.x, southWestPoint.y, northEastPoint.x - southWestPoint.x, northEastPoint.y - southWestPoint.y);
free(pointArr);
}
PoluLineを表示:-
[self.mapView addOverlay:self.routeLine];
オーバーレイのみを追加しても、マップ上には何もレンダリングされません。 MKMapViewDelegate実装は、追加しただけでは役に立たないため、追加したばかりのこのルートのオーバーレイを返す必要があります。
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id )overlay
{
MKOverlayView* overlayView = nil;
if(overlay == self.routeLine)
{
//if we have not yet created an overlay view for this overlay, create it now.
if(nil == self.routeLineView)
{
self.routeLineView = [[[MKPolylineView alloc] initWithPolyline:self.routeLine] autorelease];
self.routeLineView.fillColor = [UIColor redColor];
self.routeLineView.strokeColor = [UIColor redColor];
self.routeLineView.lineWidth = 3;
}
overlayView = self.routeLineView;
}
return overlayView;
}
First of all Add frame work
1 Foundation.framework
2 CoreGraphics.framework
3 CoreLocation.framework
4 MapKit.framework
次に、nsobjectファイルを作成します。たとえば、... TrailsMap.hファイル
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface TrailsMap : NSObject<MKAnnotation>
{
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *image;
NSString *subtitle;
}
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (nonatomic,copy) NSString *title;
@property (nonatomic,copy) NSString *image;
@property (nonatomic,copy) NSString *subtitle;
- (id)initWithLocation:(CLLocationCoordinate2D)coord;
TrailsMap.m
#import "TrailsMap.h"
@implementation TrailsMap
@synthesize coordinate,title,image,subtitle;
- (id)initWithLocation:(CLLocationCoordinate2D)coord{
self = [super init];
if (self) {
coordinate = coord;
}
return self;
}
今メインビューでコーディングを作成してください。
ViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
@interface ViewController : UIViewController<MKMapViewDelegate>
@property (strong, nonatomic) IBOutlet MKMapView *MapView;
@property (nonatomic, retain) MKPolyline *routeLine;
@property (nonatomic, retain) MKPolylineView *routeLineView;
-(void)LoadMapRoute;
@end
最後にmainview.mファイルにコーディングを作成します
ViewController.m
#import "ViewController.h"
#import "TrailsMap.h"
@interface ViewController ()
{
NSData *alldata;
NSMutableDictionary *data1;
NSMutableArray *RouteLocation;
NSMutableArray *RouteName;
}
@end
@implementation ViewController
@synthesize MapView,routeLine,routeLineView;
- (void)viewDidLoad
{
[super viewDidLoad];
RouteName = [[NSMutableArray alloc] initWithObjects:@"Ahmedabad",@"Rajkot", nil];
RouteLocation = [[NSMutableArray alloc] initWithObjects:@"23.0300,72.5800",@"22.3000,70.7833", nil];
[self LoadMapRoute];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
//-------------------------------------
// ************* Map ******************
//-------------------------------------
-(void)LoadMapRoute
{
MKCoordinateSpan span = MKCoordinateSpanMake(0.8, 0.8);
MKCoordinateRegion region;
region.span = span;
region.center= CLLocationCoordinate2DMake(23.0300,72.5800);
// Distance between two address
NSArray *coor1=[[RouteLocation objectAtIndex:0] componentsSeparatedByString:@","];
CLLocation *locA = [[CLLocation alloc] initWithLatitude:[[coor1 objectAtIndex:0] doubleValue] longitude:[[coor1 objectAtIndex:1] doubleValue]];
NSArray *coor2=[[RouteLocation objectAtIndex:1] componentsSeparatedByString:@","];
CLLocation *locB = [[CLLocation alloc] initWithLatitude:[[coor2 objectAtIndex:0] doubleValue] longitude:[[coor2 objectAtIndex:1] doubleValue]];
CLLocationDistance distance = [locA distanceFromLocation:locB];
NSLog(@"Distance :%.0f Meters",distance);
NSString *baseUrl = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/directions/json?origin=%@&destination=%@&sensor=true", [RouteLocation objectAtIndex:0],[RouteLocation objectAtIndex:1] ];
NSURL *url = [NSURL URLWithString:[baseUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
alldata = [[NSData alloc] initWithContentsOfURL:url];
NSError *err;
data1 =[NSJSONSerialization JSONObjectWithData:alldata options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:&err];
if (err)
{
NSLog(@" %@",[err localizedDescription]);
}
NSArray *routes = [data1 objectForKey:@"routes"];
NSDictionary *firstRoute = [routes objectAtIndex:0];
NSDictionary *leg = [[firstRoute objectForKey:@"legs"] objectAtIndex:0];
NSArray *steps = [leg objectForKey:@"steps"];
int stepIndex = 0;
CLLocationCoordinate2D stepCoordinates[[steps count]+1 ];
for (NSDictionary *step in steps)
{
NSDictionary *start_location = [step objectForKey:@"start_location"];
double latitude = [[start_location objectForKey:@"lat"] doubleValue];
double longitude = [[start_location objectForKey:@"lng"] doubleValue];
stepCoordinates[stepIndex] = CLLocationCoordinate2DMake(latitude, longitude);
if (stepIndex==0)
{
TrailsMap *point=[[TrailsMap alloc] initWithLocation:stepCoordinates[stepIndex]];
point.title =[RouteName objectAtIndex:0];
point.subtitle=[NSString stringWithFormat:@"Distance :%.0f Meters",distance];
[self.MapView addAnnotation:point];
}
if (stepIndex==[steps count]-1)
{
stepIndex++;
NSDictionary *end_location = [step objectForKey:@"end_location"];
double latitude = [[end_location objectForKey:@"lat"] doubleValue];
double longitude = [[end_location objectForKey:@"lng"] doubleValue];
stepCoordinates[stepIndex] = CLLocationCoordinate2DMake(latitude, longitude);
TrailsMap *point=[[TrailsMap alloc] initWithLocation:stepCoordinates[stepIndex]];
point.title = [RouteName objectAtIndex:1];
point.subtitle=[NSString stringWithFormat:@"Distance :%.0f Meters",distance];
[self.MapView addAnnotation:point];
}
stepIndex++;
}
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:stepCoordinates count: stepIndex];
[MapView addOverlay:polyLine];
[MapView setRegion:region animated:YES];
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor colorWithRed:204/255. green:45/255. blue:70/255. alpha:1.0];
polylineView.lineWidth = 5;
return polylineView;
}
マップに複数のピンを設定する場合は、このコードを追加するだけです。 AnnotaionはObjectfileです。
-(void)LoadMultiplePin
{
RouteName = [[NSMutableArray alloc] initWithObjects:@"Ahmedabad",@"Rajkot",@"Limdi", nil];
RouteLocation = [[NSMutableArray alloc] initWithObjects:@"23.0300,72.5800",@"22.3000,70.7833",@"22.5728,71.8114", nil];
MKCoordinateSpan span = MKCoordinateSpanMake(2.9, 2.9);
MKCoordinateRegion region;
region.span = span;
region.center= CLLocationCoordinate2DMake(22.5728,71.8114);
int cnt=RouteLocation.count;
for (int p=0 ; p<cnt ; p++ )
{
NSArray *coor=[[RouteLocation objectAtIndex:p] componentsSeparatedByString:@","];
CLLocationCoordinate2D location=CLLocationCoordinate2DMake([[coor objectAtIndex:0] doubleValue],[[coor objectAtIndex:1] doubleValue]);
Annotaion *point=[[Annotaion alloc] initWithLocation:location];
point.title =[RouteName objectAtIndex:p];
[Map addAnnotation:point];
}
[Map setRegion:region animated:YES];
}
このコードを使用すると、2つのピンを簡単にドロップして、その2つのピンの間に線を引くことができますHappy Happy Coding ... :)
私は@graverから素晴らしい答えを受け取り、Swift 3に対してこれを行いました:
// Called from viewDidLoad
func setupMap() {
mapView.delegate = self
// BusStop implements the MKAnnotation protocol, I have an array of them
let routeCoordinates = busStops.map({ $0.coordinate })
let routeLine = MKPolyline(coordinates: routeCoordinates, count: routeCoordinates.count)
mapView.setVisibleMapRect(routeLine.boundingMapRect, animated: false)
mapView.add(routeLine)
}
// MARK: MKMapViewDelegate
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let polyline = overlay as? MKPolyline {
let polylineRenderer = MKPolylineRenderer(overlay: polyline)
polylineRenderer.strokeColor = .blue
polylineRenderer.lineWidth = 3
return polylineRenderer
}
return MKOverlayRenderer(overlay: overlay)
}
住所コードを渡す
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t {
NSString* saddr = [NSString stringWithFormat:@"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:@"%f,%f", t.latitude, t.longitude];
NSString* apiUrlStr = [NSString stringWithFormat:@"http://maps.google.com/maps? output=dragdir&saddr=%@&daddr=%@", saddr, daddr];
// NSString* apiUrlStr = @"http://maps.google.com/maps?output=dragdir&saddr=40.769264,-73.958995&daddr=47.286522,-122.312932";
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSLog(@"api url: %@", apiUrl);
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSUTF8StringEncoding error:nil];
NSString* encodedPoints = [apiResponse stringByMatching:@"points:\\\"([^\\\"]*)\\\"" capture:1L];
return [self decodePolyLine:[encodedPoints mutableCopy]];
}
-(NSMutableArray *)decodePolyLine: (NSMutableString *)encoded {
[encoded replaceOccurrencesOfString:@"\\\\" withString:@"\\"
options:NSLiteralSearch
range:NSMakeRange(0, [encoded length])];
NSInteger len = [encoded length];
NSInteger index = 0;
NSMutableArray *array = [[NSMutableArray alloc] init];
NSInteger lat=0;
NSInteger lng=0;
while (index < len) {
NSInteger b;
NSInteger shift = 0;
NSInteger result = 0;
do {
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
NSNumber *latitude = [[NSNumber alloc] initWithFloat:lat * 1e-5];
NSNumber *longitude = [[NSNumber alloc] initWithFloat:lng * 1e-5];
printf("[%f,", [latitude doubleValue]);
printf("%f]", [longitude doubleValue]);
CLLocation *loc = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]];
[array addObject:loc];
}
return array;
}
-(void) updateRouteView:(UIColor *)clr {
CGContextRef context =CGBitmapContextCreate(nil,routeView.frame.size.width,routeView.frame.size.height,8,4 * routeView.frame.size.width,CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedLast);
CGContextSetStrokeColorWithColor(context, clr.CGColor);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 3.0);
for(int i = 0; i < routes.count; i++) {
CLLocation* location = [routes objectAtIndex:i];
CGPoint point = [mapView convertCoordinate:location.coordinate toPointToView:routeView];
if(i == 0) {
CGContextMoveToPoint(context, point.x, routeView.frame.size.height - point.y);
} else {
CGContextAddLineToPoint(context, point.x, routeView.frame.size.height - point.y);
}
}
CGContextStrokePath(context);
CGImageRef image = CGBitmapContextCreateImage(context);
UIImage* img = [UIImage imageWithCGImage:image];
routeView.image = img;
CGContextRelease(context);
}
ここでは、緯度と経度でルートを計算してから、MapViewでポリラインを描画する必要があります。
ここでMapKitとRagexKitLiteを使用している場合は、RagexKitLiteのデモを取得するだけでも簡単です。
完全なコードを取得: https://github.com/javedmultani16/MapKitWithPolyLine
次のように線を引く:
directionsRequest.transportType = MKDirectionsTransportType.automobile
//Draw polyline by using MKRoute so it follows the street roads...
for (k, item) in arrayarrayPlacemarks.enumerated() {
if k < (arrayarrayPlacemarks.count - 1) {
directionsRequest.source = item
directionsRequest.destination = arrayarrayPlacemarks[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)
}
}
}
}
デリゲートメソッド:
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)
}
MKPolylineを使用してマップに線を描くことができます。
このリンクを参照してください
http://spitzkoff.com/craig/?p=136
また:
https://github.com/kishikawakatsumi/MapKit-Route-Directions
これらはすべて、簡単に参照できるチュートリアルとオープンソースライブラリです。現在MapKitはこの機能をサポートしていません...