静态地图:绘制多点的多边形。 (2048字符限制) [英] Static Maps: Drawing polygons with many points. (2048 char limitation)

查看:119
本文介绍了静态地图:绘制多点的多边形。 (2048字符限制)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于获取请求中有2048个字符的限制,因此您无法使用Google静态地图生成包含多边形点数多边形的图片。



特别是如果您尝试在一张地图上绘制许多复杂的多边形。
如果您使用Google Maps API,您将没有任何问题 - 它运作良好!
但是我想要一张图片(jpg或png)...

那么,有没有机会从Google Maps API创建图片?或者任何可以欺骗2048字符限制的方法?



谢谢!

解决方案

没有办法欺骗字符限制,但可以简化折线以使编码的折线字符串低于字符限制。这可能会或可能不会导致适合您的需求的多边形。

另外一个警告是(据我所知)静态地图API只允许在地图上绘制单个编码多段线(如果您自己关闭或填充它,它看起来像多边形,但它仍然是多段线,而不是多边形)。

简化折线的一个选项是 Douglas Peucker 算法。以下是使用简化方法扩展 google.maps.Polyline 对象的实现。



这需要加载Google Maps JS API,如果您使用静态地图,则可能不需要,但下面的代码可以轻松地重新编写。

  google.maps.Polyline.prototype.simplify =函数(容差){

var points = this.getPath()。的getArray(); //一个google.maps.LatLng对象数组
var keep = []; //简化的点数组

//检查是否有一些可以简化的内容。
if(points.length< = 2){
return points;


函数distanceToSegment(p,v,w){

函数distanceSquared(v,w){
return Math.pow((vx - wx),2)+ Math.pow((vy - wy),2)
}
函数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); (t> 1)return distanceSquared(p,w);
if(t> 1)
return distanceSquared(p,{x:v.x + t *(w.x-v.x),y:v.y + t *(w.y - v.y)});

$ b $ // Lat / Lng to x / y
函数ll2xy(p){
return {x:p.lat(),y:p。 LNG()};
}

return Math.sqrt(distanceToSegmentSquared(ll2xy(p),ll2xy(v),ll2xy(w)));
}

函数dp(points,tolerance){

//如果段太小,只保留第一个点。
//我们将最后一点推到最后。
if(points.length< = 2){
return [points [0]];


var keep = [],//一个点的数组
v = points [0],//定义段的起始点
w = points [points.length-1],//定义段的终点
maxDistance = 0,//最远点的距离
maxIndex = 0; //所述点的索引

//循环遍历每个中间点以找出距离线段
的点最大距离(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;



//检查最大距离是否大于我们的公差允许
if(maxDistance> = tolerance){

//在前半部分点上递归调用dp()
keep = keep.concat(dp(points.slice(0,maxIndex + 1),tolerance));

//然后在下半部分
keep = keep.concat(dp(points.slice(maxIndex,points.length),tolerance));

} else {
//放弃中间点,保留第一个
keep = [points [0]];
}
返回保留;
};

//将最后一点推到
keep = dp(points,tolerance);
keep.push(points [points.length-1]);
返回保留;

};

通过几个例子(这里 here)。



现在,您可以取出原始多段线并通过此功能提供,得到的编码折线低于URL长度限制(这将取决于您传递给静态地图的其他参数)。



类似这样的应用程序应该可以工作: p>

  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;
}


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;
}

这篇关于静态地图:绘制多点的多边形。 (2048字符限制)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆