草庐IT

javascript - 拆分过大的路径时,Google Maps Elevation Service 响应不准确

coder 2024-07-20 原文

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

截至 4 月 4 日,添加了更新并将问题缩小到一个待处理的问题,有关最新信息,请参阅此问题的底部。

TLDR;

我有一条从 Google Maps Directions API 返回的长路线,并且想要该路线的高程图。太糟糕了,它不起作用,因为它是通过 GET 请求的,并且 URL 最大长度为 2.048 个字符,超出了。我拆分了请求;使用 Promises 保证正确的处理顺序;但海拔数据并不总是完整的完整路线,并不总是以正确的顺序显示,并不总是遵循给定的路径,有时高程间的位置跨越几公里。

介绍;

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

执行;

我想我会比谷歌更聪明(不是真的,但至少试图找到一种方法来解决它),将 DirectionsService 返回的路径( overview_path 属性)分成批次并连接结果( elevations由 ElevationService 方法返回 getElevationsAlongPath)。

  • 为了获得最好的详细信息,我使用 512 查询 ElevationService
    每批 sample ;
  • 并且因为 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 个或更少航点的问题。

    问题;

    我面临的问题是:
  • 海拔数据并不总是遵循完整的路线路径,这意味着图表中的最后一个海拔点距离路线终点(远);
  • 海拔数据有时会以随机顺序显示,就好像 Promise 尚未等待下一个任务执行一样;
  • 高程数据并不总是遵循给定的 LatLng来自overview_path在给定的批次中提供(见截图);
  • 高程间距离数据很多。有时跨越数公里,同时要求 512 个样本以均匀匹配的批次大小,最大值为 200 LatLng每批次 s。



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

    非常感谢帮助

    我也想放一个 250 代表。就在这个问题上悬赏,但目前这是不可能的。因此,请随时回复,因为我稍后可以添加赏金并将其奖励给解决所描述问题的答案。一个 250 代表。已授予赏金,以表达我对您为我指明正确方向的感谢。

    感谢阅读和回复!

    4 月 4 日更新,留下 1 个待处理问题(据我目前所知)

    随机顺序的高程问题已解决

    当我注意到方向结果中的不一致行为时,我已经能够解决一些问题。这是由一个明显的原因造成的:异步调用没有“ promise ”被安排,所以有些时候顺序是正确的,大多数时候不是。起初我没有注意到这一点,因为标记显示正确(缓存)。

    高程间距问题已解决

    显示高程数据的 div 只有 300 像素宽,并且包含许多数据点。由于如此小的宽度,我根本无法悬停在足够多的点上,导致触发彼此相距更远的高程点。

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

    不知何故,我也解决了这个问题,但我不确定更大的宽度或“有希望”的方向顺序是否解决了这个问题。

    未决问题:高程数据并不总是完整的

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

    当返回 Over Query Limit 错误时,如何重新触发相同的链?我已经尝试不再解析相同的函数,而只是触发 setTimeout(...) ,但是当 Promise 不再获得 Over Query Limit 时,它似乎没有解决重新触发的批处理。目前这是我设置它的方式(对于两个方向和海拔):
    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();
                }
            });
        });
    }
    

    最佳答案

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

    只有一些想法,英语不好 - 我很害怕。
    祝你好运,莱因哈德

    关于javascript - 拆分过大的路径时,Google Maps Elevation Service 响应不准确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36266442/

    有关javascript - 拆分过大的路径时,Google Maps Elevation Service 响应不准确的更多相关文章

    1. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

      我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

    2. ruby-on-rails - 每次我尝试部署时,我都会得到 - (gcloud.preview.app.deploy) 错误响应 : [4] DEADLINE_EXCEEDED - 2

      我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie

    3. ruby-on-rails - Rails - 使用/自定义 URL : '/dashboard' 指定根路径 - 2

      如何使此根路径转到:“/dashboard”而不仅仅是http://example.com?root:to=>'dashboard#index',:constraints=>lambda{|req|!req.session[:user_id].blank?} 最佳答案 您可以通过以下方式实现:root:to=>redirect('/dashboard')match'/dashboard',:to=>"dashboard#index",:constraints=>lambda{|req|!req.session[:user_id].b

    4. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

      在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

    5. ruby - 如何根据长度将路径数组转换为嵌套数组或散列 - 2

      我需要根据字符串路径的长度将字符串路径数组转换为符号、哈希和数组的数组给定以下数组:array=["info","services","about/company","about/history/part1","about/history/part2"]我想生成以下输出,对不同级别进行分组,根据级别的结构混合使用符号和对象。产生以下输出:[:info,:services,about:[:company,history:[:part1,:part2]]]#altsyntax[:info,:services,{:about=>[:company,{:history=>[:part1,:pa

    6. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

      我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

    7. ruby-on-rails - 如何播种图像的路径? - 2

      Organization和Image具有一对一的关系。Image有一个名为filename的列,它存储文件的路径。我在Assets管道中包含这样一个文件:app/assets/other/image.jpg。播种时如何包含此文件的路径?我已经在我的种子文件中尝试过:@organization=...@organization.image.create!(filename:File.open('app/assets/other/image.jpg'))#Ialsotried:#@organization.image.create!(filename:'app/assets/other/i

    8. ruby - 拆分字符串并分配给不同的变量 - 2

      我从ui中得到日期范围为-approved_between"=>"2013-03-17-2013-03-18"我需要拆分此approved_start_date="2013-03-17"和approved_end_date="2013-03-18"...我希望使用它在mysql中查询,因为mysql中的日期格式是created_at:2012-07-2810:35:01.我正在做的是:approved=approved_between.split("")approved_start_date=approved[0]approved_end_date=approved[2]很确定这不是处

    9. ruby-on-rails - Ruby on Rails 将列表拆分或切片为列 - 2

      @locations=Location.all#currentlistingall@locations=Location.slice(5)orLocation.split(5)使用Ruby,我试图将我的列表分成4列,每列限制为5个;然而,切片或拆分似乎都不起作用。知道我可能做错了什么吗?任何帮助是极大的赞赏。 最佳答案 您可能想使用in_groups_of:http://railscasts.com/episodes/28-in-groups-of这是RyanBates在railscast中的示例用法:

    10. ruby - 在 Mechanize 中使用 JavaScript 单击链接 - 2

      我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan

    随机推荐