Search code examples
flutteropenstreetmapfluttermap

Rotating an ImageOverlay specified with longitude/latitude corners in Open Street Maps in Flutter


I have an image placed using flutter_map in Flutter, which is positioned using NW/SE corner longitude/latitudes. I need to rotate this image around its centre a specified number of degrees - I do this in Google Maps by simply rotating the image div using CSS, which works fine for our purposes. Flutter lets me rotate the OverlayImageLayer, but not individual overlayImages.

As I understand it flutter_map uses a third lng/lat to specify the lower left (SW) bounding box corner to control rotation, and possibly also needs new co-ordinates for the other two points.

In short I need to be able to specify an initial bounding box which is unrotated, and then recalculate the corner positions once rotated a specified number of degrees.


Solution

  • I found a solution, credit to this answer - each corner point should be rotated around a central point, this gives transformed LatLngs providing the overlay does not overlap the poles or span the international date line.

      LatLng rotateLatLng(LatLng coord, LatLng centre, double degRotation) {
        // Make this constant so it doesn't have to be repeatedly recalculated
        const piDiv180 = maths.pi / 180;
    
        // Convert the input angle to radians
        final r = (0-degRotation) * piDiv180;
    
        // Create local variables using appropriate nomenclature
        final x = coord.longitude;
        final y = coord.latitude;
        final mx = centre.longitude;
        final my = centre.latitude;
    
        // Offset input point by the midpoint so the midpoint becomes the origin
        final ox = x - mx;
        final oy = y - my;
    
        // Cache trig results because trig is expensive
        final cosr = maths.cos(r);
        final sinr = maths.sin(r);
    
        // Perform rotation
        final dx = ox * cosr - oy * sinr;
        final dy = ox * sinr + oy * cosr;
    
        // Undo the offset
        return LatLng(dy + my, dx + mx);
      }