Remove Polylines from over the map Xcode - iphone

I am implementing an iphone app. i have a map and array of objects that contains the coordinates to be plotted on the map. And a polyline is drawn between these point. So i want to know how to remove this polyline. not Show/Hide, but remove.
here is my code of how i am drawing it
int pointCount = [routeLatitudes count] / 2; //routeLatitudes is the array that contains the coordinates latitude followed by longitude.
MKMapPoint* pointArr = malloc(sizeof(MKMapPoint) * pointCount);
int pointArrIndex = 0;
for (int idx = 0; idx < [routeLatitudes count]; idx=idx+2)
{
CLLocationCoordinate2D workingCoordinate;
workingCoordinate.latitude=[[routeLatitudes objectAtIndex:idx] doubleValue];
workingCoordinate.longitude=[[routeLatitudes objectAtIndex:idx+1] doubleValue];
MKMapPoint point = MKMapPointForCoordinate(workingCoordinate);
pointArr[pointArrIndex] = point;
pointArrIndex++;
}
// create the polyline based on the array of points.
routeLine = [MKPolyline polylineWithPoints:pointArr count:pointCount];
[mapView addOverlay:routeLine];
free(pointArr);
And to Show/Hide the polylines i created a reference MKOverlayView* overlayView = nil;
overlayView.hidden=false/true;
now i need to know how to remove/delete the drawn polylines.
Thank in advance.

try this
[mapView removeOverlays:mapView.overlays];

Related

Using CLLocationDistance to calculate the outermost coordinates?

I am placing 1-12 placemarks on my map. I am having trouble calculating the two outermost points so that I can zoom the map out to show all the pins.
CLLocationDistance distLong = [zoomLocationMax.longitude getDistanceFrom:zoomLocationMin.longitude];
CLLocationDistance distLat = [zoomLocationMax.latitude getDistanceFrom:zoomLocationMin.latitude];
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(m_MapView.userLocation.coordinate, distLat, distLong);
MKCoordinateRegion adjustedRegion = [m_MapView regionThatFits:viewRegion];
m_MapView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
[m_MapView setRegion:adjustedRegion animated:YES];
I have been fooling with the above code but I can foresee some issues:
1) The first two lines give me a Bad receiver type 'CLLocationDegres' (aka double'} error.
2) I do not really want the users location as the center point, I would ideally like to have the center of the two farthest points.
Any code snippet, example or explanation would greatly help!!
Thank you
Edit to show how zoomLocatin was calculated. I basically take the log and lat and determine the min and max... not sure if that is right either:
CLLocationCoordinate2D zoomLocationMin;
CLLocationCoordinate2D zoomLocationMax;
if (coordinate.latitude < zoomLocationMin.latitude)
zoomLocationMin.latitude = coordinate.latitude;
if (coordinate.longitude < zoomLocationMin.longitude)
zoomLocationMin.longitude = coordinate.longitude;
if (coordinate.latitude > zoomLocationMax.latitude)
zoomLocationMax.latitude = coordinate.latitude;
if (coordinate.longitude > zoomLocationMax.longitude)
zoomLocationMax.longitude = coordinate.longitude;
Maybe you should try this code to handle perfect fit for your placemarks :
- (void)zoomMapViewToFitAnnotations:(MKMapView *)mapView animated:(BOOL)animated
{
NSArray *annotations = mapView.annotations;
int count = [mapView.annotations count];
if ( count == 0) { return; } //return if no annotations
//convert NSArray of id <MKAnnotation> into an MKCoordinateRegion that can be used to set the map size
//can't use NSArray with MKMapPoint because MKMapPoint is not an id
MKMapPoint points[count]; //C array of MKMapPoint struct
for( int i=0; i<count; i++ ) //load points C array by converting coordinates to points
{
CLLocationCoordinate2D coordinate = [(id <MKAnnotation>)[annotations objectAtIndex:i] coordinate];
points[i] = MKMapPointForCoordinate(coordinate);
}
//create MKMapRect from array of MKMapPoint
MKMapRect mapRect = [[MKPolygon polygonWithPoints:points count:count] boundingMapRect];
//convert MKCoordinateRegion from MKMapRect
MKCoordinateRegion region = MKCoordinateRegionForMapRect(mapRect);
//add padding so pins aren't scrunched on the edges
region.span.latitudeDelta *= ANNOTATION_REGION_PAD_FACTOR;
region.span.longitudeDelta *= ANNOTATION_REGION_PAD_FACTOR;
//but padding can't be bigger than the world
if( region.span.latitudeDelta > MAX_DEGREES_ARC ) { region.span.latitudeDelta = MAX_DEGREES_ARC; }
if( region.span.longitudeDelta > MAX_DEGREES_ARC ){ region.span.longitudeDelta = MAX_DEGREES_ARC; }
//and don't zoom in stupid-close on small samples
if( region.span.latitudeDelta < MINIMUM_ZOOM_ARC ) { region.span.latitudeDelta = MINIMUM_ZOOM_ARC; }
if( region.span.longitudeDelta < MINIMUM_ZOOM_ARC ) { region.span.longitudeDelta = MINIMUM_ZOOM_ARC; }
//and if there is a sample of 1 we want the max zoom-in instead of max zoom-out
if( count == 1 )
{
region.span.latitudeDelta = MINIMUM_ZOOM_ARC;
region.span.longitudeDelta = MINIMUM_ZOOM_ARC;
}
[mapView setRegion:region animated:animated];
}
So, you have to define the Padding, Maximum degree arc and Minimum zoom arc. For Ex. should belike this :
#define MINIMUM_ZOOM_ARC 0.05 //approximately 1 miles (1 degree of arc ~= 69 miles)
#define ANNOTATION_REGION_PAD_FACTOR 1.25
#define MAX_DEGREES_ARC 360
Hopefully, You will like it, Cheers

How to zoom MapView annotations below an overlay view?

I need to zoom the map annotations below the over laid view.
Im using this method to zoom to the 2 annotations.
I can't seem to find a way to fit the 2 annotations below the over laid view, because:
Setting map edgePadding will hide the bottom pin
Setting the map center will hide the bottom pin
Setting the latitudeDelta would work I guess but if pins are horizontally parallel it would not be necessary + it would get messy with different cases.
So i'm wondering if there's an elegant solution for this problem that I might have missed?
This overlay also hides the annotation callout, I guess this could be fixed if I have a solution for the first problem.
Maybe you should try this code to handle perfect fit for Annotations :
- (void)zoomMapViewToFitAnnotations:(MKMapView *)mapView animated:(BOOL)animated
{
NSArray *annotations = mapView.annotations;
int count = [mapView.annotations count];
if ( count == 0) { return; } //return if no annotations
//convert NSArray of id <MKAnnotation> into an MKCoordinateRegion that can be used to set the map size
//can't use NSArray with MKMapPoint because MKMapPoint is not an id
MKMapPoint points[count]; //C array of MKMapPoint struct
for( int i=0; i<count; i++ ) //load points C array by converting coordinates to points
{
CLLocationCoordinate2D coordinate = [(id <MKAnnotation>)[annotations objectAtIndex:i] coordinate];
points[i] = MKMapPointForCoordinate(coordinate);
}
//create MKMapRect from array of MKMapPoint
MKMapRect mapRect = [[MKPolygon polygonWithPoints:points count:count] boundingMapRect];
//convert MKCoordinateRegion from MKMapRect
MKCoordinateRegion region = MKCoordinateRegionForMapRect(mapRect);
//add padding so pins aren't scrunched on the edges
region.span.latitudeDelta *= ANNOTATION_REGION_PAD_FACTOR;
region.span.longitudeDelta *= ANNOTATION_REGION_PAD_FACTOR;
//but padding can't be bigger than the world
if( region.span.latitudeDelta > MAX_DEGREES_ARC ) { region.span.latitudeDelta = MAX_DEGREES_ARC; }
if( region.span.longitudeDelta > MAX_DEGREES_ARC ){ region.span.longitudeDelta = MAX_DEGREES_ARC; }
//and don't zoom in stupid-close on small samples
if( region.span.latitudeDelta < MINIMUM_ZOOM_ARC ) { region.span.latitudeDelta = MINIMUM_ZOOM_ARC; }
if( region.span.longitudeDelta < MINIMUM_ZOOM_ARC ) { region.span.longitudeDelta = MINIMUM_ZOOM_ARC; }
//and if there is a sample of 1 we want the max zoom-in instead of max zoom-out
if( count == 1 )
{
region.span.latitudeDelta = MINIMUM_ZOOM_ARC;
region.span.longitudeDelta = MINIMUM_ZOOM_ARC;
}
[mapView setRegion:region animated:animated];
}
So, you have to define the Padding, Maximum degree arc and Minimum zoom arc. For Ex. should belike this :
#define MINIMUM_ZOOM_ARC 0.05 //approximately 1 miles (1 degree of arc ~= 69 miles)
#define ANNOTATION_REGION_PAD_FACTOR 1.25
#define MAX_DEGREES_ARC 360
Hopefully, You will like it, Cheers
Set userintercation disabled for the overlay if you want touch points on the overlay.
For setting the zoom level I made a few adjustments after plotting the points. You can calculate the average of the lat longs and then adjust the lat longs as per size of the overlay. Here's what I did:
float latAvg,longAvg;
latAvg = (location1.latitude + location.latitude)/2;
longAvg = (location1.longitude + location.longitude)/2;
MKCoordinateSpan span;// = MKCoordinateSpanMake(0.006, 0.006);
span.latitudeDelta = fabs(location1.latitude - location.latitude);
span.longitudeDelta = fabs(location1.longitude - location.longitude);
//Then adjust the lat longs delta according to your need.
span.latitudeDelta = span.latitudeDelta + 0.0010;
span.longitudeDelta = span.longitudeDelta + 0.0010;
CLLocationCoordinate2D locationLatlng;
locationLatlng.latitude = latAvg;
locationLatlng.longitude = longAvg;
MKCoordinateRegion viewRegion = MKCoordinateRegionMake(locationLatlng, span);
[map setRegion:viewRegion animated:YES];
[map regionThatFits:viewRegion];

how to color area on map from gps coordinates

I'm trying to plot and area on a map with multiple GPS coordinates. These coordinates will be downloaded from a web service. There are five coordinates that creates on colored area block. since I can't post images yet here is a url to the example
OutageMap
Can someone tell me what the best way of achieving this? I'm shooting in the dark here so no real code is available. The below url is what we currently use via html. Trying to create it natively to iphone instead of calling a webview.
You can use a MKPolygon and a MKPolygonView with your list of points:
When the viewController is created, or the data is loaded, you add a MKPolygon for each colored block to the map:
- (void)viewDidLoad {
for (NSDictionary *coloredAreas in coloredAreas) {
NSArray *coordinateData = coloredArea[#"coords"];
// this assumes coordinateData is an array of arrays like:
// [[0, 0], [0, 1], [0, 1]]
NSUInteger coordsLen = [coordinateData count];
CLLocationCoordinate2D *coords = malloc(sizeof(CLLocationCoordinate2D) * coordsLen);
for (int i=0; i < coordsLen; i++) {
coords[i] = CLLocationCoordinate2DMake(coordinateData[i][0], coordinateData[i][1]);
}
MKMapPoint point[] = coloredAreas['points'];
MKPolygon *polygon = [MKPolygon polygonWithPoints:points count:3];
[self.mapView addOverlay:polygon];
}
}
Then you add a mapView:viewForOverlay method to draw each polygon:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay {
MKPolygonView *polygonView = [[MKPolygonView alloc] initWithPolygon:overlay]];
polygonView.fillColor = [UIColor greenColor];
return polygonView;
}
This will draw a green box for each of your polygons. In order to have each polygon be a certain color I would create a ColoredPolygon class that is a subclass of MKPolygon and that has a color property. You then create ColoredPolygon and set the color when loading the data. In mapView:viewForOverlay you would just cast the MKOverlay to a ColoredPolygon and then set the fillColor to ColoredPolygon.color.

iOS MKMapView zoom to show all markers

I'm working with MKMapView and have plotted several points on the map. I have used the MKCoordinateRegion and MKCoordinateSpan to enable zooming etc around one of the points - but that's not what I want...
I'm trying to use something similar to the Javascript zoom to bounds function. so all my points should be visible to the user. (There will be around 10 points around the UK) I'd like to show them all, or if most of them were in the London area, zoom to there.
Is there a way to work this out programatically?
Sure. You want to find the biggest and smallest latitude and longitude values among your annotations (which you can do by iterating over map.annotations), then set the map to show all of them.
// pad our map by 10% around the farthest annotations
#define MAP_PADDING 1.1
// we'll make sure that our minimum vertical span is about a kilometer
// there are ~111km to a degree of latitude. regionThatFits will take care of
// longitude, which is more complicated, anyway.
#define MINIMUM_VISIBLE_LATITUDE 0.01
MKCoordinateRegion region;
region.center.latitude = (minLatitude + maxLatitude) / 2;
region.center.longitude = (minLongitude + maxLongitude) / 2;
region.span.latitudeDelta = (maxLatitude - minLatitude) * MAP_PADDING;
region.span.latitudeDelta = (region.span.latitudeDelta < MINIMUM_VISIBLE_LATITUDE)
? MINIMUM_VISIBLE_LATITUDE
: region.span.latitudeDelta;
region.span.longitudeDelta = (maxLongitude - minLongitude) * MAP_PADDING;
MKCoordinateRegion scaledRegion = [map regionThatFits:region];
[map setRegion:scaledRegion animated:YES];
If you are only targeting iOS 7 or greater you can now use:
- (void)showAnnotations:(NSArray *)annotations
animated:(BOOL)animated
Here is an improvement that takes into account the height of the annotation views that you are overlaying onto the map (such that the top of the annotation does not get cut off when its coordinate offset is at the bottom for example). Or to generalise further, allows you to specify padding in pixels as opposed to as a percentage. It requires a two stage pass whereby you find out the bounds for the annotations, then you further increase the bounds to take into account your map padding.
- (void) zoomToAnnotationsBounds:(NSArray *)annotations {
CLLocationDegrees minLatitude = DBL_MAX;
CLLocationDegrees maxLatitude = -DBL_MAX;
CLLocationDegrees minLongitude = DBL_MAX;
CLLocationDegrees maxLongitude = -DBL_MAX;
for (MyAnnotation *annotation in annotations) {
double annotationLat = annotation.coordinate.latitude;
double annotationLong = annotation.coordinate.longitude;
minLatitude = fmin(annotationLat, minLatitude);
maxLatitude = fmax(annotationLat, maxLatitude);
minLongitude = fmin(annotationLong, minLongitude);
maxLongitude = fmax(annotationLong, maxLongitude);
}
// See function below
[self setMapRegionForMinLat:minLatitude minLong:minLongitude maxLat:maxLatitude maxLong:maxLongitude];
// If your markers were 40 in height and 20 in width, this would zoom the map to fit them perfectly. Note that there is a bug in mkmapview's set region which means it will snap the map to the nearest whole zoom level, so you will rarely get a perfect fit. But this will ensure a minimum padding.
UIEdgeInsets mapPadding = UIEdgeInsetsMake(40.0, 10.0, 0.0, 10.0);
CLLocationCoordinate2D relativeFromCoord = [self.mapView convertPoint:CGPointMake(0, 0) toCoordinateFromView:self.mapView];
// Calculate the additional lat/long required at the current zoom level to add the padding
CLLocationCoordinate2D topCoord = [self.mapView convertPoint:CGPointMake(0, mapPadding.top) toCoordinateFromView:self.mapView];
CLLocationCoordinate2D rightCoord = [self.mapView convertPoint:CGPointMake(0, mapPadding.right) toCoordinateFromView:self.mapView];
CLLocationCoordinate2D bottomCoord = [self.mapView convertPoint:CGPointMake(0, mapPadding.bottom) toCoordinateFromView:self.mapView];
CLLocationCoordinate2D leftCoord = [self.mapView convertPoint:CGPointMake(0, mapPadding.left) toCoordinateFromView:self.mapView];
double latitudeSpanToBeAddedToTop = relativeFromCoord.latitude - topCoord.latitude;
double longitudeSpanToBeAddedToRight = relativeFromCoord.latitude - rightCoord.latitude;
double latitudeSpanToBeAddedToBottom = relativeFromCoord.latitude - bottomCoord.latitude;
double longitudeSpanToBeAddedToLeft = relativeFromCoord.latitude - leftCoord.latitude;
maxLatitude = maxLatitude + latitudeSpanToBeAddedToTop;
minLatitude = minLatitude - latitudeSpanToBeAddedToBottom;
maxLongitude = maxLongitude + longitudeSpanToBeAddedToRight;
minLongitude = minLongitude - longitudeSpanToBeAddedToLeft;
[self setMapRegionForMinLat:minLatitude minLong:minLongitude maxLat:maxLatitude maxLong:maxLongitude];
}
-(void) setMapRegionForMinLat:(double)minLatitude minLong:(double)minLongitude maxLat:(double)maxLatitude maxLong:(double)maxLongitude {
MKCoordinateRegion region;
region.center.latitude = (minLatitude + maxLatitude) / 2;
region.center.longitude = (minLongitude + maxLongitude) / 2;
region.span.latitudeDelta = (maxLatitude - minLatitude);
region.span.longitudeDelta = (maxLongitude - minLongitude);
// MKMapView BUG: this snaps to the nearest whole zoom level, which is wrong- it doesn't respect the exact region you asked for. See http://stackoverflow.com/questions/1383296/why-mkmapview-region-is-different-than-requested
[self.mapView setRegion:region animated:YES];
}
It's an old question and I know you might not need any help. But I'm just putting it out there for anyone who is looking for a way to do this now as there's a new method in MKMapView as of iOS 7 that can be used. It is both clean and easy.
Declaration
SWIFT
func showAnnotations(_ annotations: [AnyObject]!,
animated animated: Bool)
OBJECTIVE-C
- (void)showAnnotations:(NSArray *)annotations
animated:(BOOL)animated
Parameters
annotations The annotations that you want to be visible in
the map. animated YES if you want the map region change to be
animated, or NO if you want the map to display the new region
immediately without animations.
Discussion
Calling this method updates
the value in the region property and potentially other properties to
reflect the new map region.
Modified Answer with all Perfect Working Code.
//Zooming the ploted Area
- (void)zoomToAnnotationsBounds:(NSArray *)latLongArray {
__block CLLocationDegrees minLatitude = DBL_MAX;
__block CLLocationDegrees maxLatitude = -DBL_MAX;
__block CLLocationDegrees minLongitude = DBL_MAX;
__block CLLocationDegrees maxLongitude = -DBL_MAX;
[latLongArray enumerateObjectsUsingBlock:^(NSString *latLongObj, NSUInteger latLongIdx, BOOL *stop) {
latLongObj = [latLongArray objectAtIndex:latLongIdx];
NSArray *latLongPoint = [latLongObj componentsSeparatedByString:#","];
double annotationLat = [[latLongPoint objectAtIndex:0] doubleValue];
double annotationLong = [[latLongPoint objectAtIndex:1] doubleValue];
minLatitude = fmin(annotationLat, minLatitude);
maxLatitude = fmax(annotationLat, maxLatitude);
minLongitude = fmin(annotationLong, minLongitude);
maxLongitude = fmax(annotationLong, maxLongitude);
}];
[self setMapRegionForMinLat:minLatitude minLong:minLongitude maxLat:maxLatitude maxLong:maxLongitude];
}
-(void) setMapRegionForMinLat:(double)minLatitude minLong:(double)minLongitude maxLat:(double)maxLatitude maxLong:(double)maxLongitude {
// pad our map by 10% around the farthest annotations
// we'll make sure that our minimum vertical span is about a kilometer
// there are ~111km to a degree of latitude. regionThatFits will take care of
// longitude, which is more complicated, anyway.
MKCoordinateRegion region;
region.center.latitude = (minLatitude + maxLatitude) / 2;
region.center.longitude = (minLongitude + maxLongitude) / 2;
region.span.latitudeDelta = (maxLatitude - minLatitude) * MAP_PADDING;
region.span.latitudeDelta = (region.span.latitudeDelta < MINIMUM_VISIBLE_LATITUDE)
? MINIMUM_VISIBLE_LATITUDE
: region.span.latitudeDelta;
region.span.longitudeDelta = (maxLongitude - minLongitude) * MAP_PADDING;
MKCoordinateRegion scaledRegion = [regionsMapView regionThatFits:region];
[regionsMapView setRegion:scaledRegion animated:YES];
}

How do I show the user's location, and additional points on an iPhone map?

Basically I want to show the users location plus a list of selected location on a map. It can even have the standard iphone annotations. But, I have no idea of the general steps I would take to achieve this. Would I use MKMapView, or Core Location, or both? Could someone give me a simple outline of steps to take, or a link to a good tutorial or sample code. Thanks
To expand, I was wondering if there are any examples anywhere on how to deal with arrays of locations. I'm guessing that I would need to identify the users location then set up a radius of how far I want to reference locations away from the user, then populate that radius with an array of location that fit within that radius. Are my thoughts on this correct? And are there any examples out there of how to do at least a part of this. I have seen a ton of examples on how to show a single location, but none dealing with multiple locations.
Here's something I'm using that may help you. It will give you an MKCoordinateRegion that fits an array of CLLocations. You can then use that region to pass it to MKMapView setRegion:animated:
// create a region that fill fit all the locations in it
+ (MKCoordinateRegion) getRegionThatFitsLocations:(NSArray *)locations {
// initialize to minimums, maximums
CLLocationDegrees minLatitude = 90;
CLLocationDegrees maxLatitude = -90;
CLLocationDegrees minLongitude = 180;
CLLocationDegrees maxLongitude = -180;
// establish the min and max latitude and longitude
// of all the locations in the array
for (CLLocation *location in locations) {
if (location.coordinate.latitude < minLatitude) {
minLatitude = location.coordinate.latitude;
}
if (location.coordinate.latitude > maxLatitude) {
maxLatitude = location.coordinate.latitude;
}
if (location.coordinate.longitude < minLongitude) {
minLongitude = location.coordinate.longitude;
}
if (location.coordinate.longitude > maxLongitude) {
maxLongitude = location.coordinate.longitude;
}
}
MKCoordinateSpan span;
CLLocationCoordinate2D center;
if ([locations count] > 1) {
// for more than one location, the span is the diff between
// min and max latitude and longitude
span = MKCoordinateSpanMake(maxLatitude - minLatitude, maxLongitude - minLongitude);
// and the center is the min + the span (width) / 2
center.latitude = minLatitude + span.latitudeDelta / 2;
center.longitude = minLongitude + span.longitudeDelta / 2;
} else {
// for a single location make a fixed size span (pretty close in zoom)
span = MKCoordinateSpanMake(0.01, 0.01);
// and the center equal to the coords of the single point
// which will be the coords of the min (or max) coords
center.latitude = minLatitude;
center.longitude = minLongitude;
}
// create a region from the center and span
return MKCoordinateRegionMake(center, span);
}
As you're probably already established, you'll need to use a MKMapView and Core Location to do what you want. In my app I know what locations I want to display, and then make the MKMapView big enough to fit them all in. The method above will help you do that. If however you want to get a list of locations that fit within a given map region, then you'll have to do more or less the reverse of what I'm doing above.
Here's three:
http://mithin.in/2009/06/22/using-iphone-sdk-mapkit-framework-a-tutorial/
http://blog.objectgraph.com/index.php/2009/04/02/iphone-sdk-30-playing-with-map-kit/
http://www.iphonedevsdk.com/forum/tutorial-discussion/39374-mkmapview-tutorial-using-latitude-longitude.html