title: How can I rotate and translate/scale an overlay so it matches the map rect?
body: <p>I have an app where users can add an image to a map. This is pretty straightforward. It becomes much more difficult when I want to add rotation (taken from the current map heading). The code I use to create an image is pretty straightforward:</p>
  <pre><code>let imageAspectRatio = Double(image.size.height / image.size.width)
  let mapAspectRatio = Double(visibleMapRect.size.height / visibleMapRect.size.width)
  
  var mapRect = visibleMapRect
  
  if mapAspectRatio &gt; imageAspectRatio {
      // Aspect ratio of map is bigger than aspect ratio of image (map is higher than the image), take away height from the rectangle
      let heightChange = mapRect.size.height - mapRect.size.width * imageAspectRatio
      mapRect.size.height = mapRect.size.width * imageAspectRatio
      mapRect.origin.y += heightChange / 2
  } else {
      // Aspect ratio of map is smaller than aspect ratio of image (map is higher than the image), take away width from the rectangle
      let widthChange = mapRect.size.width - mapRect.size.height / imageAspectRatio
      mapRect.size.width = mapRect.size.height / imageAspectRatio
      mapRect.origin.x += widthChange / 2
  }
  
  photos.append(ImageOverlay(image: image, boundingMapRect: mapRect, rotation: cameraHeading))
  </code></pre>
  <p>The ImageOverlay class inherits from MKOverlay, which I can easily draw on the map. Here's the code for that class:</p>
  <pre><code>class ImageOverlay: NSObject, MKOverlay {
      let image: UIImage
      let boundingMapRect: MKMapRect
      let coordinate: CLLocationCoordinate2D
      let rotation: CLLocationDirection
      
      init(image: UIImage, boundingMapRect: MKMapRect, rotation: CLLocationDirection) {
          self.image = UIImage.fixedOrientation(for: image) ?? image
          self.boundingMapRect = boundingMapRect
          self.coordinate = CLLocationCoordinate2D(latitude: boundingMapRect.midX, longitude: boundingMapRect.midY)
          self.rotation = rotation
      }
  }
  </code></pre>
  <p>I have figured out by how much I need to scale and translate the context to fit on the correct location on the map (from which it was added). I can't figure out how to rotate the context to make the image render in the correct location.</p>
  <p>I figured out that the map rotation was in degrees, and the rotate method takes radians (took longer than I dare to admit), but the image moves around when I apply the rotation.</p>
  <p>I use the following code to render the overlay:</p>
  <pre><code>override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
      guard let overlay = overlay as? ImageOverlay else {
          return
      }
      
      let rect = self.rect(for: overlay.boundingMapRect)
      
      context.scaleBy(x: 1.0, y: -1.0)
      context.translateBy(x: 0.0, y: -rect.size.height)
      context.rotate(by: CGFloat(overlay.rotation * Double.pi / 180))
      context.draw(overlay.image.cgImage!, in: rect)
  }
  </code></pre>
  <p>How do I need to rotate this context to get the image to be aligned properly?</p>
  <p>This is an open source project with the code <a href="https://github.com/vrwim/Walkr" rel="nofollow noreferrer">here</a></p>
  <p>Edit: I have tried (and failed) to use some kind of trig function. If I scale by a factor of <code>3 * sin(rotation) / 4</code> (no clue where the 3/4 comes from), I get a correct scale for some rotations, but not for others.</p>