5

Googleマップアプリにドライブタイムポリゴン機能を追加するための純粋な(または可能な限り純粋な)GoogleマップJavaScriptAPIV3ソリューションを探しています。

基本的にワークフローは、ユーザーが地図上のマーカーまたはポイントをクリックすると、マーカー/ポイントの周囲にポリゴンが生成され、任意の方向に5分以内に運転できるエリアを示します。

これを純粋なGoogleMapsAPIソリューションとして実行できるかどうかはわかりません。ランダムなルートを使用して、Directions Serviceを度も呼び出す必要があり、時間のしきい値に収まらないものはすべて破棄されるためです。 。これが実行可能かどうか、またはこれを設計するための最良の方法が何であるかはわかりません。これにはバックエンド処理を使用する必要があるかもしれませんが、最初に他のすべてのオプションを除外したいのですが、バックエンドソリューションの例を歓迎します。

ヘルプ、提案、または例は大歓迎です。以下は私が遭遇したいくつかの例ですが、それらは純粋なGoogle Maps APIソリューションではないか、ドライブタイムを使用していません。

  1. Google Maps Utility Libraryの例-クリックしたポイントの周囲に1、2、3分のドライブタイムポリゴンを描画しますが、Esriのサンプルジオプロセシングサービスを使用して計算を実行し、ポリゴンジオメトリを生成するため、私の場合は機能しません要件。

  2. 30マイルの方向-これは、DirectionsAPIを使用した純粋なGoogleMaps APIソリューションであり、優れたポリゴンを描画します、計算にドライブ時間を使用せず、ポイントから30マイル離れた場所までの距離だけです。

  3. Mapnificent-純粋なGoogleMapsAPIソリューションのようで、APIがありますが、運転時間ではなく、公共交通機関のデータから取得した公共交通機関の時間を処理しています。したがって、時間を増やすと「開く」領域は、指定された時間内に公共交通機関に乗れる場所を示します。私はこれが欲しいのですが、通過時間の代わりに運転時間で。

4

1 に答える 1

4

古くてV2APIで書かれていますが、あなたが「30マイルの道順」と呼んでいるのは私のマッシュアップです。マッシュアップと同じ原理を使用できます。つまり、始点の周りの円を計算し、その点を目的地として使用し、各ルートについて、目的の運転時間に達したときにそれを切り取ります。

元のリンクは無効です(以下のコードスニペット)

この例では、関数shortenAndShow()は、ルートの30マイルを超える部分を遮断します。30マイルの目的地の円は直線の半径を持っているため、道路にはカーブがあるため到達する可能性は低く、青い円の端に到達する前に30マイルに到達します。同じことを行うことができますが、距離ではなくドライブ時間に基づいてルートを切断します。

パフォーマンスは、可能な宛先ポイントを設定した円に沿った間隔(度単位)によって異なります。1度ごとの試行には、10度ごとの試行の10倍のリクエストが必要です(デフォルトは30度)。

コードスニペット:

var map;
var container;
var zoom = 9;
var centerPoint = new google.maps.LatLng(35.149534, -90.04898);
var dirService = new google.maps.DirectionsService();
var centerMarker;
var circleMarkers = Array();
var circlePoints = Array();
var drivePolyPoints = Array();
var searchPolygon, drivePolygon;
var distToDrive = 30; // miles
var pointInterval = 30;
var searchPoints = [];
var polyline;
var polylines = [];
var redIcon8 = "https://maps.gstatic.com/intl/en_us/mapfiles/markers2/measle.png";

function initialize() {
  map = new google.maps.Map(
    document.getElementById("map_canvas"), {
      center: centerPoint,
      zoom: 9,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });
  google.maps.event.addListener(map, "click", mapClick);
}
google.maps.event.addDomListener(window, "load", initialize);

function mapClick(evt) {
  // map.clearOverlays();
  circleMarkers = Array();
  if (!centerMarker) {
    centerMarker = new google.maps.Marker({
      position: evt.latLng,
      map: map
    });
  } else {
    centerMarker.setMap(null);
    centerMarker.setPosition(evt.latLng);
  }
  centerMarker.setMap(map);
  searchPoints = getCirclePoints(evt.latLng, distToDrive);
  drivePolyPoints = Array();
  getDirections();
}

function getCirclePoints(center, radius) {
  var bounds = new google.maps.LatLngBounds();
  var circlePoints = Array();
  var searchPoints = Array();
  with(Math) {
    var rLat = (radius / 3963.189) * (180 / PI); // miles
    var rLng = rLat / cos(center.lat() * (PI / 180));
    for (var a = 0; a < 361; a++) {
      var aRad = a * (PI / 180);
      var x = center.lng() + (rLng * cos(aRad));
      var y = center.lat() + (rLat * sin(aRad));
      var point = new google.maps.LatLng(parseFloat(y), parseFloat(x), true);
      bounds.extend(point);
      circlePoints.push(point);
      if (a % pointInterval == 0) {
        searchPoints.push(point);
      }
    }
  }
  searchPolygon = new google.maps.Polygon({
    paths: circlePoints,
    strokeColor: '#0000ff',
    strokeWeight: 1,
    strokeOpacity: 1,
    fillColor: '#0000ff',
    fillOpacity: 0.2
  });
  searchPolygon.setMap(map);
  map.fitBounds(bounds);
  return searchPoints;
}

function getDirections() {
  if (!searchPoints.length) {
    return;
  }
  var to = searchPoints.shift();
  var request = {
    origin: centerMarker.getPosition(),
    destination: to,
    travelMode: google.maps.TravelMode.DRIVING
  };
  dirService.route(request, function(result, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      var distance = parseInt(result.routes[0].legs[0].distance.value / 1609);
      var duration = parseFloat(result.routes[0].legs[0].duration.value / 3600).toFixed(2);
      var path = result.routes[0].overview_path;
      var legs = result.routes[0].legs;
      if (polyline && polyline.setPath) {
        polyline.setPath([]);
      } else {
        polyline = new google.maps.Polyline({
          path: [],
          // map: map,
          strokeColor: "#FF0000",
          strokeOpacity: 1
        });
      }
      for (i = 0; i < legs.length; i++) {
        var steps = legs[i].steps;
        for (j = 0; j < steps.length; j++) {
          var nextSegment = steps[j].path;
          for (k = 0; k < nextSegment.length; k++) {
            polyline.getPath().push(nextSegment[k]);
            // bounds.extend(nextSegment[k]);
          }
        }
      }
      // polyline.setMap(map);
      shortenAndShow(polyline);
      getDirections();
    } else {
      console.log("Directions request failed, status=" + status + " [from:" + request.origin + " to:" + request.destination + "]");
      getDirections();
    }
  });
}

function shortenAndShow(polyline) {
  var distToDriveM = distToDrive * 1609;
  var dist = 0;
  var cutoffIndex = 0;
  var copyPoints = Array();
  for (var n = 0; n < polyline.getPath().getLength() - 1; n++) {
    dist += google.maps.geometry.spherical.computeDistanceBetween(polyline.getPath().getAt(n), polyline.getPath().getAt(n + 1));
    //GLog.write(dist + ' - ' + distToDriveM);
    if (dist < distToDriveM) {
      copyPoints.push(polyline.getPath().getAt(n));
    } else {
      break;
    }
  }
  var lastPoint = copyPoints[copyPoints.length - 1];
  var newLine = new google.maps.Polyline({
    path: copyPoints,
    strokeColor: '#ff0000',
    strokeWeight: 2,
    strokeOpacity: 1
  });
  newLine.setMap(map);
  polylines.push(newLine);
  drivePolyPoints.push(lastPoint);
  addBorderMarker(lastPoint, dist)
  if (drivePolyPoints.length > 3) {
    if (drivePolygon) {
      drivePolygon.setMap(null);
    }
    drivePolygon = new google.maps.Polygon({
      paths: drivePolyPoints,
      strokeColor: '#00ff00',
      strokeWeight: 1,
      strokeOpacity: 1,
      fillColor: '#00ff00',
      fillOpacity: 0.4
    });
    drivePolygon.setMap(map);
  }
}

function addBorderMarker(pt, d) {
  var str = pt.lat().toFixed(6) + ',' + pt.lng().toFixed(6) + ' - Driving Distance: ' + (d / 1609).toFixed(2) + ' miles';
  var marker = new google.maps.Marker({
    position: pt,
    icon: redIcon8,
    title: str
  });
  circleMarkers.push(marker);
  marker.setMap(map);
}

function clearOverlays() {
  for (var i = 0; i < circleMarkers.length; i++) {
    circleMarkers[i].setMap(null);
  }
  circleMarkers = [];
  for (var i = 0; i < circlePoints.length; i++) {
    circlePoints[i].setMap(null);
  }
  circlePoints = [];
  for (var i = 0; i < polylines.length; i++) {
    polylines[i].setMap(null);
  }
  polylines = [];
  if (searchPolygon && searchPolygon.setMap) searchPolygon.setMap(null);
  if (drivePolygon && drivePolygon.setMap) drivePolygon.setMap(null);
  if (centerMarker && centerMarker.setMap) centerMarker.setMap(null);
}
html,
body,
#map_canvas {
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px
}
<a href="#" onclick="clearOverlays();">Clear</a>&nbsp;|&nbsp;
<a href="#" onclick="pointInterval=30;clearOverlays();">interval 30 (default)</a>&nbsp;|&nbsp;
<a href="#" onclick="pointInterval=20;clearOverlays();">interval 20</a>&nbsp;|&nbsp;

<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry"></script>
<div id="map_canvas"></div>

于 2012-09-08T09:46:47.350 に答える