拆分过大的路径

时间:2016-03-28 16:26:29

标签: javascript google-maps-api-3 batch-processing map-directions google-elevation-api

这是一个有一定程度细节的问题,所以让我首先解释一下情况,然后是我的实施并提出问题以便你最了解。

自4月4日起,我们会添加更新,问题范围缩小为一个待处理问题,请参阅此问题的底部以获取最新信息。 < / p>

TLDR;

我有一条很长的路线从谷歌地图方向API返回,并希望该路线的高程图表。太糟糕了,它不起作用,因为它是通过GET请求的,并且URL最大长度是超过2.048个字符。我分开了请求;使用Promises保证正确的处理顺序;但是,对于完整路线,Evelation数据并不总是完整的,并不总是以正确的顺序显示,并不总是遵循给定的路径,并且有时会间隔高度超过几公里。

简介

尝试为Google Maps DirectionsService回复创建高程图我遇到了路线太长的问题(这似乎与距离无关,而不是每个overview_path的LatLng数量)。这是因为通过GET请求ElevationService,并且URL的最大长度为2048个字符。这个问题是described on SO here as well

实施;

我认为我会比Google聪明(不是真的,但至少试图找到解决方法),将DirectionsService(overview_path属性)返回的路径分成批并连接结果(ElevationService方法elevations返回的getElevationsAlongPath)。

  • 为了获得最佳细节,我使用512查询ElevationService 每批样品;
  • 并且因为ElevationService在整个长度上传播样本 路径我每批设置最大LatLng并检查 处理完整路径需要多少批次(totalBatches = overview_path.length / maxBatchSize);
  • 最后为我的指示得到均匀的传播结果 获得完整路线的相同详细程度(batchSize = Math.ceil(overview_path.length / totalBatches))。

当ElevationService异步工作时,我确保在其他SO用户的帮助下,首先使用setTimout并使用Promises,以正确的顺序处理所有请求。

我的代码

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

旁注;

我还批准了DirectionService的请求,以解决该服务所具有的8个航点限制,但我可以确认这不是问题,因为我也面临着8个或更少航点的问题

问题;

我面临的问题是:

  • 高程数据并不总是遵循路径的完整路径,这意味着图表中的最后一个高程点(远离)路径末端;
  • 高程数据有时会以随机顺序显示,好像承诺似乎还没有等待下一个任务执行;
  • 海拔数据不会始终遵循给定的LatLng来自 在给定批次中提供overview_path(参见屏幕截图);
  • 海拔高度距离数据很多。有时跨越多公里,同时请求512个样本以获得均匀匹配的批量大小,每批最多200 LatLng秒。

elevation data not following the overview_path it was told to follow

我认为使用Promise对ElevationService进行批处理(在使用setTimtout计时之前)将解决我的所有问题,但我解决的唯一问题是不超过2.048字符请求URL并面临上述新问题。

非常感谢帮助

另外我想说250个代表。对此问题的赏金,但此时此刻不可能。所以请随时回复,因为我可以稍后添加赏金并将其奖励给解决所述问题的答案。 250代表。赏金已被授予我感谢你指出我正确的方向。

感谢阅读和回复!

4月4日更新,留下1个未决问题(据我现在所知)

随机顺序升级问题已解决

当我注意到路线结果中的不一致行为时,我已经能够解决一些问题。这是由于一个显而易见的原因引起的:异步调用不是“承诺”#34;因此,有时候订单是正确的,大部分时间都没有。我一开始并没有注意到这一点,因为标记显示正确(缓存)。

降低了海拔高度距离的问题

显示高程数据的div只有300像素宽,包含许多数据点。通过如此小的宽度,我根本无法悬停在足够的点上,从而触发彼此远离的高程点。

高程数据未沿路线显示的问题

不知怎的某个地方我也解决了这个问题,但我不确定是否有更大的宽度或者#34;有希望&#34;方向指令解决了这个问题。

待定问题:高程数据并非总是完整

唯一剩下的问题是高程数据并不总是涵盖整个路径。我相信这是因为Promising逻辑中的一个错误,因为在控制台中记录一些消息告诉我高程图是在并非所有Promise-then已经完成的时刻绘制的,我认为这是由重新启动批处理引起的当Google Maps API返回Over Query Limit错误时调用。

如果返回Over Query Limit错误,如何重新连接相同的链?我已经尝试过不再解决相同的功能了,只是触发了setTimeout(...),但是Promise似乎无法在不再获得Over Query的情况下解析已批准的批处理限制。目前,这就是我设置它的方式(包括方向和高程):

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('ElevationService: Over Query Limit, retrying in 200ms');

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

                    }, 200));
                } else {
                    reject(status);
                }
            } else {
                console.log('Elevations Count: ' + elevations.length);
                routeElevations = routeElevations.concat(elevations);
                resolve();
            }
        });
    });
}

3 个答案:

答案 0 :(得分:0)

Google Maps Elevation API中涵盖了实施部分,附注和所列问题中提出的问题。完整的文档提供了一个简单的界面,用于查询地球上的高程数据位置,并解决所有遇到的问题,如高程请求,参数用法,指定位置,路径和高程响应。

对于您在简介中讨论的问题,Google Maps Elevation API具有标准和高级使用限制。强制执行这些限制是为了防止滥用Google Maps Elevation API。 Google Maps Elevation API Usage Limits为您提供有关使用限制的详细信息以及增加配额的选项。

文档中可能解决您问题的其他说明:

  
      
  1. 请注意,当传递多个点时,高程数据会变得更粗糙。要获得某个点的最准确高程值,应单独查询。
  2.   
  3. 如果Google在您请求的确切位置没有精确的高程测量值,服务将使用最近的四个位置进行插值并返回平均值。
  4.   
  5. 与位置请求一样,path参数指定一组纬度和经度值。但是,与位置请求不同,路径指定有序的顶点集。路径请求不是在顶点返回高程数据,而是沿着路径的长度进行采样,每个样本彼此等距。
  6.   
  7. Google Maps Elevation API会返回尽可能高精度的单点查询数据。涉及多个位置的批处理查询可能会以较低的准确度返回数据。
  8.   

答案 1 :(得分:0)

Mmmh, how many points do you have to handle. Can you publish the path, so maybe some other can test it in their own apps. Did you try to reduce the path points with Douglas-Peuker or comparable methods. Did you try other apps like the free "Routeconverter" (which works with HGT) to see if you get better results. Do you need the elevation points direct/on the fly? Would using other free elevation services be an option. Perhaps you have to read the elevation points back to your route points, so that you can sort out unwanted points.

Only some thinking, in bad English - I'm afraid. Good luck, Reinhard

答案 2 :(得分:0)

在SO问题的帮助下,最后一个问题也得到了解决:How to re-run a javascript promise when failed?。因此,如果jfriend00回复此问题,我可以将赏金奖励给他,因为这是最终帮助我的伎俩。

确保功能解析状态为OVER_QUERY_LIMIT重试位于any other status拒绝位于{{我必须将Promise逻辑放在一个函数中并调用该函数,如下所示:

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);
    });
}
相关问题