I am using google map sdk for ios to provide directions between current user location and an end location. I have so far achieved to draw a GMSPolyline between the current user location and the end location using the code below and it's working great.
GMSPath *encodedPath = [GMSPath pathFromEncodedPath:encodedPathSting];
self.polyline = [GMSPolyline polylineWithPath:encodedPath];
self.polyline.strokeWidth = 4;
self.polyline.strokeColor = [UIColor colorWithRed:55.0/255.0 green:160.0/255.0 blue:250.0/255.0 alpha:1.0];;
self.polyline.map = self.mapView;
Is it possible to remove a part of the GMSPolyline that has been covered by the user through driving/walking? The GMSPolyline must gradually decrease in length as we trace the path.
One way to achieve this is by redrawing the path repeatedly but this is not or may not be efficient.
Thanks.
So get the latlng point of the polyline in an array as described here:
//route is the MKRoute in this example
//but the polyline can be any MKPolyline
NSUInteger pointCount = route.polyline.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)
];
//this part just shows how to use the results...
NSLog(#"route pointCount = %d", pointCount);
for (int c = 0; c < pointCount; c++) {
NSLog(#"routeCoordinates[%d] = %f, %f",
c, routeCoordinates[c].latitude, routeCoordinates[c].longitude);
}
//free the memory used by the C array when done with it...
free(routeCoordinates);
Then, implement a while loop for the first point as you move along the path like this:
int c = 0;
while (pointCount.size() > 0)
{
pointCount.get(0).remove();
}
Note: I'm not that experienced with iOS and haven't tested this solution. Treat it as a suggestion rather than a fix. Thanks!
Hope it helps!
Related
I have a list of 50+ coordinates. What is the most efficient way to draw lines between all these coordinates (should create a "circular" path because they all have a display order) that is also easy to customize (line thickness, color, etc...)?
Thanks!
I am not sure I understand your question for certain. If you are looking for a list of points to display from end to end, then you will want to create a MKPolyline object from those points, making sure the points are added to the myPoints array in the order you want to connect them:
CLLocationCoordinate2D coordinates[[myPoints count]];
int i = 0;
for (Checkpoint *point in myPoints)
{
coordinates[i] = CLLocationCoordinate2DMake([point.lat floatValue] , [point.lon floatValue]);
i++;
}
self.polyline = [MKPolyline polylineWithCoordinates:coordinates count: [myPoints count]];
[mapView addOverlay:self.polyline];
Then make sure you are implementing the delegate method - mapView:rendererForOverlay:. Here's an example, but tailor it to your needs:
-(MKOverlayRenderer*)mapView:(MKMapView*)mapView rendererForOverlay:(id <MKOverlay>)overlay
{
MKPolylineRenderer* lineView = [[MKPolylineRenderer alloc] initWithPolyline:self.polyline];
lineView.strokeColor = [UIColor blueColor];
lineView.lineWidth = 7;
return lineView;
}
However, if you really want a closed loop (circular) object, then you will want to create a MKPolygon object instead. The process is quite similar; in that case replace the self.polyline initializer above with this code:
self.polygon = [MKPolygon polygonWithCoordinates:coordinates count: [myPoints count]];
[mapView addOverlay:self.polygon];
The - mapView:rendererForOverlay: code should remain the same I think. I haven't tested this code, but hopefully it gets you moving in the right direction.
I wants to draw polyline for walk like google map app in ios using google maps ios sdk. For more clear understanding i am uploading image that is from google map app(ios.)
Are you asking how to achieve the dotted polyline effect? If so, I don't believe that is supported in the SDK.
You can manually create a similar effect with GMSCircles.
for(int x = 0; x < [self.path count]; x++)
{
CLLocationCoordinate2D coord = [self.path coordinateAtIndex:x];
//draw circle coord
GMSCircle *circle = [GMSCircle circleWithPosition:coord radius:20];
circle.fillColor = [UIColor blueColor];
circle.strokeColor = [UIColor blackColor];
circle.strokeWidth = 2;
circle.map = mapView;
}
For this to really look like the original example you will probably need to add additional points onto the line in order for the circles to be evenly spaced out. For that you could do something like this.
for(all the points in the path)
{
if(the distance from pointA to pointB is > some distance)
{
centerPtr = center point of pointA and pointB
insert centerPt in path
}
}
You can turn this into a simple recursive function that should give you something similar to what you are looking for.
I am using GMSCoordinateBounds to get a list of markers that are in visible area. But I am getting all the markers that are plotted instead of just visible ones.
This is how I am doing it:
GMSVisibleRegion visibleRegion = [mapView_.projection visibleRegion];
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc]initWithRegion:visibleRegion];
GMSMarker *resultMarker = [[GMSMarker alloc]init];
for (int i=0; i<[markerArray count]; i++) //this has all the markers
{
resultMarker = [markerArray objectAtIndex:i];
if ([bounds containsCoordinate:resultMarker.position])
{
NSLog(#"User is present on screen");
[listTableArray addObject:resultMarker.title];
}
}
[listTableView reloadData];
Your code looks fine. I'm pretty sure whatever your issue is, it's coming from somewhere other than the code you posted.
Another potential issue is that if your map allows rotation, all manner of disorienting stuff will happen to your GMSVisibleRegion object. (ie. the farLeft property won't correspond to the north-western point). I'd think GMSCoordinateBounds would take that into account and not get tripped by it.
Having said that, you can write your own method to check if a marker's coordinate is contained in a region. This is one that I've written (including my own "wrappers" for region and marker):
-(BOOL)isMarker:(SGMarker*)m inVisibleRegion:(SGRegion*)region
{
CLLocationCoordinate2D upperLeftPosition = region.topLeft;
CLLocationCoordinate2D lowerRightPosition = region.bottomRight;
if (m.position.latitude > lowerRightPosition.latitude && m.position.latitude < upperLeftPosition.latitude &&
m.position.longitude < lowerRightPosition.longitude && m.position.longitude > upperLeftPosition.longitude) {
return YES;
}
return NO;
}
// In my region wrapper, this is how I make sure I have the north-east/south-west points
+(SGRegion*)regionWithGMSVisibleRegion:(GMSVisibleRegion)region
{
SGRegion* mapRegion = [[self alloc] init];
// Since the camera can rotate, first we need to find the upper left and lower right positions of the
// visible region, which may not correspond to the farLeft and nearRight points in GMSVisibleRegion.
double latitudes[] = {region.farLeft.latitude, region.farRight.latitude, region.nearLeft.latitude};
double longitudes[] = {region.nearRight.longitude, region.nearLeft.longitude, region.farLeft.longitude};
double highestLatitude = latitudes[0], lowestLatitude = latitudes[0];
double highestLongitude = longitudes[0], lowestLongitude = longitudes[0];
for (int i = 1; i < 3; i++) {
if (latitudes[i] >= highestLatitude)
highestLatitude = latitudes[i];
if (latitudes[i] < lowestLatitude)
lowestLatitude = latitudes[i];
if (longitudes[i] >= highestLongitude)
highestLongitude = longitudes[i];
if (longitudes[i] < lowestLongitude)
lowestLongitude = longitudes[i];
}
mapRegion.topLeft = CLLocationCoordinate2DMake(highestLatitude, lowestLongitude);
mapRegion.bottomRight = CLLocationCoordinate2DMake(lowestLatitude, highestLongitude);
return mapRegion;
}
So if you use these methods instead, you should be able to absolutely tell where your issue is coming from (ie. not from here ;) ).
As you seen in the image, there are numbers of polygon on the top of the mapView. Each polygon overlays on the top of other polygon. This causes opacity problem and that misleads user to interpret colors by referring to colormap.
Before placing any polygons, first I want to remove/clear the new polygon area then add the polygon.
I hope my question clear! if not, please let me know. Appreciated in advance.
I have also add portion of my code below as a reference! Polygon data comes from server in JSON format and I get coordinates out of this data and add them as a polygon for each time stamp.
for(bb = 0; bb < [polygonArray count]; bb++){
coords = malloc(sizeof(CLLocationCoordinate2D) * [[polygonArray objectAtIndex:bb] count]);
for (int a = 0;a < [[polygonArray objectAtIndex:bb] count]; a++){
coords[a].latitude = [[[[polygonArray objectAtIndex:bb]objectAtIndex:a]objectAtIndex:0]doubleValue];
coords[a].longitude = [[[[polygonArray objectAtIndex:bb]objectAtIndex:a]objectAtIndex:1]doubleValue];
}
polygon = [[MKPolygon alloc]init];
polygon = [MKPolygon polygonWithCoordinates:coords count:[[polygonArray objectAtIndex:bb]count]];
[previousPolygons addObject:polygon];
[mapView addOverlay:polygon];
}
}
Hmm. I'm a little unclear on what you want to do. If you simply want to remove a polygon, you'd have to some how find the polygon you want remove and run
[mapView removeOverlay:polygon]
If you want to remove all polygons then you could run
[mapView removeOverlays:mapView.overlays]
I've been looking at Apple's iOS Class Reference documentation, and am unfortunately none the wiser. I have downloaded their sample code KMLViewer but they've overcomplicated it... All I really want to know is how to generate a path and add it to the MKMapView. The documentation talks of using a CGPathRef, but doesn't really explain how.
Here's how to generate a path and add it as an overlay to an MKMapView. I'm going to use an MKPolylineView, which is a subclass of MKOverlayPathView and shields you from having to refer to any CGPath since you instead create an MKPolyline (containing the data of the path) and use that to create the MKPolylineView (the visual representation of the data on the map).
The MKPolyline has to be created with a C array of points (MKMapPoint), or a C array of coordinates (CLLocationCoordinate2D). It's a shame that MapKit doesn't use more advanced data structures such as NSArray, but so be it! I'm going to assume that you have an NSArray or NSMutableArray of CLLocation objects to demonstrate how to convert to a C array of data suitable for the MKPolyline. This array is called locations and how you fill it would be determined by your app - e.g. filled in by processing touch locations by the user, or filled with data downloaded from a web service etc.
In the view controller that is in charge of the MKMapView:
int numPoints = [locations count];
if (numPoints > 1)
{
CLLocationCoordinate2D* coords = malloc(numPoints * sizeof(CLLocationCoordinate2D));
for (int i = 0; i < numPoints; i++)
{
CLLocation* current = [locations objectAtIndex:i];
coords[i] = current.coordinate;
}
self.polyline = [MKPolyline polylineWithCoordinates:coords count:numPoints];
free(coords);
[mapView addOverlay:self.polyline];
[mapView setNeedsDisplay];
}
Note that self.polyline is declared in the .h as:
#property (nonatomic, retain) MKPolyline* polyline;
This view controller should also implement the MKMapViewDelegate method:
- (MKOverlayView*)mapView:(MKMapView*)theMapView viewForOverlay:(id <MKOverlay>)overlay
{
MKPolylineView* lineView = [[[MKPolylineView alloc] initWithPolyline:self.polyline] autorelease];
lineView.fillColor = [UIColor whiteColor];
lineView.strokeColor = [UIColor whiteColor];
lineView.lineWidth = 4;
return lineView;
}
You can play with the fillColor, strokeColor and lineWidth properties to ensure that they are appropriate for your app. I've just gone with a simple, moderately wide plain white line here.
If you want to remove the path from the map, e.g. to update it with some new coordinates, then you would do:
[mapView removeOverlay:self.polyline];
self.polyline = nil;
and then repeat the above process to create a new MKPolyline and add it to the map.
Although on first glance MapKit can look a bit scary and complex, it can be easy to do some things as illustrated in this example. The only scary bit - for non-C programmers at least - is the use of malloc to create a buffer, copy the CLLocationCoordinates into it using array syntax, and then freeing the memory buffer afterwards.