MKMapPoint with MKMapPointMake from MKMapRect

前提是你 提交于 2019-12-04 19:43:53

The overall idea is correct but there are two problems:

  1. Code assumes that the visibleMapRect's bounds are from 0,0 which they are usually not. The visibleMapRect.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 minimum x (instead of setting the ending x to 90).

    So instead of MKMapRectGetMaxX(mRect)/2, it should be (MKMapRectGetMinX(mRect) + MKMapRectGetMaxX(mRect))/2 or even simpler MKMapRectGetMidX(mRect).

    Same applies to the y position.

  2. 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).

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!