来自折线百分比的纬度 [英] latLng from polyLine Percentage

查看:12
本文介绍了来自折线百分比的纬度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何沿折线返回给定百分比的 latLng 值?我花了一天时间使用插值和单个节点.他们有更简单的功能可以完成咕噜声吗?

谷歌地图 API v3谢谢!

解决方案

http://www.geocodezip.com/scripts/v3_epoly.js

为移植到 v3 的 Google Maps Javascript API v2 编写.v2 版本的文档

有这两种方法:

  • .Distance() 返回多边形路径的长度
  • .GetPointAtDistance() 返回指定距离处的 GLatLng
    沿着小路.
    距离以米为单位
    如果路径短于该路径,则返回 null

这应该可以工作(如果您包含该脚本并且您的折线变量是polyline"):

var latlng = polyline.GetPointAtDistance(polyline.Distance()*(所需百分比)/100);

当然,如果多段线的长度没有变化,那么每次要在多段线上找到一个点时使用一次计算长度会更有效.

var polylength = polyline.Distance();var latlng = polylength*(所需百分比)/100);

实例

代码片段:

var directionDisplay;var directionService = new google.maps.DirectionsService();无功地图;var polyline = null;var 标记;var 信息窗口;函数 createMarker(latlng, label, html) {//alert("createMarker("+latlng+","+label+","+html+","+color+")");var contentString = ''+ 标签 + '</b><br>'+ html;var 标记 = 新的 google.maps.Marker({位置:latlng,地图:地图,标题:标签,zIndex: Math.round(latlng.lat() * -100000) <<5、内容字符串:内容字符串});标记.我的名字 = 标签;//gmarkers.push(marker);google.maps.event.addListener(marker, 'click', function() {infowindow.setContent(this.contentString);infowindow.open(地图,标记);});返回标记;}var myLatLng = null;变量 lat;变种;无功缩放 = 2;无功映射类型;函数初始化(){infowindow = new google.maps.InfoWindow();myLatLng = 新的 google.maps.LatLng(37.422104808, -122.0838851);地图类型 = google.maps.MapTypeId.ROADMAP;//如果 URL 的 eh 端有任何参数,它们将在 location.search 中//看起来像?marker=3"//跳过第一个字符,我们对?"不感兴趣var query = location.search.substring(1);//在每个&"处拆分其余部分给出argname=value"对列表的字符var pair = query.split("&");for (var i = 0; i  总时间为:" + (totalTime/60).toFixed(2) + " 分钟
平均速度为: " + (totalDist/(totalTime/3600)).toFixed(2) + " kph";document.getElementById("totalTime").value = (totalTime/60.).toFixed(2);}功能 putMarkerOnRoute(百分比){如果(百分比 > 100){百分比 = 100;document.getElementById('percent').value = percent;}var 距离 = 百分比/100 * totalDist * 1000;//time = ((percentage/100) * totalTIme/60).toFixed(2);//alert("Time:"+time+" totalTime:"+totalTime+" totalDist:"+totalDist+" dist:"+distance);如果(!标记){标记 = createMarker(polyline.GetPointAtDistance(distance), "percent:" + percent, "marker");} 别的 {标记.setPosition(polyline.GetPointAtDistance(distance));marker.setTitle("百分比:" + 百分比);marker.contentString = "<b>percent:" + percent + "</b><br>distance:" + (distance/1000).toFixed(2) + " km<br>marker";google.maps.event.trigger(标记,点击");}}google.maps.event.addDomListener(window, 'load', initialize);//来自 epoly_v3.js//修改为使用几何库计算线段的长度//=== 一种返回沿路径给定距离的点的 GLatLng 的方法 ===//=== 如果路径短于指定距离则返回 null ===google.maps.Polyline.prototype.GetPointAtDistance = 函数(米){//一些尴尬的特殊情况if (metres == 0) 返回 this.getPath().getAt(0);如果(米<0)返回空值;如果 (this.getPath().getLength() <2) 返回空值;无功分布= 0;var olddist = 0;对于 (var i = 1;(i < this.getPath().getLength() && dist < 米);我++) {olddist = dist;dist += google.maps.geometry.sphereal.computeDistanceBetween(this.getPath().getAt(i), this.getPath().getAt(i - 1));}如果(距离<米){返回空;}var p1 = this.getPath().getAt(i - 2);var p2 = this.getPath().getAt(i - 1);var m = (米 - olddist)/(dist - olddist);返回新的 google.maps.LatLng(p1.lat() + (p2.lat() - p1.lat()) * m, p1.lng() + (p2.lng() - p1.lng()) *米);}

html {高度:100%}身体 {高度:100%;边距:0px;填充:0px}

<!-- 用你自己的 API 密钥替换 key 参数的值.--><script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=geometry"></script><div id="工具">开始:<input type="text" name="start" id="start" value="海得拉巴"/>结尾:<input type="text" name="end" id="end" value="Bangalore"/><input type="submit" onclick="calcRoute();"/><br/>百分比:<input type="text" name="percent" id="percent" value="0"/><input type="submit" onclick="putMarkerOnRoute(parseFloat(document.getElementById('percent').value));"/>&nbsp;总时间:<input type="text" name="totalTime" id="totalTime" value="0"/>

<div id="map_canvas" style="float:left;width:70%;height:100%;"></div><div id="control_panel" style="float:right;width:30%;text-align:left;padding-top:20px"><div id="directions_panel" style="margin:20px;background-color:#FFEE77;"></div><div id="total"></div>

How do I return a latLng value from a given percentage along a polyLine? I have spent a day on this using interpolate and individual nodes. Is their an easier function out there that does the grunt work?

Google maps API v3 thanks!

解决方案

http://www.geocodezip.com/scripts/v3_epoly.js

written for the Google Maps Javascript API v2 ported to v3. Documentation for the v2 version

Has these two methods:

  • .Distance() returns the length of the poly path
  • .GetPointAtDistance() returns a GLatLng at the specified distance
    along the path.
    The distance is specified in metres
    Returns null if the path is shorter than that

This should work (if you include that script and your polyline variable is "polyline"):

var latlng = polyline.GetPointAtDistance(polyline.Distance()*(desired percentage)/100);

of course if you polyline isn't changing in length, it would be more efficient to compute the length once an use it each time you want to find a point on the polyline.

var polylength = polyline.Distance();
var latlng = polylength*(desired percentage)/100);

live example

code snippet:

var directionDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
var polyline = null;
var marker;
var infowindow;

function createMarker(latlng, label, html) {
  // alert("createMarker("+latlng+","+label+","+html+","+color+")");
  var contentString = '<b>' + label + '</b><br>' + html;
  var marker = new google.maps.Marker({
    position: latlng,
    map: map,
    title: label,
    zIndex: Math.round(latlng.lat() * -100000) << 5,
    contentString: contentString
  });
  marker.myname = label;
  // gmarkers.push(marker);

  google.maps.event.addListener(marker, 'click', function() {
    infowindow.setContent(this.contentString);
    infowindow.open(map, marker);
  });
  return marker;
}
var myLatLng = null;
var lat;
var lng;
var zoom = 2;
var maptype;

function initialize() {
  infowindow = new google.maps.InfoWindow();
  myLatLng = new google.maps.LatLng(37.422104808, -122.0838851);
  maptype = google.maps.MapTypeId.ROADMAP;
  // If there are any parameters at eh end of the URL, they will be in  location.search
  // looking something like  "?marker=3"

  // skip the first character, we are not interested in the "?"
  var query = location.search.substring(1);

  // split the rest at each "&" character to give a list of  "argname=value"  pairs
  var pairs = query.split("&");
  for (var i = 0; i < pairs.length; i++) {
    // break each pair at the first "=" to obtain the argname and value
    var pos = pairs[i].indexOf("=");
    var argname = pairs[i].substring(0, pos).toLowerCase();
    var value = pairs[i].substring(pos + 1);

    // process each possible argname  -  use unescape() if theres any chance of spaces
    if (argname == "filename") {
      filename = unescape(value);
    }
    if (argname == "lat") {
      lat = parseFloat(value);
    }
    if (argname == "lng") {
      lng = parseFloat(value);
    }
    if (argname == "start") {
      document.getElementById("start").value = decodeURI(value);
    }
    if (argname == "end") {
      document.getElementById("end").value = decodeURI(value);
    }
    if (argname == "time") {
      document.getElementById("time").value = decodeURI(value);
      // putMarkerOnRoute(parseFloat(document.getElementById('time').value));
    }
    if (argname == "zoom") {
      zoom = parseInt(value);
    }
    if (argname == "type") {
      // from the v3 documentation 8/24/2010
      // HYBRID This map type displays a transparent layer of major streets on satellite images. 
      // ROADMAP This map type displays a normal street map. 
      // SATELLITE This map type displays satellite images. 
      // TERRAIN This map type displays maps with physical features such as terrain and vegetation. 
      if (value == "m") {
        maptype = google.maps.MapTypeId.ROADMAP;
      }
      if (value == "k") {
        maptype = google.maps.MapTypeId.SATELLITE;
      }
      if (value == "h") {
        maptype = google.maps.MapTypeId.HYBRID;
      }
      if (value == "t") {
        maptype = google.maps.MapTypeId.TERRAIN;
      }

    }
  }
  if (!isNaN(lat) && !isNaN(lng)) {
    myLatLng = new google.maps.LatLng(lat, lng);
  }
  var myOptions = {
    zoom: zoom,
    center: myLatLng,
    mapTypeId: maptype
  };
  directionsDisplay = new google.maps.DirectionsRenderer({
    suppressMarkers: true
  });

  map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  polyline = new google.maps.Polyline({
    path: [],
    strokeColor: '#FF0000',
    strokeWeight: 3
  });
  directionsDisplay.setMap(map);
  calcRoute();
}

function calcRoute() {

  var start = document.getElementById("start").value;
  var end = document.getElementById("end").value;
  var travelMode = google.maps.DirectionsTravelMode.DRIVING

  var request = {
    origin: start,
    destination: end,
    travelMode: travelMode
  };
  directionsService.route(request, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      polyline.setPath([]);
      var bounds = new google.maps.LatLngBounds();
      startLocation = new Object();
      endLocation = new Object();
      directionsDisplay.setDirections(response);
      var route = response.routes[0];
      var summaryPanel = document.getElementById("directions_panel");
      summaryPanel.innerHTML = "";

      // For each route, display summary information.
      var path = response.routes[0].overview_path;
      var legs = response.routes[0].legs;
      for (i = 0; i < legs.length; i++) {
        if (i == 0) {
          startLocation.latlng = legs[i].start_location;
          startLocation.address = legs[i].start_address;
          // marker = google.maps.Marker({map:map,position: startLocation.latlng});
          // marker = createMarker(legs[i].start_location,"start",legs[i].start_address,"green");
        }
        endLocation.latlng = legs[i].end_location;
        endLocation.address = legs[i].end_address;
        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);

      computeTotalDistance(response);
      putMarkerOnRoute(parseFloat(document.getElementById('percent').value));
    } else {
      alert("directions response " + status);
    }
  });
}

var totalDist = 0;
var totalTime = 0;

function computeTotalDistance(result) {
  totalDist = 0;
  totalTime = 0;
  var myroute = result.routes[0];
  for (i = 0; i < myroute.legs.length; i++) {
    totalDist += myroute.legs[i].distance.value;
    totalTime += myroute.legs[i].duration.value;
  }
  totalDist = totalDist / 1000.
  document.getElementById("total").innerHTML = "total distance is: " + totalDist + " km<br>total time is: " + (totalTime / 60).toFixed(2) + " minutes<br>average speed is: " + (totalDist / (totalTime / 3600)).toFixed(2) + " kph";
  document.getElementById("totalTime").value = (totalTime / 60.).toFixed(2);
}

function putMarkerOnRoute(percent) {
  if (percent > 100) {
    percent = 100;
    document.getElementById('percent').value = percent;
  }

  var distance = percent / 100 * totalDist * 1000;
  // time = ((percentage/100) * totalTIme/60).toFixed(2);
  // alert("Time:"+time+" totalTime:"+totalTime+" totalDist:"+totalDist+" dist:"+distance);
  if (!marker) {
    marker = createMarker(polyline.GetPointAtDistance(distance), "percent: " + percent, "marker");
  } else {
    marker.setPosition(polyline.GetPointAtDistance(distance));
    marker.setTitle("percent:" + percent);
    marker.contentString = "<b>percent: " + percent + "</b><br>distance: " + (distance / 1000).toFixed(2) + " km<br>marker";
    google.maps.event.trigger(marker, "click");
  }
}
google.maps.event.addDomListener(window, 'load', initialize);
// from epoly_v3.js
// modified to use geometry library for length of line segments
// === A method which returns a GLatLng of a point a given distance along the path ===
// === Returns null if the path is shorter than the specified distance ===
google.maps.Polyline.prototype.GetPointAtDistance = function(metres) {
  // some awkward special cases
  if (metres == 0) return this.getPath().getAt(0);
  if (metres < 0) return null;
  if (this.getPath().getLength() < 2) return null;
  var dist = 0;
  var olddist = 0;
  for (var i = 1;
    (i < this.getPath().getLength() && dist < metres); i++) {
    olddist = dist;
    dist += google.maps.geometry.spherical.computeDistanceBetween(this.getPath().getAt(i), this.getPath().getAt(i - 1));
  }
  if (dist < metres) {
    return null;
  }
  var p1 = this.getPath().getAt(i - 2);
  var p2 = this.getPath().getAt(i - 1);
  var m = (metres - olddist) / (dist - olddist);
  return new google.maps.LatLng(p1.lat() + (p2.lat() - p1.lat()) * m, p1.lng() + (p2.lng() - p1.lng()) * m);
}

html {
  height: 100%
}

body {
  height: 100%;
  margin: 0px;
  padding: 0px
}

<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=geometry"></script>
<div id="tools">
  start:
  <input type="text" name="start" id="start" value="Hyderabad" /> end:
  <input type="text" name="end" id="end" value="Bangalore" />
  <input type="submit" onclick="calcRoute();" /><br /> percentage:
  <input type="text" name="percent" id="percent" value="0" />
  <input type="submit" onclick="putMarkerOnRoute(parseFloat(document.getElementById('percent').value));" /> &nbsp;total time:<input type="text" name="totalTime" id="totalTime" value="0" />
</div>
<div id="map_canvas" style="float:left;width:70%;height:100%;"></div>
<div id="control_panel" style="float:right;width:30%;text-align:left;padding-top:20px">
  <div id="directions_panel" style="margin:20px;background-color:#FFEE77;"></div>
  <div id="total"></div>
</div>

这篇关于来自折线百分比的纬度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆