I'm trying to draw a Great Circle line between two lat/lon points on an MKMapView. This is a line that would appear rounded (a 'straight' line on a globe) and is best visualized here. In fact this very odd WordPress site seems to begin to describe exactly how to do this, but it ends abruptly after the first few steps.
Reading in Apple's documentation I see
In iOS 4.0 and later, you can also use projected map coordinates instead of regions to specify some values. When you project the curved surface of the globe onto a flat surface, you get a two-dimensional version of a map where longitude lines appear to be parallel. Locations and distances on this map are specified using the MKMapPoint, MKMapSize, and MKMapRect data types. You can use these data types to specify the map’s visible region and when specifying the location of overlays.
How I would apply this to a Great Circle overlay I'm not sure. Can anyone help?
I've implemented this for drawing a great circle route for aircraft going between two airports using MKPolyline.
+ (void)createGreatCircleMKPolylineFromPoint:(CLLocationCoordinate2D)point1
toPoint:(CLLocationCoordinate2D)point2
forMapView:(MKMapView*)mapView
{
double lat1 = point1.latitude;
double lon1 = point1.longitude;
double lat2 = point2.latitude;
double lon2 = point2.longitude;
lat1 = lat1 * (PI/180);
lon1 = lon1 * (PI/180);
lat2 = lat2 * (PI/180);
lon2 = lon2 * (PI/180);
double d = 2 * asin( sqrt(pow(( sin( (lat1-lat2)/2) ), 2) + cos(lat1) * cos(lat2) * pow(( sin( (lon1-lon2)/2) ), 2)));
int numsegs = 100;
CLLocationCoordinate2D *coords = malloc(sizeof(CLLocationCoordinate2D) * numsegs);
double f = 0.0;
for(int i=1; i<=numsegs; i++)
{
f += 1.0 / (float)numsegs;
double A=sin((1-f)*d)/sin(d);
double B=sin(f*d)/sin(d);
double x = A*cos(lat1) * cos(lon1) + B * cos(lat2) * cos(lon2);
double y = A*cos(lat1) * sin(lon1) + B * cos(lat2) * sin(lon2);
double z = A*sin(lat1) + B*sin(lat2);
double latr=atan2(z, sqrt(pow(x, 2) + pow(y, 2) ));
double lonr=atan2(y, x);
double lat = latr * (180/PI);
double lon = lonr * (180/PI);
// NSLog(@"lat: %f lon: %f", lat, lon);
CLLocationCoordinate2D loc = CLLocationCoordinate2DMake(lat, lon);
coords[i - 1] = loc;
}
//check for circling west to east. If the plane is crossing 180, we need
//to draw two lines or else the polyline connects the dots and draws a straight
//line all the way across the map.
CLLocationCoordinate2D prevCoord;
BOOL twoLines = NO;
int numsegs2 = 0;
CLLocationCoordinate2D *coords2;
for(int i=0; i<numsegs; i++)
{
CLLocationCoordinate2D coord = coords[i];
if(prevCoord.longitude < -170 && prevCoord.longitude > -180 && prevCoord.longitude < 0
&& coord.longitude > 170 && coord.longitude < 180 && coord.longitude > 0)
{
twoLines = YES;
coords2 = malloc(sizeof(CLLocationCoordinate2D) * (numsegs - i));
numsegs2 = numsegs - i;
for(int j=0; j<numsegs2; j++)
{
coords2[j] = coords[i + j];
}
break;
}
prevCoord = coord;
}
//remove any previously added overlays
[mapView removeOverlays:mapView.overlays];
if(twoLines)
{
MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:numsegs - numsegs2];
free(coords);
[mapView addOverlay:polyline];
MKPolyline *polyline2 = [MKPolyline polylineWithCoordinates:coords2 count:numsegs2];
free(coords2);
[mapView addOverlay:polyline2];
}
else
{
MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:numsegs];
free(coords);
[mapView addOverlay:polyline];
}
}
You've now created the overlay(s), now you just need to provide an MKOverlayView in mapView:viewForOverlay.
- (MKOverlayView*)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
MKPolyline *polyline = (MKPolyline*)overlay;
MKPolylineView *view = [[[MKPolylineView alloc] initWithPolyline:polyline] autorelease];
//choose your line params here
view.lineWidth = 2;
view.fillColor = [UIColor blueColor];
return view;
}
Hope this helps.
Screenshot http://s1-03.twitpicproxy.com/photos/large/489178500.png
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With