问题
I have the following code:
MKMapRect mRect = self.mapView.visibleMapRect;
MKMapPoint eastMapPoint = MKMapPointMake(MKMapRectGetMaxX(mRect), MKMapRectGetMaxY(mRect)/2);
MKMapPoint northMapPoint = MKMapPointMake(MKMapRectGetMaxX(mRect)/2, 0);
MKMapPoint southMapPoint = MKMapPointMake(MKMapRectGetMaxX(mRect)/2, MKMapRectGetMaxY(mRect));
MKMapPoint westMapPoint = MKMapPointMake(0, MKMapRectGetMaxY(mRect)/2);
I am converting these to CLLocationCoordinate2D
with MKCoordinateForMapPoint
. For example:
CLLocationCoordinate2D northCoords = MKCoordinateForMapPoint(northMapPoint);
Along with northCoords
, I have centerCoords
which is the coordinates of the point in the center in the map. With these two set of coordinates, I create an array CLLocationCoordinate2D coordinates[2]
to which I add these two sets...
Following, I use the following code to draw a line between the two coordinates:
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:coordinates count:2];
[_mapView addOverlay:polyLine];
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor redColor];
polylineView.lineWidth = 5.0;
return polylineView;
}
The Problem:
The polyline overlay starting point (center of the map) is correct always starting at the center. However the other end of the line (north/south/east/west) does not point correctly to where it should be. In the image below I am drawing all four lines respective to the 4 MKMapPoint above.

回答1:
The overall idea is correct but there are two problems:
Code assumes that the
visibleMapRect
's bounds are from 0,0 which they are usually not. ThevisibleMapRect.origin
property has the starting offset. This has to be taken into account when calculating the midpoint.With the current code, if the bounds are say from 80 to 100,
MKMapRectGetMaxX(mRect)/2
returns 50 but the visible map rect is from 80 to 100 so the line ends somewhere before the minimumx
(instead of setting the endingx
to 90).So instead of
MKMapRectGetMaxX(mRect)/2
, it should be(MKMapRectGetMinX(mRect) + MKMapRectGetMaxX(mRect))/2
or even simplerMKMapRectGetMidX(mRect)
.Same applies to the
y
position.Code assumes that the user location will be at the center of the map. If this is guaranteed, then you can use the midpoint as above. However, this is an unnecessary restriction. You can easily adjust the code so it works even if the user location is not in the center:
//first convert userLocation to map points... MKMapPoint userLocationMapPoint = MKMapPointForCoordinate(mapView.userLocation.coordinate); MKMapPoint eastMapPoint = MKMapPointMake(MKMapRectGetMaxX(mRect), userLocationMapPoint.y); MKMapPoint northMapPoint = MKMapPointMake(userLocationMapPoint.x, MKMapRectGetMinY(mRect)); MKMapPoint southMapPoint = MKMapPointMake(userLocationMapPoint.x, MKMapRectGetMaxY(mRect)); MKMapPoint westMapPoint = MKMapPointMake(MKMapRectGetMinX(mRect), userLocationMapPoint.y);
The above should work for the 0 (N), 90 (E), 180 (S), and 270 (W) positions but this can be generalized for any angle using some trigonometry:
//radiusMapPoints will be the length of the line (max of width or height).
double radiusMapPoints = MAX(mRect.size.width, mRect.size.height);
//thetaRadians is the heading of the line in radians.
//Example below is for 45.0 degrees.
double thetaRadians = 45.0 * (M_PI/180.0);
//endMapPoint is end of line starting from user location.
MKMapPoint endMapPoint;
endMapPoint.x = userLocationMapPoint.x + (radiusMapPoints * sin(thetaRadians));
endMapPoint.y = userLocationMapPoint.y - (radiusMapPoints * cos(thetaRadians));
CLLocationCoordinate2D lineCoords[2];
lineCoords[0] = mapView.userLocation.coordinate;
lineCoords[1] = MKCoordinateForMapPoint(endMapPoint);
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:lineCoords count:2];
//can also use polylineWithPoints and pass MKMapPoints instead
[mapView addOverlay:polyLine];
Also note that for iOS 7, you should implement the rendererForOverlay
delegate method instead of viewForOverlay
and return an MKPolylineRenderer
instead of an MKPolylineView
. Although iOS 7 currently still works if you only implement viewForOverlay
it is technically deprecated. You can have both delegate methods so that the app works in any iOS version (iOS 6 will use viewForOverlay
and iOS 7 will use rendererForOverlay
it it's there).
来源:https://stackoverflow.com/questions/19968477/mkmappoint-with-mkmappointmake-from-mkmaprect