Google maps api 3 有没有一种方法可以通过谷歌地图API查找路线内的城市?

Google maps api 3 有没有一种方法可以通过谷歌地图API查找路线内的城市?,google-maps-api-3,Google Maps Api 3,有没有办法获得由directionservice.route()追踪的路线经过的城市 例如,在年路线中,属于圣保罗(起点)、安安古拉、卡贾马尔、朱迪亚(其他…)和坎皮纳斯(终点)城市的道路 如果我们在DirectionsService.route()方法中输入起点和终点,我们将获得legs的列表,其中包括道路、里程和旅行时间,但不包括它们所属的城市 有没有一种方法可以在不调用其他API的情况下获取此数据?在考虑Maps API时,成本是一个重要问题 编辑:阐明解决方案不应涉及额外的调用。解决方案

有没有办法获得由
directionservice.route()
追踪的路线经过的城市

例如,在年路线中,属于圣保罗(起点)、安安古拉、卡贾马尔、朱迪亚(其他…)和坎皮纳斯(终点)城市的道路

如果我们在
DirectionsService.route()
方法中输入起点和终点,我们将获得
leg
s的列表,其中包括道路、里程和旅行时间,但不包括它们所属的城市

有没有一种方法可以在不调用其他API的情况下获取此数据?在考虑Maps API时,成本是一个重要问题


编辑:阐明解决方案不应涉及额外的调用。解决方案并不比为路线的每一段调用PlacesService好多少,因为它只是对路线的一部分进行装箱,并无论如何调用它们。

我的建议是放弃一切都使用Google API的方法。毫无疑问,它是最好的导航工具,正因为如此,它才那么昂贵。因此,我建议使用其他一些非谷歌的地理编码方法,特别是如果你只寻找大城市(如你的例子所示)。有一些“免费”的API已经存在(事实上,它们通常从来都不是真正免费的)——我只建议你在没有服务器的情况下这样做。在这种情况下,我会选择Namingm——它没有限制上限(有点像,请参阅operations.osmfoundation.org/policies/Namingm——您可以对它进行垃圾邮件处理,但不鼓励使用),没有API密钥,而且完全免费——当然,唯一的问题是,正如您所提到的,您必须通过每一点向API发出请求,这需要很多时间。但是,我会:

let zoom = 12; // Adjust to your needs: see nominatim.org/release-docs/develop/api/Reverse. Higher numbers will result in more places being matched, while lower numbers will result in faster execution.

let coords = [];

const stepList = [];

Array.from(googleResponse.routes[0].legs).forEach(leg => {
  stepList.push(...leg.steps);
});

stepList.forEach(e => {
  coords.push([e.endLocation.lat, e.endLocation.long]);
});

coords.push([legList[0].startLocation.lat, legList[0].startLocation.long]);

let arr = [];
let promises = [];
let bboxes = [];

const loopOn = (i, cb) => {
  const coord = coords[i];
  const nextLoop = () => {
    i+1 < coords.length? loopOn(i+1, cb) : cb();
  }

  let makeRequest = true;
  for (let bbox of bboxes) {
    if (coord[0] >= bbox[0] 
        && coord[0] <= bbox[1] 
        && coord[1] >= bbox[2] 
        && coord[1] <= bbox[3]){ // If it is within a bounding box we've already seen
          makeRequest = false; // there's no need to geocode it, since we already roughly know it's in an area we have already saved.
          break;
        }
  }

  if (makeRequest){
    var request = $.ajax({
      url: `https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${coord[0]}&lon=${coord[1]}&zoom=${zoom}`,
      type:'GET',
      dataType: 'jsonp',
      success: resp => {
        thisPlace = resp.address.city || resp.address.town || resp.address.village;
        thisPlace && arr.indexOf(thisPlace) === -1 && arr.push(thisPlace);
        bboxes.push(resp.boundingbox);
        nextLoop();
      }
    });
  } else {
    nextLoop();
  }
};

loopOn(0, () => {
  /*The rest of your code*/
});
此外,您还可以删除边界框代码,因为您不再需要节省请求时间

然而,像这样重新安排会更快:

let resp = [];

fs.createReadStream(<your file here.csv>)
  .pipe(csv())
  .on('data', (data) => resp.push(data))
  .on('end', () => {
    let coords = [];

    const stepList = [];

    Array.from(googleResponse.routes[0].legs).forEach(leg => {
      stepList.push(...leg.steps);
    });

    stepList.forEach(e => {
      coords.push([e.endLocation.lat, e.endLocation.lng]);
    });

    coords.push([legList[0].startLocation.lat, legList[0].startLocation.lng]);

    let arr = [];
    let promises = [];
    let bboxes = [];

    coords.forEach(coord => {
      let results = search(coords);

      let thisPlace = results.address.city || results.address.town || results.address.village;
      thisPlace && arr.indexOf(thisPlace) === -1 && arr.push(thisPlace);
    };

    /*The rest of your code*/
});
let resp=[];
fs.createReadStream()
.pipe(csv())
.on('data',(data)=>resp.push(data))
.on('end',()=>{
设coords=[];
常量stepList=[];
Array.from(googleResponse.routes[0].legs.forEach(leg=>{
步骤列表。推(…腿。步骤);
});
stepList.forEach(e=>{
协调推进([e.endLocation.lat,e.endLocation.lng]);
});
coords.push([legList[0].startLocation.lat,legList[0].startLocation.lng]);
设arr=[];
让承诺=[];
设bboxes=[];
coords.forEach(coord=>{
让结果=搜索(coords);
让thisPlace=results.address.city | | results.address.town | | results.address.village;
thisPlace&&arr.indexOf(thisPlace)==-1&&arr.push(thisPlace);
};
/*代码的其余部分*/
});
接下来我们需要的是实际的
搜索
功能,这是一个复杂的部分。我们需要找到一些快速但基本正确的功能。实际的实现取决于文件的格式,但下面是我要做的一个快速概述:

  • 创建两个重复的
    resp
    ,但按经度排序一个(我们将此数组称为
    a_o
    ),按纬度排序另一个(
    a_a
    )。在定义这些数组时,请确保不使用
    var
    let
    const
    。只需…定义它们
  • 对于每一个,移除距离
    a_o
    中经轴上的点25公里(半径)以外的任何东西,并且相同,但具有
    a_a
  • 删除两个阵列以清除它们在RAM中占用的空间
  • 找到两个数组中的任何项目,并将其放入名为
    a\u c
  • 过滤彼此距离在3-4km范围内的任何项目(但请确保保留其中一个点,而不是同时删除两个点!)
  • 检查每个项目,并计算出到该点的绝对距离(使用算法-记住,地球是一个球体,基本毕达哥拉斯定理将起作用
  • 如果您发现任何距离小于20公里的物品,并且附有城市、村庄或城镇,请打断并返回名称
  • 如果完成,即永不中断,则返回
    undefined
除此之外,您可以使用任何CSV,其中包含:

  • 城市名称
  • 中纬度
  • 中经度

我希望这会有所帮助。总之,如果你一小时只做5-6条简单路线,那么就采用第一种经过尝试和测试的预制方法。如果你有数百万个航路点,下载数据,然后花半个小时左右的时间制作你自己的地理编码系统。这很值得提高性能。

你可以对eac进行反向地理编码h步骤(或您感兴趣的点)并从地理编码器响应中提取信息。这将是非常高的成本(和计算)昂贵,因为每个谷歌api的请求都是付费的。是的,我知道。此外,地理编码器的费率是有限的。但正如你所说的,这些信息不是方向响应的一部分,所以…你还想做什么?我想知道是否有其他参数可以使用,或者可以调用其他服务。可能是重复的谢谢我肯定会选择第二个选项,因为请求的数量接近gajilions.:)@EricWu如果还不算太晚,请看:我注意到第二个代码示例中的一个错误,我不必要地使用了递归。这样做只是为了在对API进行请求时生成一个更紧凑的版本,但如果您只是推到一个数组,则不必这样做。此外,如果您确实发出了那么多请求,则会导致
Ma最大堆栈调用大小超过了错误
——然而,我合理地假设,任何人只要有足够少的请求来证明使用API的合理性,就不会出现递归问题。一点也不晚:)。是的,递归不是问题。
let resp = [];

fs.createReadStream(<your file here.csv>)
  .pipe(csv())
  .on('data', (data) => resp.push(data))
  .on('end', () => {
    let coords = [];

    const stepList = [];

    Array.from(googleResponse.routes[0].legs).forEach(leg => {
      stepList.push(...leg.steps);
    });

    stepList.forEach(e => {
      coords.push([e.endLocation.lat, e.endLocation.lng]);
    });

    coords.push([legList[0].startLocation.lat, legList[0].startLocation.lng]);

    let arr = [];
    let promises = [];
    let bboxes = [];

    coords.forEach(coord => {
      let results = search(coords);

      let thisPlace = results.address.city || results.address.town || results.address.village;
      thisPlace && arr.indexOf(thisPlace) === -1 && arr.push(thisPlace);
    };

    /*The rest of your code*/
});