I have map view over which i like to draw line using overlay method, i added two location latitude and longitude to draw line between them when i pressed button, but when i pressed second time new paire of coordinates i provide and new line over map appers but previous overlay path got vanished, but i need previou path on the same map also
here is my code .
- (IBAction)refreshMapMethod:(id)sender
{
int kk=[[NSUserDefaults standardUserDefaults]integerForKey:#"ham"];
if (kk==1)
{
CLLocationCoordinate2D coordinateArray[2];
coordinateArray[0] = CLLocationCoordinate2DMake(12.915181,+77.626055);
coordinateArray[1] = CLLocationCoordinate2DMake(12.892156, +77.582188);
self.routeLine = [MKPolyline polylineWithCoordinates:coordinateArray count:2];
[self.myMapView setVisibleMapRect:[self.routeLine boundingMapRect]];
[self.myMapView addOverlay:self.routeLine];
[[NSUserDefaults standardUserDefaults]setInteger:2 forKey:#"ham" ];
}
if (kk==2)
{
CLLocationCoordinate2D coordinateArray[2];
coordinateArray[0] = CLLocationCoordinate2DMake(12.892156,+77.426055);
coordinateArray[1] = CLLocationCoordinate2DMake(12.892156, +77.582188);
self.routeLine = [MKPolyline polylineWithCoordinates:coordinateArray count:2];
[self.myMapView setVisibleMapRect:[self.routeLine boundingMapRect]];
[self.myMapView addOverlay:self.routeLine];
[[NSUserDefaults standardUserDefaults]setInteger:3 forKey:#"ham" ];
}
if (kk==3)
{
CLLocationCoordinate2D coordinateArray[2];
coordinateArray[0] = CLLocationCoordinate2DMake(12.892156, +77.382188);
coordinateArray[1] = CLLocationCoordinate2DMake(12.892156, +77.282188);
self.routeLine = [MKPolyline polylineWithCoordinates:coordinateArray count:2];
[self.myMapView setVisibleMapRect:[self.routeLine boundingMapRect]];
[self.myMapView addOverlay:self.routeLine];
[[NSUserDefaults standardUserDefaults]setInteger:3 forKey:#"ham" ];
}
CLLocationCoordinate2D zoomLocation;
zoomLocation.latitude= 12.915181;
zoomLocation.longitude=77.626055;
MKCoordinateRegion viewRegion=MKCoordinateRegionMakeWithDistance(zoomLocation, 3*METERS_PER_MILE, 3*METERS_PER_MILE);
[self.myMapView setRegion:viewRegion animated:YES];
[[NSUserDefaults standardUserDefaults]setInteger:2 forKey:#"change" ];
}
calling overlay method ..
-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
if(overlay == self.routeLine)
{
if(nil == self.routeLineView)
{
self.routeLineView = [[MKPolylineView alloc] initWithPolyline:self.routeLine];
self.routeLineView.fillColor = [UIColor redColor];
self.routeLineView.strokeColor = [UIColor redColor];
self.routeLineView.lineWidth = 5;
}
return self.routeLineView;
}
return nil;
}
please provide me the solution in tye same way or the other any alternate way .
than you .
It's because you are only allowing the viewForOverlay function to return the view for self.routeline and you only have one of those. Every other call to viewForOverlay will return nil and therefore not be drawn. What you need to do is draw all the overlays.
-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
MKPolylineView* routeLineView = [[MKPolylineView alloc] initWithPolyline:(MKPolyLine)overlay];
routeLineView.fillColor = [UIColor redColor];
routeLineView.strokeColor = [UIColor redColor];
routeLineView.lineWidth = 5;
return routeLineView;
}
You'll probably need to do some more stuff like checking the overlay actually is a polyline first, but this should be enough to get you going.
Related
I had an application in which i am showing polylines in mkmapkit like this -
self.routeLine = [MKPolyline polylineWithCoordinates:coordinateArray count:4];
//[self.mapView setVisibleMapRect:[self.routeLine boundingMapRect]]; //If you want the route to be visible
[self.mapView addOverlay:self.routeLine];
-(MKPolylineRenderer *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
if(overlay == self.routeLine)
{
if(nil == self.routeLineView)
{
self.routeLineView = [[MKPolylineRenderer alloc] initWithPolyline:self.routeLine];
self.routeLineView.fillColor = [UIColor redColor];
self.routeLineView.strokeColor = [UIColor redColor];
self.routeLineView.lineWidth = 2;
}
return self.routeLineView;
}
return nil;
}
Now i want to add an arrow over that polylines to show the direction like this
How to draw an arrow on every polyline segment on Google Maps V3
. I googled for the same but no luck so far. Can anybody direct me on how to achieve this?
I would suggest actually drawing the arrow yourself with an MKOverlayPathRenderer, as I do in this example:
I am using OCMapView in my project . OCMapView is Map Kit cluster pinpoints.
I want to add line on mapkit. like this
But my code doing this : it's not logical add to overlay line on map .
I handle this code .
CLLocationCoordinate2D *coordinates
= malloc(sizeof(CLLocationCoordinate2D) * [self.mapView.annotations count]);
for (int i=0; i<[self.mapView.annotations count]; i++) {
OCMapViewSampleHelpAnnotation * ann=[annodationArray objectAtIndex:i];
coordinates[i]=ann.coordinate;
}
self.routeLineView=nil;
self.routeLine = [MKPolyline polylineWithCoordinates:coordinates count:self.mapView.annotations.count]; //
free(coordinates);
[self.mapView setVisibleMapRect:[self.routeLine boundingMapRect]]; //If you want the route to be visible
dispatch_async(dispatch_get_main_queue(), ^{
[self.mapView addOverlay:self.routeLine];
});
you can see my overlay delagate method
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay{
//normally here is circle.
if(overlay == self.routeLine)
{
if(nil == self.routeLineView)
{
self.routeLineView = [[MKPolylineView alloc] initWithPolyline:self.routeLine];
self.routeLineView.fillColor = [UIColor redColor];
self.routeLineView.strokeColor = [UIColor redColor];
self.routeLineView.lineWidth = 3;
}
return self.routeLineView;
}
return nil;
}
also I am sharing my project code . How can I solve this problem ?
https://www.dropbox.com/s/q0gtwihtl8o2pom/OCMapView-master.zip
Just use self.mapView.displayedAnnotations (these are only the ones visible) instead of self.mapView.annotations (these are all annotations, that were added).
I have been building an app which draw the lines of the current user moving along the map. Now, in iOS5 when I add the overlay to the mapview, it justs add it directly, in iOS6 it adds the overlay with "fade in" animation. I don't want this annoying animation. I also have a function which plays the trail upon the coordinates saved (after the user is done running or walking), when I play this, the lines flicker very fast, just because of this animation. This is really annoying and I really would appreciate any guidance or a solution to get rid of this animation.
Code for adding overlays:
MKMapPoint *pointsArray = malloc(sizeof(CLLocationCoordinate2D)*2);
pointsArray[0]= MKMapPointForCoordinate(oldLocation.coordinate);
pointsArray[1]= MKMapPointForCoordinate(newLocation.coordinate);
self.routeLine = [MKPolyline polylineWithPoints:pointsArray count:2];
free(pointsArray);
[self.mapView addOverlay:self.routeLine];
Code for displaying overlay:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay{
MKOverlayView *overlayView = nil;
MKPolylineView *routeLineView = [[MKPolylineView alloc] initWithPolyline:(MKPolyline *)overlay];
routeLineView.fillColor = [UIColor blueColor];
routeLineView.strokeColor = [UIColor blueColor];
routeLineView.backgroundColor = [UIColor clearColor];
routeLineView.lineWidth = 10;
routeLineView.lineCap = kCGLineCapRound;
overlayView = routeLineView;
return overlayView;
}
Thanks!
EDIT:
Code for going through the path:
playTimer = [NSTimer scheduledTimerWithTimeInterval:interval
target:self
selector:#selector(playPathTimer)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:playTimer forMode:NSRunLoopCommonModes];
- (void)playPathTimer{
MKMapPoint *pointsArray = malloc(sizeof(CLLocationCoordinate2D) * 2);
double latitude1 = ((WorldPoint *)[coordsArray objectAtIndex:playCounter]).latitude.doubleValue;
double longitude1 = ((WorldPoint *)[coordsArray objectAtIndex:playCounter]).longitude.doubleValue;
double latitude2 = ((WorldPoint *)[coordsArray objectAtIndex:playCounter+nextCord]).latitude.doubleValue;
double longitude2 = ((WorldPoint *)[coordsArray objectAtIndex:playCounter+nextCord]).longitude.doubleValue;
CLLocation *location1 = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(latitude1, longitude1)
altitude:0
horizontalAccuracy:0
verticalAccuracy:0
timestamp:[NSDate date]];
CLLocation *location2 = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(latitude2, longitude2)
altitude:0
horizontalAccuracy:0
verticalAccuracy:0
timestamp:[NSDate date]];
pointsArray[0] = MKMapPointForCoordinate(location1.coordinate);
pointsArray[1] = MKMapPointForCoordinate(location2.coordinate);
self.routeLine = [MKPolyline polylineWithPoints:pointsArray count:2];
free(pointsArray);
[self.mapView addOverlay:self.routeLine];
[playRouteLines addObject:self.routeLine];
// self.mapView.centerCoordinate = CLLocationCoordinate2DMake(latitude1, longitude1);
playCounter = playCounter + nextCord;
if(playCounter + nextCord >= coordsArray.count){
// [displayLink setPaused:YES];
// [displayLink invalidate];
[playTimer invalidate];
playTimer = nil;
playCounter = 0;
[self showStartAndEndFlags];
if(ee.trail.checkpoint.count > 0){
[self showCheckpoints];
}
self.playButton.enabled = YES;
MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:[self getRegionWithCorrectZooming]];
[self.mapView setRegion:adjustedRegion animated:YES];
}
}
Instead of using a MKPolylineView you can use your own subclass of MKOverlayView (superclass of MKPolylineView) and then override drawMapRect:zoomScale:inContext: where you draw the lines yourself.
I guess with this you won't have any fade in animation (I'm using it and never noticed any animation).
Try the following code for your drawMapRect:zoomScale:inContext: implementation.
You need to create the properties lineColor(CGColor) and lineWidth (CGFloat).
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context {
MKPolyline *polyline = self.overlay;
CGContextSetStrokeColorWithColor(context, self.lineColor);
CGContextSetLineWidth(context, self.lineWidth/zoomScale);
CGMutablePathRef path = CGPathCreateMutable();
CGPoint *points = malloc(sizeof(CGPoint)*polyline.pointCount);
for (int i=0; i<polyline.pointCount; i++) {
points[i] = [self pointForMapPoint:polyline.points[i]];
}
CGPathAddLines(path, NULL, points, polyline.pointCount);
CGContextAddPath(context, path);
CGContextDrawPath(context, kCGPathStroke);
CGPathRelease(path);
free(points);
}
I'm trying to add MKPolyLine to my mapView. But got error: NSInvalidArgumentException', reason: '-[MKPolylineView boundingMapRect]
My code:
- (void)addRoad {
[self loadRoude];
[self.mapView addOverlay:self.routeLine];
}
- (void)loadRoude{
MKMapPoint northEastPoint = MKMapPointForCoordinate(self.mapView.userLocation.coordinate);
MKMapPoint southWestPoint = MKMapPointMake(52.142391, 21.055641);
MKMapPoint* pointArr = malloc(sizeof(CLLocationCoordinate2D) * 2);
pointArr[0] = northEastPoint;
pointArr[1] = southWestPoint;
self.routeLine = [MKPolyline polylineWithPoints:pointArr count:2];
_routeRect = MKMapRectMake(southWestPoint.x, southWestPoint.y, northEastPoint.x - southWestPoint.x, northEastPoint.y - southWestPoint.y);
free(pointArr);
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKOverlayView* overlayView = nil;
if(overlay == self.routeLine)
{
if(nil == self.routeLineView)
{
self.routeLineView = [[MKPolylineView alloc] initWithPolyline:self.routeLine];
self.routeLineView.fillColor = [UIColor redColor];
self.routeLineView.strokeColor = [UIColor redColor];
self.routeLineView.lineWidth = 3;
}
overlayView = self.routeLineView;
}
return overlayView;
}
There is my problem?
EDIT
NSLog of self.routeLineView shows me : outeLiveView = <MKPolylineView: 0x7c956d0; frame = (0 0; 0 0); opaque = NO; layer = <MKOverlayClusterProxyLayer: 0x7c97eb0>> Is this normal?
EDIT2
NSLog(#"pointArr[0]x = %f",pointArr[0].x);
NSLog(#"pointArr[0]y = %f",pointArr[0].y);
NSLog(#"pointArr[1]x = %f",pointArr[1].x);
NSLog(#"pointArr[1]y = %f",pointArr[1].y);
show:
pointArr[0]x = 149891376.014222
pointArr[0]y = 88510604.996837
pointArr[1]x = 149917951.870020
pointArr[1]y = 88495551.883086
That mean my pointers array have no nil objects. I'm really in shock
From Apple's documentation:
NSInvalidArgumentException: Name of an exception that occurs when you
pass an invalid argument to a method, such as a nil pointer where a
non-nil object is required. Available in Mac OS X v10.0 and later.
Check the values you are using to initialize routeLineView or any other MKPolylineView objects. One is probably nil.
I am trying to connect my pins using MKPolyline on my MKMapView.
It gives no errors, but the line does not show up on my map.
I have tried everything almost but still can't get it to work.
[NEW]
I have tried now commenting the rest out. I also moved everything into the same controller. The child only sends a NSMutableArray with CLLocations to its parent. I have also thought that it might be drawing on a different MKMapView than the one showing on the screen. But it seem not, because I draw pins and a TileOverlay on the same MKMapView with success.
I tried this with no success:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
NSLog(#"Drawing overlay");
if(overlay == self.routeLine)
{
NSLog(#"Drawing routeLine");
if(nil == self.routeLineView)
{
NSLog(#"Drawing routeLineView");
NSLog(#"Point Count: %d",self.routeLine.pointCount);
/*MKMapPoint *tmp = self.routeLine.points;
for(int i = 0; i < self.routeLine.pointCount;i++)
NSLog(#"Points: %d\t%#",i, tmp[i]);*/ // Can't find way to output points
self.routeLineView = [[[MKPolylineView alloc] initWithPolyline:self.routeLine] autorelease];
self.routeLineView.fillColor = [UIColor redColor];
self.routeLineView.strokeColor = [UIColor redColor];
self.routeLineView.lineWidth = 3;
NSLog(#"After setting line specs");
}
return self.routeLineView;
NSLog(#"Not supposed to be called");
}
/*TileOverlayView *view = [[TileOverlayView alloc] initWithOverlay:overlay];
view.tileAlpha = 0.6;
return [view autorelease];*/
return nil;
}
This outputs:
Drawing overlay
Drawing routeLine
Drawing routeLineView
Point Count: 2
After setting line specs
[Initial Question]
I will post my code in reverse of how stuff happens:
mapView:viewForOverlay:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
NSLog(#"Drawing overlay");
if(overlay == self.routeLine)
{
NSLog(#"Drawing routeLine");
if(nil == self.routeLineView)
{
NSLog(#"Drawing routeLineView");
self.routeLineView = [[[MKPolylineView alloc] initWithPolyline:self.routeLine] autorelease];
self.routeLineView.fillColor = [UIColor redColor];
self.routeLineView.strokeColor = [UIColor redColor];
self.routeLineView.lineWidth = 3;
}
return self.routeLineView;
}
//Not part of the Question
TileOverlayView *view = [[TileOverlayView alloc] initWithOverlay:overlay];
view.tileAlpha = 0.6;
return [view autorelease];
}
This outputs all to the console:
Drawing overlay
Drawing routeLine
Drawing routeLineView
Adding the line
-(void)addRouteLine:(MKPolyline *)route
{
self.routeLine = route;
NSLog(#"addRouteLine"); //Successfully prints in console
[myMapView addOverlay:self.routeLine];
}
Creating the line
This happens in a child modal viewcontroller
-(void)loadRoute
{
// while we create the route points, we will also be calculating the bounding box of our route
// so we can easily zoom in on it.
MKMapPoint northEastPoint;
MKMapPoint southWestPoint;
// create a c array of points.
MKMapPoint *pointArr = malloc(sizeof(CLLocationCoordinate2D) * waypoints.count);
MKPolyline *polyLine;
for(int idx = 0; idx < waypoints.count; idx++)
{
CLLocationCoordinate2D coordinate = ((CLLocation *)[waypoints objectAtIndex:idx]).coordinate;
MKMapPoint point = MKMapPointForCoordinate(coordinate);
// if it is the first point, just use them, since we have nothing to compare to yet.
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;
}
NSLog(#"Routing Waypoint:\t%f\t%f\t%.02f\t%.02f", point.x, point.y, coordinate.latitude, coordinate.longitude);
pointArr[idx] = point;
}
// create the polyline based on the array of points.
polyLine = [MKPolyline polylineWithPoints:pointArr count:(waypoints.count)];
if([self.presentingViewController isKindOfClass:[FirstViewController class]])
[(FirstViewController*)self.presentingViewController addRouteLine:polyLine];
free(pointArr);
}
This outputs the data correctly. I currently have two "Routing Waypoints". My output was:
Routing Waypoint: 145449142.044444 161268376.039062 -34.07 15.06
Routing Waypoint: 142917646.563556 157564926.760068 -29.86 11.67
This clearly indicates that the two points are valid points with actual coordinates etc.
So it creates the polyline with valid coordinates. Calls the method to draw that polyline. Then it also gets to the point where it adds the polyline as a view.
Why wouldn't this show on the map?
Please help!