Because there is a limitation to 2048 characters in the get request, you are not able to generate an image with Google Static Maps which contains a polygon with a great number of polygon points.
Especially if you try to draw many complex polygons on one map. If you use Google Maps API, you will have no problem - it works very well! But I want to have an image (jpg or png)...
So, is there any opportunity to create an image from the Google Maps API? Or any way to 'trick' the 2048 char limitation?
Thanks!
There's no way to 'trick' the character limit, but it is possible to simplify your polyline to bring the encoded polyline string below the character limit. This may or may not result in a polygon of suitable fidelity for your needs.
One additional caveat is that (to the best of my knowledge) the Static Maps API only allows a single encoded polyline to be drawn on the map (this can look like a polygon, if you either close it yourself or fill it, but it's still a polyline, not a polygon).
One option for simplifying your polyline is the Douglas Peucker algorithm. Below is an implementation which extends the google.maps.Polyline
object with a simplify
method.
This relies on having the Google Maps JS API loaded, which you may not want if you're using Static Maps, but the code below could easily be re-written.
google.maps.Polyline.prototype.simplify = function(tolerance) {
var points = this.getPath().getArray(); // An array of google.maps.LatLng objects
var keep = []; // The simplified array of points
// Check there is something to simplify.
if (points.length <= 2) {
return points;
}
function distanceToSegment(p, v, w) {
function distanceSquared(v, w) {
return Math.pow((v.x - w.x),2) + Math.pow((v.y - w.y),2)
}
function distanceToSegmentSquared(p, v, w) {
var l2 = distanceSquared(v, w);
if (l2 === 0) return distanceSquared(p, v);
var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
if (t < 0) return distanceSquared(p, v);
if (t > 1) return distanceSquared(p, w);
return distanceSquared(p, { x: v.x + t * (w.x - v.x), y: v.y + t * (w.y - v.y) });
}
// Lat/Lng to x/y
function ll2xy(p){
return {x:p.lat(),y:p.lng()};
}
return Math.sqrt(distanceToSegmentSquared(ll2xy(p), ll2xy(v), ll2xy(w)));
}
function dp( points, tolerance ) {
// If the segment is too small, just keep the first point.
// We push the final point on at the very end.
if ( points.length <= 2 ) {
return [points[0]];
}
var keep = [], // An array of points to keep
v = points[0], // Starting point that defines a segment
w = points[points.length-1], // Ending point that defines a segment
maxDistance = 0, // Distance of farthest point
maxIndex = 0; // Index of said point
// Loop over every intermediate point to find point greatest distance from segment
for ( var i = 1, ii = points.length - 2; i <= ii; i++ ) {
var distance = distanceToSegment(points[i], points[0], points[points.length-1]);
if( distance > maxDistance ) {
maxDistance = distance;
maxIndex = i;
}
}
// check if the max distance is greater than our tollerance allows
if ( maxDistance >= tolerance ) {
// Recursivly call dp() on first half of points
keep = keep.concat( dp( points.slice( 0, maxIndex + 1 ), tolerance ) );
// Then on second half
keep = keep.concat( dp( points.slice( maxIndex, points.length ), tolerance ) );
} else {
// Discarding intermediate point, keep the first
keep = [points[0]];
}
return keep;
};
// Push the final point on
keep = dp(points, tolerance);
keep.push(points[points.length-1]);
return keep;
};
This has been cobbled together with the help of a couple of examples (here and here).
You can now take your original polyline and feed it through this function with increasing tolerance until the resulting encoded polyline falls below the URL length limit (which will depend on the other parameters you're passing to Static Maps).
Something like this should work:
var line = new google.maps.Polyline({path: path});
var encoded = google.maps.geometry.encoding.encodePath(line.getPath());
var tol = 0.0001;
while (encoded.length > 1800) {
path = line.simplify(tol);
line = new google.maps.Polyline({path: path});
encoded = google.maps.geometry.encoding.encodePath(path);
tol += .005;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With