Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Google maps 谷歌地图API-查找最近的位置_Google Maps_Google Maps Api 3 - Fatal编程技术网

Google maps 谷歌地图API-查找最近的位置

Google maps 谷歌地图API-查找最近的位置,google-maps,google-maps-api-3,Google Maps,Google Maps Api 3,我有一份全美大约250个办公地点的电子表格。我想有一个网页,用户将输入他们的家庭地址和五个最近的办公室(姓名,城市,电话号码等)将列在左侧和地图画布上映射的点。你知道我如何使用谷歌地图API实现这个场景吗 我已经知道了如何使用GeoJSON将数据加载到地图中,但我还没有学会如何根据行驶距离或时间显示最近的五个站点。我确实找到了Distance Matrix服务,但每个请求只能有25个目的地,所以这不起作用 其他人建议的哈弗森方法在这种情况下不起作用,因为我需要根据驾驶距离或更有效的驾驶时间进行计

我有一份全美大约250个办公地点的电子表格。我想有一个网页,用户将输入他们的家庭地址和五个最近的办公室(姓名,城市,电话号码等)将列在左侧和地图画布上映射的点。你知道我如何使用谷歌地图API实现这个场景吗

我已经知道了如何使用GeoJSON将数据加载到地图中,但我还没有学会如何根据行驶距离或时间显示最近的五个站点。我确实找到了Distance Matrix服务,但每个请求只能有25个目的地,所以这不起作用


其他人建议的哈弗森方法在这种情况下不起作用,因为我需要根据驾驶距离或更有效的驾驶时间进行计算。此外,在这种情况下,我没有访问PHP的权限,但我们可以使用JavaScript。

使用haversine方法将点数减少到可以通过距离矩阵运行的数值,然后使用距离矩阵生成最后5个点

代码片段:

var-geocoder=null;
var-map=null;
var customerMarker=null;
var gmarkers=[];
var最近值=[];
函数初始化(){
//警报(“初始”);
geocoder=新的google.maps.geocoder();
map=new google.maps.map(document.getElementById('map'){
缩放:9,
中心:新google.maps.LatLng(52.6699927,-0.7274620),
mapTypeId:google.maps.mapTypeId.ROADMAP
});
var infowindow=new google.maps.infowindow();
var标记,i;
var bounds=new google.maps.LatLngBounds();
document.getElementById('info').innerHTML=“found”+locations.length+“locations
”; 对于(i=0;i”+locations[i][2] }); G标记器。推(标记器); google.maps.event.addListener(标记,'click',(函数(标记,i){ 返回函数(){ setContent(marker.html); 信息窗口。打开(地图、标记); } }) (marker,i)); } 映射边界(bounds); } 函数代码地址(){ var numberOfResults=25; var numberOfDrivingResults=5; var address=document.getElementById('address')。值; 地理编码({ “地址”:地址 },功能(结果、状态){ if(status==google.maps.GeocoderStatus.OK){ map.setCenter(结果[0].geometry.location); if(customerMarker)customerMarker.setMap(null); customerMarker=new google.maps.Marker({ 地图:地图, 位置:结果[0]。几何体。位置 }); 最近=findClosestN(结果[0].geometry.location,numberOfResults); //获得驾驶距离 最近=最近。拼接(0,numberOfResults); CalculatedInstances(结果[0]。geometry.location,最近,numberOfDrivingResults); }否则{ 警报('地理编码因以下原因未成功:'+状态); } }); } 函数findClosestN(pt,numberOfResults){ var最近值=[]; document.getElementById('info').innerHTML+=“正在处理”+gmarkers.length+“
”; 对于(变量i=0;i”; gmarkers[i].setMap(空); 最近的推送(gmarkers[i]); } 最近的。排序(排序列表); 返回最近的位置; } 功能排序列表(a、b){ 返回(a.距离-b.距离) } 函数计算实例(pt、最近、numberOfResults){ var service=new google.maps.DistanceMatrixService(); var请求={ 来源:[pt], 目的地:[], travelMode:google.maps.travelMode.DRIVING, unitSystem:google.maps.unitSystem.METRIC, 避免:错误, 避免收费:错误 }; 对于(变量i=0;i”+结果[i]。地址+“
”+结果[i]。距离.text+'近似地'+结果[i]。持续时间.text+'

'; } } }); } 函数sortByDistDM(a,b){ 返回值(a.distance.value-b.distance.value) } google.maps.event.addDomListener(窗口“加载”,初始化); //门店名称[0],配送[1],地址[2],配送区[3],坐标[4]来自FusionTables比萨饼店的数据示例 变量位置=[ [“约翰比萨饼”,“不”,“加利福尼亚州帕洛阿尔托大学大道400号”,“122.121277,37.386799,0-122.158012,37.4168,0-122.158012,37.448151,0-122.142906,37.456055,0-122.118874,37.45224,0-122.107544,37.437793,0-122.102737,37.426,0-122.113037,37.414618,0-122.121277,37.386790,12,12
async function calculateDistances(data, origin) {

    const destinations = [];
    const stores = [];
    const destinations_p = [];

    // Build parallel arrays for the store IDs and destinations
    data.forEach((store) => {

        const storeNum = store.getProperty('storeid');
        const storeLoc = store.getGeometry().get();

        destinations_p.push(storeLoc);
        stores.push(storeNum);


    });

    destinations.push(destinations_p, stores);
    //console.log(destinations);
    /******************************************************************************************
    I thought this step above would be helpful to make 2 dimentional array and send it to 
    distance metrix service and get storeid sorted in that function but distance matrix only 
    allow a set of inputs to be taken in consideration , we cannot set additional custom identtifier
*******************************************************************************************/



    // Retrieve the distances of each store from the origin
    // The returned list will be in the same order as the destinations list
    const service = new google.maps.DistanceMatrixService();
    // console.log(service);
    const getDistanceMatrix =
        (service, parameters) => new Promise((resolve, reject) => {
            service.getDistanceMatrix(parameters, (response, status) => {
                if (status != google.maps.DistanceMatrixStatus.OK) {
                    reject(response);
                } else {
                    const distances = [];
                    const results = response.rows[0].elements;
                    //console.log(response);
                    for (let j = 0; j < results.length; j++) {
                        const element = results[j];
                        //console.log(element);
                        const distanceText = (element.status != 'ZERO_RESULTS') ? element.distance.text : '9999999999 km';
                        const distanceVal = (element.status != 'ZERO_RESULTS') ? element.distance.value : '9999999999 km';
                        const distanceObject = {
                            storeid: stores[j],
                            distanceText: distanceText,
                            distanceVal: distanceVal,
                        };
                        distances.push(distanceObject);
                    }

                    resolve(distances);
                }
            });
        });


    /***********************************************************************************
    This method was build to pass only 25 destinations in array to distance matrix 
    service , that's the max it was take at a time , if there is change to this 
    settings in google then only chnage max_records value below and it should work
    ************************************************************************************/
    let p_results = [];
    let p_process = [];
    let nextSet = [];
    var lastIndex = 0
    var max_records = 25;
    var p_stores = [];
    var flatArray = [];
    var total_records = Math.ceil(destinations[0].length / max_records);


    // later i figured out that foreach does not work with async function however FOR loop works

    /*  data.forEach((store) => {
      let p_val = store.getGeometry().get().lat()+","+store.getGeometry().get().lng();
      p_results.push("["+p_val+"]");
        });
    */


    for (var g = 1; g <= total_records; g++) {

        let nextSet = [];

        /*************************************************************
        These debugging could be use to match what we are sending 
        matching with destination and storeid'd in parallel array
        console.log(destinations[0].slice(lastIndex, max_records));
        console.log(destinations[1].slice(lastIndex, max_records));
        *************************************************************/
        nextSet.push(destinations[0].slice(lastIndex, max_records));

        lastIndex = max_records;
        max_records = lastIndex + 25;

        /*********************************************************************************************
        There is some issue going on with hawaii lats and lng - This is Test for that these are hawaii
        lat,lng , I have opened Ticket with google : https://issuetracker.google.com/u/2/issues/189164319
           
           p_process.push(await getDistanceMatrix(service, {
              origins: ['21.304247103770592,-157.8504303328067'],
              destinations: ['19.638878300603324,-155.9901696156307','19.666046167473695,-155.99401485525755','19.517828633585925,-155.92144357145344','19.927879613527526,-155.78726601617393','21.304247103770592,-157.8504303328067'],
              travelMode: 'DRIVING',
              unitSystem: google.maps.UnitSystem.METRIC,
            }));
        
        *********************************************************************************************/

        p_process.push(await getDistanceMatrix(service, {
            origins: [origin],
            destinations: nextSet[0],
            travelMode: 'DRIVING',
            unitSystem: google.maps.UnitSystem.METRIC,
        }));


    }; // end for loop


    /**********************************************************
    So i get back array results from getDistance matrix and now
    they are nice stacked in 3,4,5 etc # of array depends on how
    many set of 25's where passed , now to process further more
    we need to merge all these array togather and stamp back 
    storeID - if you get 'undefined' error that means somehow 
    there is mismatch between array and loop count .
    **********************************************************/



    flatArray = Array.prototype.concat(...p_process);
    for (var h = 0; h < flatArray.length; h++) {

        flatArray[h].storeid = h; // reassigning storeid

    };


    // finally sorting array's
    flatArray.sort((first, second) => {
        return first.distanceVal - second.distanceVal;
    });


    return flatArray;

}; // end function
var geocoder = null;
var map = null;
var customerMarker = null;
var gmarkers = [];
var closest = [];

function initialize() {
  // alert("init");
  geocoder = new google.maps.Geocoder();
  map = new google.maps.Map(document.getElementById('map'), {
    zoom: 9,
    center: new google.maps.LatLng(52.6699927, -0.7274620),
    mapTypeId: google.maps.MapTypeId.ROADMAP
  });
  var infowindow = new google.maps.InfoWindow();
  var marker, i;
  var bounds = new google.maps.LatLngBounds();
  document.getElementById('info').innerHTML = "found " + locations.length + " locations<br>";
  for (i = 0; i < locations.length; i++) {
    var coordStr = locations[i][4];
    var coords = coordStr.split(",");
    var pt = new google.maps.LatLng(parseFloat(coords[0]), parseFloat(coords[1]));
    bounds.extend(pt);
    marker = new google.maps.Marker({
      position: pt,
      map: map,
      icon: locations[i][5],
      address: locations[i][2],
      title: locations[i][0],
      html: locations[i][0] + "<br>" + locations[i][2]
    });
    gmarkers.push(marker);
    google.maps.event.addListener(marker, 'click', (function(marker, i) {
        return function() {
          infowindow.setContent(marker.html);
          infowindow.open(map, marker);
        }
      })
      (marker, i));
  }
  map.fitBounds(bounds);

}

function codeAddress() {
  var numberOfResults = 25;
  var numberOfDrivingResults = 5;
  var address = document.getElementById('address').value;
  geocoder.geocode({
    'address': address
  }, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      map.setCenter(results[0].geometry.location);
      if (customerMarker) customerMarker.setMap(null);
      customerMarker = new google.maps.Marker({
        map: map,
        position: results[0].geometry.location
      });
      closest = findClosestN(results[0].geometry.location, numberOfResults);
      // get driving distance
      closest = closest.splice(0, numberOfResults);
      calculateDistances(results[0].geometry.location, closest, numberOfDrivingResults);
    } else {
      alert('Geocode was not successful for the following reason: ' + status);
    }
  });
}

function findClosestN(pt, numberOfResults) {
  var closest = [];
  document.getElementById('info').innerHTML += "processing " + gmarkers.length + "<br>";
  for (var i = 0; i < gmarkers.length; i++) {
    gmarkers[i].distance = google.maps.geometry.spherical.computeDistanceBetween(pt, gmarkers[i].getPosition());
    document.getElementById('info').innerHTML += "process " + i + ":" + gmarkers[i].getPosition().toUrlValue(6) + ":" + gmarkers[i].distance.toFixed(2) + "<br>";
    gmarkers[i].setMap(null);
    closest.push(gmarkers[i]);
  }
  closest.sort(sortByDist);
  return closest;
}

function sortByDist(a, b) {
  return (a.distance - b.distance)
}

function calculateDistances(pt, closest, numberOfResults) {
  var service = new google.maps.DistanceMatrixService();
  var request = {
    origins: [pt],
    destinations: [],
    travelMode: google.maps.TravelMode.DRIVING,
    unitSystem: google.maps.UnitSystem.METRIC,
    avoidHighways: false,
    avoidTolls: false
  };
  for (var i = 0; i < closest.length; i++) {
    request.destinations.push(closest[i].getPosition());
  }
  service.getDistanceMatrix(request, function(response, status) {
    if (status != google.maps.DistanceMatrixStatus.OK) {
      alert('Error was: ' + status);
    } else {
      var origins = response.originAddresses;
      var destinations = response.destinationAddresses;
      var outputDiv = document.getElementById('side_bar');
      outputDiv.innerHTML = '';

      var results = response.rows[0].elements;
      // save title and address in record for sorting
      for (var i = 0; i < closest.length; i++) {
        results[i].title = closest[i].title;
        results[i].address = closest[i].address;
        results[i].idx_closestMark = i;
      }
      results.sort(sortByDistDM);
      for (var i = 0;
        ((i < numberOfResults) && (i < closest.length)); i++) {
        closest[i].setMap(map);
        outputDiv.innerHTML += "<a href='javascript:google.maps.event.trigger(closest[" + results[i].idx_closestMark + "],\"click\");'>" + results[i].title + '</a><br>' + results[i].address + "<br>" + results[i].distance.text + ' appoximately ' + results[i].duration.text + '<br><hr>';
      }
    }
  });
}

function sortByDistDM(a, b) {
  return (a.distance.value - b.distance.value)
}

google.maps.event.addDomListener(window, 'load', initialize);
// Store Name[0],delivery[1],Address[2],Delivery Zone[3],Coordinates[4] data from FusionTables pizza stores example
var locations = [
  ["manteca", "no", "165 St Dominic's Drive, Suite 120, Manteca, CA 95337, United States", "<Polygon><outerBoundaryIs><LinearRing><coordinates>37.7989569785489, -121.2457803959148, </coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.7989569785489, -121.2457803959148", "http://maps.google.com/mapfiles/ms/icons/blue.png"],
  ["Modesto", "yes", "2001 McHenry Ave suite c, Modesto, CA 95350", "<Polygon><outerBoundaryIs><LinearRing><coordinates>37.67168268071346, -120.99588593892189, </coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.67168268071346, -120.99588593892189", "http://maps.google.com/mapfiles/ms/icons/green.png"],
  ["Salinas", "no", "668 E Romie Ln, Salinas, CA 93901", "<Polygon><outerBoundaryIs><LinearRing><coordinates>36.65946188634873, -121.64384530884517, </coordinates></LinearRing></outerBoundaryIs></Polygon>", "36.65946188634873, -121.64384530884517", "http://maps.google.com/mapfiles/ms/icons/red.png"],
  ["North Fresno", "yes", "7720 N Fresno St #106, Fresno", "<Polygon><outerBoundaryIs><LinearRing><coordinates>36.850906490807695, -119.78336169402402, </coordinates></LinearRing></outerBoundaryIs></Polygon>", "36.850906490807695, -119.78336169402402", "http://maps.google.com/mapfiles/ms/icons/green.png"],
  ["Stockton", "yes", "6445 Pacific Ave, Stockton, CA 95207", "<Polygon><outerBoundaryIs><LinearRing><coordinates>38.00869528204428, -121.32144706598464, </coordinates></LinearRing></outerBoundaryIs></Polygon>", "38.00869528204428, -121.32144706598464", "http://maps.google.com/mapfiles/ms/icons/blue.png"],
  ["rancho cordova", "yes", "2485 Sunrise Blvd STE C, Gold River, CA 95670", "<Polygon><outerBoundaryIs><LinearRing><coordinates>38.61414637168712, -121.26836087865699,  </coordinates></LinearRing></outerBoundaryIs></Polygon>", "38.61414637168712, -121.26836087865699", "http://maps.google.com/mapfiles/ms/icons/green.png"],
  ["Turlock", "yes", "3051 Countryside Dr, Turlock, CA 95380", "<Polygon><outerBoundaryIs><LinearRing><coordinates>37.52115426554001, -120.88342493687244, </coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.52115426554001, -120.88342493687244", "http://maps.google.com/mapfiles/ms/icons/green.png"],
  ["Fair Oaks", "yes", "5450 Dewey Dr, Fair Oaks, CA 95628", "<Polygon><outerBoundaryIs><LinearRing><coordinates>38.6654151803707, -121.30725862370025, </coordinates></LinearRing></outerBoundaryIs></Polygon>", "38.6654151803707, -121.30725862370025", "http://maps.google.com/mapfiles/ms/icons/green.png"],
  ["Elk Grove", "yes", "5021 Laguna Blvd, Elk Grove, CA 95758", "<Polygon><outerBoundaryIs><LinearRing><coordinates>38.4244478858968, -121.44655697842991, </coordinates></LinearRing></outerBoundaryIs></Polygon>", "38.4244478858968, -121.44655697842991", "http://maps.google.com/mapfiles/ms/icons/green.png"],
  
  //New York, NY, USA (40.7127837, -74.00594130000002)  
  ["New York, NY, USA", "no", "New York City Hall, New York, NY 10007, USA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.02343,37.52198,0 -122.023773,37.558731,0 -121.989784,37.573426,0 -121.959572,37.566351,0 -121.944466,37.544305,0 -121.967125,37.520891,0 -122.023087,37.522525,0</coordinates></LinearRing></outerBoundaryIs></Polygon>", "40.7127837, -74.0059413", "http://maps.google.com/mapfiles/ms/icons/yellow.png"],
  // Newark, NJ, USA (40.735657, -74.1723667)  
  ["Newark, NJ, USA", "no", "169 Market St, Newark, NJ 07102, USA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.02343,37.52198,0 -122.023773,37.558731,0 -121.989784,37.573426,0 -121.959572,37.566351,0 -121.944466,37.544305,0 -121.967125,37.520891,0 -122.023087,37.522525,0</coordinates></LinearRing></outerBoundaryIs></Polygon>", "40.735657, -74.1723667", "http://maps.google.com/mapfiles/ms/icons/yellow.png"],
  // Baltimore, MD, USA (39.2903848, -76.6121893
  ["Baltimore, MD, USA", "no", "201-211 E Fayette St, Baltimore, MD 21202, USA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.02343,37.52198,0 -122.023773,37.558731,0 -121.989784,37.573426,0 -121.959572,37.566351,0 -121.944466,37.544305,0 -121.967125,37.520891,0 -122.023087,37.522525,0</coordinates></LinearRing></outerBoundaryIs></Polygon>", "39.2903848, -76.6121893", "http://maps.google.com/mapfiles/ms/icons/yellow.png"],
  // Boston, MA, USA (42.3600825, -71.05888
  ["Boston, MA, USA", "no", "City Hall Plaza, Boston, MA 02203, USA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.02343,37.52198,0 -122.023773,37.558731,0 -121.989784,37.573426,0 -121.959572,37.566351,0 -121.944466,37.544305,0 -121.967125,37.520891,0 -122.023087,37.522525,0</coordinates></LinearRing></outerBoundaryIs></Polygon>", "42.3600825, -71.05888", "http://maps.google.com/mapfiles/ms/icons/yellow.png"],
  // Philadelphia, PA, USA (39.9525839, -75.16522150000003)
  ["Philadelphia, PA, USA", "no", "1414 PA-611, Philadelphia, PA 19102, USA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.02343,37.52198,0 -122.023773,37.558731,0 -121.989784,37.573426,0 -121.959572,37.566351,0 -121.944466,37.544305,0 -121.967125,37.520891,0 -122.023087,37.522525,0</coordinates></LinearRing></outerBoundaryIs></Polygon>", "39.9525839, -75.1652215", "http://maps.google.com/mapfiles/ms/icons/yellow.png"]
];