Javascript 分割过大路径时,Google地图提升服务响应不准确

Javascript 分割过大路径时,Google地图提升服务响应不准确,javascript,google-maps-api-3,batch-processing,map-directions,google-elevation-api,Javascript,Google Maps Api 3,Batch Processing,Map Directions,Google Elevation Api,这是一个有点细节的问题,所以让我先解释一下情况,然后是我的实现,最后是一个问题,以便您能最好地理解 从4月4日起,将添加一个更新,并将问题缩小为一个未决问题,有关最新信息,请参阅此问题的底部。 TLDR 我有一个很长的路线从谷歌地图方向API返回,并希望该路线的海拔图。太糟糕了,它不能工作,因为它是通过GET请求的,URL最大长度是2.048个字符,超过了。我把请求分开;使用承诺保证正确的加工顺序;但是,整条路线的高程数据并不总是完整的,也不总是以正确的顺序显示,也不总是遵循给定的路径,有时高程

这是一个有点细节的问题,所以让我先解释一下情况,然后是我的实现,最后是一个问题,以便您能最好地理解

从4月4日起,将添加一个更新,并将问题缩小为一个未决问题,有关最新信息,请参阅此问题的底部。

TLDR

我有一个很长的路线从谷歌地图方向API返回,并希望该路线的海拔图。太糟糕了,它不能工作,因为它是通过GET请求的,URL最大长度是2.048个字符,超过了。我把请求分开;使用承诺保证正确的加工顺序;但是,整条路线的高程数据并不总是完整的,也不总是以正确的顺序显示,也不总是遵循给定的路径,有时高程间的位置跨度超过几公里

介绍

尝试为Google Maps DirectionsService响应创建高程图时,我遇到了一个路线太长的问题(这似乎与距离无关,而与每个概览路径的LATLNG数无关)。这是由于通过
GET
请求ElevationService,URL的最大长度为2048个字符。这个问题很严重

实施

我想我会比谷歌更聪明(不是真的,但至少尝试找到一种解决方法),将DirectionService(
overview\u path
属性)返回的路径拆分成批并连接结果(
ElevationService方法
getElevationsAlongPath
返回的高程

  • 为了获得最佳的详细程度,我使用512查询了ElevationService 每批样品
  • 因为升降服务将样品分散在整个长度上 在路径中,我设置了每个批次的最大
    LatLng
    ,并进行检查 处理完整路径(
    totalBatches)需要多少批
    =概述_path.length/maxBatchSize
  • 最终,我的方向分布均匀,这是一次尝试 获取完整路线的同等详细程度(
    batchSize=
    Math.ceil(概述\u path.length/totalBatches)
当ElevationService异步工作时,我确保在其他SO用户的帮助下,所有请求都以正确的顺序处理,因此首先使用setTimout,现在使用Promissions

我的代码

var maxBatchSize = 200;
var currentBatch = 0;
var promise = Promise.resolve();
var totalElevationBatches = Math.ceil(directions.routes[0].overview_path.length / maxBatchSize);
var batchSize =  Math.ceil(directions.routes[0].overview_path.length / totalElevationBatches);

while(currentBatch < totalElevationBatches) {
    promise = addToChain(promise, currentBatch, batchSize);
    currentBatch++;
}

promise.then(function() {
    drawRouteElevationChart(); // this uses the routeElevations to draw an AreaChart
});

function getRouteElevationChartDataBatchPromise(batch, batchSize) {
    return new Promise(function(resolve, reject) {
        var elevator = new google.maps.ElevationService();
        var thisBatchPath = [];

        for (var j = batch * batchSize; j < batch * batchSize + batchSize; j++) {
            if (j < directions.routes[0].overview_path.length) {
                thisBatchPath.push(directions.routes[0].overview_path[j]);
            } else {
                break;
            }
        }

        elevator.getElevationAlongPath({
            path: thisBatchPath,
            samples: 512
        }, function (elevations, status) {
            if (status != google.maps.ElevationStatus.OK) {
                if(status == google.maps.ElevationStatus.OVER_QUERY_LIMIT) {
                    console.log('Over query limit, retrying in 250ms');

                    resolve(setTimeout(function() {
                        getRouteElevationChartDataBatchPromise(batch, batchSize);

                    }, 250));
                } else {
                    reject(status);
                }
            } else {
                routeElevations = routeElevations.concat(elevations);
                resolve();
            }
        });
    });
}

function addToChain(chain, batch, batchSize){
    return chain.then(function(){
        console.log('Promise add to chain for batch: ' + batch);
        return getRouteElevationChartDataBatchPromise(batch, batchSize);
    });
}

在实施部分提出的关注、旁注和列举的问题都包含在本手册中。完整的文档提供了一个简单的界面来查询地球上的高程数据位置,并将解决您遇到的所有问题,如高程请求、参数使用、指定位置、路径和高程响应

对于您在介绍中讨论的问题,Google Maps Elevation API有标准和高级使用限制。执行这些限制是为了防止滥用谷歌地图提升API。提供有关使用限制和增加配额选项的详细信息

文档中的其他注释可能会解决您的问题:

  • 请注意,传递多个点时,高程数据会变得更粗糙。要获取点的最精确高程值,应单独查询该点
  • 如果谷歌在您请求的精确位置没有精确的高程测量,该服务将使用四个最近的位置插值并返回平均值
  • 与位置请求一样,path参数指定一组纬度和经度值。但是,与位置请求不同,路径指定一组有序的顶点。路径请求不是在顶点返回高程数据,而是沿路径长度进行采样,每个采样彼此之间的距离相等
  • Google Maps Elevation API为单点查询返回尽可能高精度的数据。涉及多个位置的批量查询可能返回精度较低的数据

  • 嗯,你要处理多少点。你能发布路径吗,这样也许其他人可以在他们自己的应用程序中测试它。 您是否尝试使用Douglas Peuker或类似方法减少路径点。 您是否尝试过其他应用程序,如免费的“Routeconverter”(与HGT一起使用),以查看是否获得更好的效果。您是否需要直接/动态的高程点?是否可以选择使用其他免费提升服务。也许您必须将高程点读回路线点,以便可以整理出不需要的点

    恐怕只有一些思考,用蹩脚的英语。
    祝你好运,莱因哈德

    在这个问题的帮助下,剩下的最后一个问题也得到了解决:。因此,如果回答这个问题,我可以将赏金奖励给他,因为这是最终帮助我摆脱困境的诀窍

    为了确保函数在状态
    OK
    时解析
    超过查询限制时重试
    任何其他状态下拒绝
    我必须将承诺逻辑放入函数中并调用该函数,如下所示:

    function getRouteElevationChartDataBatchPromise(batch, batchSize) {
        return new Promise(function(resolve, reject) {
            function run(batch, batchSize) {
                var elevator = new google.maps.ElevationService();
                var thisBatchPath = [];
    
                for (var j = batch * batchSize; j < batch * batchSize + batchSize; j++) {
                    if (j < directions.routes[0].overview_path.length) {
                        thisBatchPath.push(directions.routes[0].overview_path[j]);
                    } else {
                        break;
                    }
                }
    
                elevator.getElevationAlongPath({
                    path: thisBatchPath,
                    samples: 512
                }, function (elevations, status) {
                    if(status == google.maps.ElevationStatus.OK) {
                        routeElevations = routeElevations.concat(elevations);
                        resolve();
                    } else if (status == google.maps.ElevationStatus.OVER_QUERY_LIMIT) {                        
                        setTimeout(function () {
                            run(batch, batchSize);
                        }, 200);
                    } else {
                        reject(status);
                    }
                });
            }
    
            run(batch, batchSize);
        });
    }
    
    函数getRouteElevationChartDataBatchPromise(批处理,批处理大小){
    返回新承诺(功能(解决、拒绝){
    函数运行(批处理、批处理大小){
    var电梯=新的google.maps.ElevationService();
    var thisBatchPath=[];
    对于(变量j=批次*batchSize;jfunction getRouteElevationChartDataBatchPromise(batch, batchSize) {
        return new Promise(function(resolve, reject) {
            function run(batch, batchSize) {
                var elevator = new google.maps.ElevationService();
                var thisBatchPath = [];
    
                for (var j = batch * batchSize; j < batch * batchSize + batchSize; j++) {
                    if (j < directions.routes[0].overview_path.length) {
                        thisBatchPath.push(directions.routes[0].overview_path[j]);
                    } else {
                        break;
                    }
                }
    
                elevator.getElevationAlongPath({
                    path: thisBatchPath,
                    samples: 512
                }, function (elevations, status) {
                    if(status == google.maps.ElevationStatus.OK) {
                        routeElevations = routeElevations.concat(elevations);
                        resolve();
                    } else if (status == google.maps.ElevationStatus.OVER_QUERY_LIMIT) {                        
                        setTimeout(function () {
                            run(batch, batchSize);
                        }, 200);
                    } else {
                        reject(status);
                    }
                });
            }
    
            run(batch, batchSize);
        });
    }