How to determine the correct height for MKMapCamera, focusing on MKPolygon

I need to figure out how to set up MKMapSnapshotterOptions to take aerial photographs / satellite images associated with a polygonal region of the earth.

Filling out the "region", "scale", "size" and "mapType" properties is trivial, since I have MKPolygon to work with. The tricky part is setting up the “camera” - in my particular case, I use MKMapSnapshotter regardless of MKMapView (actually, not even in the main thread).

However, I would prefer to orient the image so that it matches the borders of the polygon based on a nonzero caption, i.e. the area I draw has a “start” and a “start”, end ", which I would like to orient from bottom to top in the resulting image. Since the polygon will in principle never be naturally oriented towards the 0 degree course, I will need to define" centerCoordinate "," title "and" height ".

Since I have the coordinates of the polygon, I can easily get the center coordinate and the desired title. The first coordinate of the polygon correlates with the "beginning" of the shape and the end (or another coordinate in my case) correlates with the "end".

Figuring out the height is more complicated; I want to make sure the polygon area ends with filling in the aspect ratio of the snapshot I want to display. How to calculate the correct height for use with MKMapCamera without relying on the MKMapView 'setRegion' selector?

+4
source share
1 answer

To solve this problem, I decided to do the following:

1) MKPolygon , / : MKPolygon "boundingMapRect" , . , - -, . .

2), , , : , "" - .

3) [ ]. : , , , , / . , , .

4)

5), () , A = , B = C = ( )

, , 1 . MKMapView , MKMapCamera 30 - , , . , .

5) , , , (/2)/tan (aperture_angle_in_radians/2)

, , / StackOverflow , : 1) - 2) - , ,

!

OH, , , :

+ (double)determineAltitudeForPolygon:(MKPolygon *)polygon withHeading:(double)heading andWithViewport:(CGSize)viewport {
    // Get a bounding rectangle that encompasses the polygon and represents its
    // true aspect ratio based on the understanding of its heading.
    MKMapRect boundingRect = [[self rotatePolygon:polygon withCenter:MKMapPointForCoordinate(polygon.coordinate) byHeading:heading] boundingMapRect];

    MKCoordinateRegion boundingRectRegion = MKCoordinateRegionForMapRect(boundingRect);

    // Calculate a new bounding rectangle that is corrected for the aspect ratio
    // of the viewport/camera -- this will be needed to ensure the resulting
    // altitude actually fits the polygon in view for the observer.
    CLLocationCoordinate2D upperLeftCoord = CLLocationCoordinate2DMake(boundingRectRegion.center.latitude + boundingRectRegion.span.latitudeDelta / 2, boundingRectRegion.center.longitude - boundingRectRegion.span.longitudeDelta / 2);
    CLLocationCoordinate2D upperRightCoord = CLLocationCoordinate2DMake(boundingRectRegion.center.latitude + boundingRectRegion.span.latitudeDelta / 2, boundingRectRegion.center.longitude + boundingRectRegion.span.longitudeDelta / 2);
    CLLocationCoordinate2D lowerLeftCoord = CLLocationCoordinate2DMake(boundingRectRegion.center.latitude - boundingRectRegion.span.latitudeDelta / 2, boundingRectRegion.center.longitude - boundingRectRegion.span.longitudeDelta / 2);

    CLLocationDistance hDist = MKMetersBetweenMapPoints(MKMapPointForCoordinate(upperLeftCoord), MKMapPointForCoordinate(upperRightCoord));
    CLLocationDistance vDist = MKMetersBetweenMapPoints(MKMapPointForCoordinate(upperLeftCoord), MKMapPointForCoordinate(lowerLeftCoord));

    double adjacent;
    double newHDist, newVDist;

    if (boundingRect.size.height > boundingRect.size.width) {
        newVDist = vDist;
        newHDist = (viewport.width / viewport.height) * vDist;

        adjacent = vDist / 2;
    } else {
        newVDist = (viewport.height / viewport.width) * hDist;
        newHDist = hDist;

        adjacent = hDist / 2;
    }

    double result = adjacent / tan(Deg_to_Rad(15));
    return result;
}

+ (MKPolygon *)rotatePolygon:(MKPolygon *)polygon withCenter:(MKMapPoint)centerPoint byHeading:(double)heading {
    MKMapPoint points[polygon.pointCount];
    double rotation_angle = -Deg_to_Rad(heading);

    for(int i = 0; i < polygon.pointCount; i++) {
        MKMapPoint point = polygon.points[i];

        // Translate each point by the coordinate to rotate around, use matrix
        // algebra to perform the rotation, then translate back into the
        // original coordinate space.
        double newX = ((point.x - centerPoint.x) * cos(rotation_angle)) + ((centerPoint.y - point.y) * sin(rotation_angle)) + centerPoint.x;
        double newY = ((point.x - centerPoint.x) * sin(rotation_angle)) - ((centerPoint.y - point.y) * cos(rotation_angle)) + centerPoint.y;

        point.x = newX;
        point.y = newY;

        points[i] = point;
    }

    return [MKPolygon polygonWithPoints:points count:polygon.pointCount];
}
+17

All Articles