3
votes

I have an iOS app where I want to read a KML-file containing GroundOverlays. A GroundOverlay contains an image-href, north, south, east, west coordinates, as well as a a rotation.

I have followed this tutorial (http://www.raywenderlich.com/30001/overlay-images-and-overlay-views-with-mapkit-tutorial) for displaying the images on the map. I can successfully parse the KML and display non-rotated images correctly. The problem is, I have no idea of how to display rotated images.

To rotate myself I need to know two things: firstly, how do I rotate the image in my drawing code. This question is just about rotating in iOS. Secondly, I need to know how the KML-coordinates are affected by a rotation. Are the north, south, east and west coordinates the coordinates of the rotated or the non-rotated image?

I have searched extensively for examples on how to do this, but found nothing useful. A link to some tutorial/code that does this would be great!

The relevant parts of the KML looks like this:

<GroundOverlay>
  <Icon>
    <href>http://developers.google.com/kml/documentation/images/etna.jpg</href>
  </Icon>
  <LatLonBox>
    <north>37.91904192681665</north>
    <south>37.46543388598137</south>
    <east>15.35832653742206</east>
    <west>14.60128369746704</west>
    <rotation>-0.1556640799496235</rotation>
  </LatLonBox>
</GroundOverlay>

My drawing code (where I guess the rotation should take place):

- (void)drawMapRect:(MKMapRect)mapRect
          zoomScale:(MKZoomScale)zoomScale
          inContext:(CGContextRef)context {

    CGImageRef imageReference = self.overlayImage.CGImage;

    // TODO: rotate image by self.rotation degrees around center.
    MKMapRect theMapRect = self.overlay.boundingMapRect;
    CGRect theRect = [self rectForMapRect:theMapRect];

    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextTranslateCTM(context, 0.0, -theRect.size.height);
    CGContextDrawImage(context, theRect, imageReference);
}
1

1 Answers

2
votes

This is how I ended up solving it. Firstly, the KML-coordinates are the coordinates of the un-rotated image, so there is nothing really that needs to be done to make them work with a rotation. Here is the completed drawMapRect:zoomScale:inContext

- (void)drawMapRect:(MKMapRect)mapRect
          zoomScale:(MKZoomScale)zoomScale
          inContext:(CGContextRef)context {

    CGImageRef imageReference = self.overlayImage.CGImage;

    MKMapRect theMapRect = self.overlay.boundingMapRect;
    CGRect theRect = [self rectForMapRect:theMapRect];

    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextTranslateCTM(context, 0.0, -theRect.size.height);
    // Translate to center of image. This is done to rotate around the center, 
    // rather than the edge of the picture
    CGContextTranslateCTM(context, theRect.size.width / 2, theRect.size.height / 2);

    // _rotation is the angle from the kml-file, converted to radians.
    CGContextRotateCTM(context, _rotation);

    // Translate back after the rotation.
    CGContextTranslateCTM(context, -theRect.size.width / 2, -theRect.size.height / 2);

    CGContextDrawImage(context, theRect, imageReference);
}

It was quite a while since I wrote this code and I don't really remember more details than this, but since someone just upvoted the question, I thought I'd at least post the code where I solved it. Hope it helps! :)