1

I'm trying to add an image to a Google Map using the Google Maps Android API v2:

mMap = googleMap;
LatLng sw = new LatLng(47.01377857060625, 8.305519705172628);
LatLng ne = new LatLng(47.01395211967171, 8.306270482717082);
LatLng nw = new LatLng(47.014014755501165, 8.305559697328135);
LatLng se = new LatLng(47.01370751919609, 8.306236284552142);
LatLngBounds latLngBounds = new LatLngBounds(sw, ne).including(nw).including(se);
GroundOverlayOptions groundOverlayOptions = new GroundOverlayOptions();
BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromAsset("t2c.png");
groundOverlayOptions.image(bitmapDescriptor);
groundOverlayOptions.positionFromBounds(latLngBounds);
mMap.addGroundOverlay(groundOverlayOptions);

Unfortunately, the LatLng values are not 100% accurate, so the background image doesn't rotate but is skewed according to Google:

If the bounds do not match the original aspect ratio, the image will be skewed.

Using only LatLng sw and ne:

https://developers.google.com/maps/documentation/android-api/groundoverlay#use_latlngbounds_to_position_an_image

With two LatLng

I don't know how I should be able to figure out the exact LatLng of south-west and north-east, so I'm interested in a way to define a polygon and squeeze the image somehow into it with the four LatLng as anchors. Using four LatLng currently looks like this. Using LatLng sw, ne, nw and se:

With four LatLng

user3105453
  • 1,881
  • 5
  • 32
  • 55

2 Answers2

0

you will never achieve what you want using LatLngBounds because you are trying to rotate your GroundOverlay.

What you need to do is to use bearing (rotation) and width/height of the ground overlay. Let's say your building in -20 degrees rotated and has width-height of 40-20 (only you know these values. 1- Get the LatLng of the center of the building, which is finding the center of the four coordinates in your code above. That value will be your "centerLocation"

GroundOverlayOptions groundOverlayOptions = new GroundOverlayOptions();
BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromAsset("t2c.png");
groundOverlayOptions.image(bitmapDescriptor);
groundOverlayOptions.position(centerLocation,widthInMeters,heightInMeters);
groundOverlayOptions.bearing(rotated);//the value is clockwise and rotation is about anchor point (which should be by default 0.5,0.5 of your image
mMap.addGroundOverlay(groundOverlayOptions);

This should work, obviously you have to calculate values or go step by step trying different values.

Hope it helps

N Dorigatti
  • 3,482
  • 2
  • 22
  • 33
  • It helps, thanks. Do you possibly know if there is a possibility to reference points on the image without needing GPS LongLat? Let's say I'd like to draw something on top of my image at pixel-coordinates x=35/y=54. but as the image already got rotated (`bearing`) I'm not sure how to reference those points anymore. – user3105453 Apr 22 '16 at 07:22
  • yes, you have to do relative-absolute transformation. Usually you should pick a pair of point (top-left, bottom-right) in both the coordinate systems and find the formula, but is quite complex to explain in a comment, you should open a new question – N Dorigatti Apr 22 '16 at 07:39
0

The first answer is what will works for u. I will just write my solution in detail so it could be easy to just copy paste code and get it done...

First Step if u have four bounds, get center of them for which u can use the below the function

 private LatLng computeCentroid(List<LatLng> points) {
        double latitude = 0;
        double longitude = 0;
        int n = points.size();

        for (LatLng point : points) {
            latitude += point.latitude;
            longitude += point.longitude;
        }

        return new LatLng(latitude/n, longitude/n);
    }

Second get the width and height in meters. Here are method to get distance between two points in meters.



private double distance(double lat1, double lon1, double lat2, double lon2) {
        double theta = lon1 - lon2;
        double dist = Math.sin(deg2rad(lat1))
                * Math.sin(deg2rad(lat2))
                + Math.cos(deg2rad(lat1))
                * Math.cos(deg2rad(lat2))
                * Math.cos(deg2rad(theta));
        dist = Math.acos(dist);
        dist = rad2deg(dist);
        dist = dist * 60 * 1.1515;
        return dist * 1609.34;
    }

    private double deg2rad(double deg) {
        return (deg * Math.PI / 180.0);
    }

    private double rad2deg(double rad) {
        return (rad * 180.0 / Math.PI);
    }

Last just use these values and done

double height=distance(selectedFloorPlan.getGeoData().get(0).getLat(), selectedFloorPlan.getGeoData().get(0).getLng(),selectedFloorPlan.getGeoData().get(1).getLat(), selectedFloorPlan.getGeoData().get(1).getLng());


    double width=distance(selectedFloorPlan.getGeoData().get(0).getLat(), selectedFloorPlan.getGeoData().get(0).getLng(),selectedFloorPlan.getGeoData().get(3).getLat(), selectedFloorPlan.getGeoData().get(3).getLng());

GroundOverlayOptions newarkMap = new GroundOverlayOptions()
                .image(images.get(0))
                .position(centerPoint,(float)width,(float)height)
                .bearing(-67.18571490414709f);

        imageOverlay = map.addGroundOverlay(newarkMap);