Question

I noticed that when you draw a polyline in google maps you set it's width in pixels (strokewidth). Is there a way I could set that in metres instead?

Was it helpful?

Solution

Unfortunately, I don't know any easy way to do this. The API does not appear to have documentation on this and I assume this feature is unsupported.

One problem is that the pixels represent a different number of meters at different zoom levels within the API. So it would be a dynamic quantity if the zoom levels are changed.

One option might be to compute the width in pixels for representing a given number of meters for a given zoom level. For that, you would have to write your own function based on the scales of the map at each zoom level. That data appear to be available here:

http://webhelp.esri.com/arcgisserver/9.3/java/index.htm#designing_overlay_gm_mve.htm

20 : 1128.497220
19 : 2256.994440
18 : 4513.988880
17 : 9027.977761
16 : 18055.955520
15 : 36111.911040
14 : 72223.822090
13 : 144447.644200
12 : 288895.288400
11 : 577790.576700
10 : 1155581.153000
9  : 2311162.307000
8  : 4622324.614000
7  : 9244649.227000
6  : 18489298.450000
5  : 36978596.910000
4  : 73957193.820000
3  : 147914387.600000
2  : 295828775.300000
1  : 591657550.500000

you can then set the pixel value dynamically depending on the meters you are trying to represent and the current zoom level.

There may still be a problem because the pixel sizes you generate, may not correspond to the screen pixel sizes, depending on how the API deals with screen DPI and resolution

OTHER TIPS

Based on this answer, I could get an acceptable result. Even if it is not the best solution.

In my case I used Android with com.google.android.gms:play-services-location:8.4.0. But the original answer is in JavaScript, so I think it is not difficult to adapt.

LatLng center = <get map center>.
float requiredWidth = 10; // in meters
Projection proj = googleMap.getProjection();
Point pointCenter = proj.toScreenLocation(center); // point in pixels
LatLng neighbor = proj.fromScreenLocation(new Point(pointCenter.x + 1000, pointCenter.y));
float[] distance = new float[1]; 
Location.distanceBetween(center.latitude, center.longitude, neighbor.latitude, neighbor.longitude, distance); // return distance in meters
float pixelsWidth = requiredWidth / (distance[0] / 1000f); // 10 meters conveted to pixels
myPolyline.setWidth(pixelsWidth);

The difference between my answer and the original is that I create the neighbor with 1000 pixels distance, to get a higher sampling rate and increase precision.

This approach also considers the zoom automatically.

It is not the accurate solution

You can use Scale control of the Leaflet. Basically you get the value of the scale and compute how many meters fit in one pixel.

Scale control

/**
 * Returns number of meters in one pixel.
 *
 * @return Integer number of meters in one pixel
 */
var _metersInPixel = function () {
    var pixels = $('.leaflet-control-scale-line').width();
    var distance = $('.leaflet-control-scale-line').first().text();

    var testRegExpKm = /(\d+)\skm/;
    var testRegExpM = /(\d+)\sm/;
    if (testRegExpKm.test(distance)) {
        var match = testRegExpKm.exec(distance);
        var meters = parseInt(match[1]) * 1000;
    } else if (testRegExpM.test(distance)) {
        var match = testRegExpM.exec(distance);
        var meters = parseInt(match[1]);
    } else {
        throw "Unable to determine meters to pixels ratio";
    }

    var metersInPixels = Math.round(meters / parseInt(pixels));
    return metersInPixels;
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top