在谷歌地图上画圆弧 [英] Draw circle's arc on google maps

查看:26
本文介绍了在谷歌地图上画圆弧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个想法是使用角度绘制以特定点为中心的弧.注意:不是弦,也不是扇形,也不是弦和弧之间的区域.

纪念品:

代码片段(使用几何库):

var EarthRadiusMeters = 6378137.0;//米/* 基于纬度/经度球面大地测量公式 &脚本在 http://www.movable-type.co.uk/scripts/latlong.html(c) 克里斯维内斯 2002-2010*/google.maps.LatLng.prototype.DestinationPoint = function(brng, dist) {var R = EarthRadiusMeters;//地球的平均半径,以米为单位var brng = brng.toRad();var lat1 = this.lat().toRad(),lon1 = this.lng().toRad();var lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist/R) +Math.cos(lat1) * Math.sin(dist/R) * Math.cos(brng));var lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist/R) * Math.cos(lat1),Math.cos(dist/R) - Math.sin(lat1) * Math.sin(lat2));返回新的 google.maps.LatLng(lat2.toDeg(), lon2.toDeg());}/*** 扩展 Number 对象以将度数转换为弧度** @return {Number} 方位弧度* @忽略*/Number.prototype.toRad = function() {返回这个 * Math.PI/180;};/*** 扩展 Number 对象以将弧度转换为度数** @return {Number} 方位角* @忽略*/Number.prototype.toDeg = function() {返回 * 180/Math.PI;};var infowindow = 新的 google.maps.InfoWindow({尺寸:新 google.maps.Size(150, 50)});函数 createMarker(latlng, html) {var 内容字符串 = html;var 标记 = 新的 google.maps.Marker({位置:latlng,地图:地图,zIndex: Math.round(latlng.lat() * -100000) <<5});bounds.extend(latlng);google.maps.event.addListener(标记,点击",函数(){infowindow.setContent(contentString);infowindow.open(地图,标记);});}函数drawArc(中心,初始轴承,最终轴承,半径){var d2r = Math.PI/180;//度到弧度var r2d = 180/Math.PI;//弧度到度变量点 = 32;//查找 lat/lon 中的 raidusvar rlat = (半径/EarthRadiusMeters) * r2d;var rlng = rlat/Math.cos(center.lat() * d2r);var extp = new Array();if (initialBearing > finalBearing) finalBearing += 360;var deltaBearing = finalBearing - initialBearing;deltaBearing = deltaBearing/点数;对于 (var i = 0;(i <点 + 1);我++){extp.push(center.DestinationPoint(initialBearing + i * deltaBearing, radius));bounds.extend(extp[extp.length - 1]);}返回扩展;}函数drawCircle(点,半径){var d2r = Math.PI/180;//度到弧度var r2d = 180/Math.PI;//弧度到度var EarthRadiusMeters = 6378137.0;//米var 地球半径 = 3963;//3963 是地球的半径,以英里为单位变量点 = 32;//查找 lat/lon 中的 raidusvar rlat = (半径/EarthRadiusMeters) * r2d;var rlng = rlat/Math.cos(point.lat() * d2r);var extp = new Array();for (var i = 0; i < points + 1; i++)//额外的一个确保我们连接{var theta = Math.PI * (i/(points/2));ey = point.lng() + (rlng * Math.cos(theta));//中心 a + 半径 x * cos(theta)ex = point.lat() + (rlat * Math.sin(theta));//中心 b + 半径 y * sin(theta)extp.push(新的 google.maps.LatLng(ex, ey));bounds.extend(extp[extp.length - 1]);}//警报(extp.length);返回扩展;}变种地图=空;变量边界=空;函数初始化(){var myOptions = {缩放:10,中心:新的 google.maps.LatLng(-33.9, 151.2),地图类型控制:真,地图类型控制选项:{样式:google.maps.MapTypeControlStyle.DROPDOWN_MENU},导航控制:真,mapTypeId:google.maps.MapTypeId.ROADMAP}地图 = 新 google.maps.Map(document.getElementById("map_canvas"),我的选项);bounds = new google.maps.LatLngBounds();google.maps.event.addListener(map, 'click', function() {infowindow.close();});var startPoint = new google.maps.LatLng(48.610335003092956, -1.6123447775299600);var endPoint = new google.maps.LatLng(48.596190206866830, -1.5551704322317228);var centerPoint = new google.maps.LatLng(48.565630000000006, -1.6050300000000002);createMarker(startPoint, "start: " + startPoint.toUrlValue(6) + "
到中心的距离:" + (google.maps.geometry.spherical.computeDistanceBetween(centerPoint, startPoint)/1000).toFixed(3)+ " km<br>方位:" + google.maps.geometry.spherical.computeHeading(centerPoint, startPoint) + "<br><a href='javascript:map.setCenter(new google.maps.LatLng("+ startPoint.toUrlValue(6) + "));map.setZoom(20);'>放大</a> - <a href='javascript:map.fitBounds(bounds);'>缩小</a>");createMarker(endPoint, "end: " + endPoint.toUrlValue(6) + "
到中心的距离:" + (google.maps.geometry.spherical.computeDistanceBetween(centerPoint, endPoint)/1000).toFixed(3)+ " km<br>方位:" + google.maps.geometry.spherical.computeHeading(centerPoint, endPoint) + "<br><a href='javascript:map.setCenter(new google.maps.LatLng("+ endPoint.toUrlValue(6) + "));map.setZoom(20);'>放大</a> - <a href='javascript:map.fitBounds(bounds);'>缩小</a>");createMarker(centerPoint, "center: " + centerPoint.toUrlValue(6));var arcPts = drawArc(centerPoint, google.maps.geometry.spherical.computeHeading(centerPoint, startPoint), google.maps.geometry.spherical.computeHeading(centerPoint, endPoint), google.maps.geometry.spherical.computeDistanceBetween(centerPoint, startPoint));//添加开始和结束行arcPts.push(centerPoint);bounds.extend(centerPoint);arcPts.push(startPoint);var piePoly = 新的 google.maps.Polygon({路径:[arcPts],strokeColor: "#00FF00",中风不透明度:0.5,行程重量:2,填充颜​​色:#FF0000",填充不透明度:0.35,地图:地图});map.fitBounds(边界);}google.maps.event.addDomListener(window, 'load', initialize);

html,身体,#map_canvas {高度:100%;宽度:100%;边距:0;填充:0;}

<script type="text/javascript" src="http://maps.google.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=geometry"></script><div id="map_canvas"></div>

The idea is to draw an arc centered on a specific point, using angles. Note: Not the chord, nor the sector, nor the area between the chord and the arc.

Memento: http://en.wikipedia.org/wiki/Arc_(geometry)

A full circle parameters:

- center at coordinates LatC,LngC
- radius of 1 609 meters
- start angle of 0 degrees
- end angle of 360 degrees

example http://jsfiddle.net/GGvQH/3/

new google.maps.Circle({
    center: new google.maps.LatLng(18.4894, 73.910158),
    radius: 1609,
    ...
});

An arc of 180° (PI/2 radiant) oriented to north would be like:

 - center at coordinates LatC,LngC
 - radius of 1 609 meters
 - start angle of 270 degrees (9 o'clock)
 - end angle of 90 degrees (3 o'clock)

First of all, I do not want to plot a polyline for each arc, using tons of points to get a smooth effect: need to recompute for each scale and may cost resources... or is it?

There is an idea with polygons intersection Google Maps API v3 - circle sector ...do anyone have seen a working jsfiddle? Note: http://jsfiddle.net/Morlock0821/4dRB2/1/ is very close to the arc, but I do not want a closed surface.

Another idea with bearing... but I am reluctant to redefine the earth's radius to get the tiny arc I want. https://developers.google.com/maps/documentation/javascript/examples/geometry-headings (in this case, I want only the purple line, not the red one).

Any help would be greatly appreciated.

解决方案

This is the code I use in this example:

function drawArc(center, initialBearing, finalBearing, radius) { 
  var d2r = Math.PI / 180;   // degrees to radians 
  var r2d = 180 / Math.PI;   // radians to degrees 

  var points = 32; 

  // find the raidus in lat/lon 
  var rlat = (radius / EarthRadiusMeters) * r2d; 
  var rlng = rlat / Math.cos(center.lat() * d2r); 

  var extp = new Array();

  if (initialBearing > finalBearing) finalBearing += 360;
  var deltaBearing = finalBearing - initialBearing;
  deltaBearing = deltaBearing/points;
  for (var i=0; (i < points+1); i++) 
  { 
    extp.push(center.DestinationPoint(initialBearing + i*deltaBearing, radius)); 
    bounds.extend(extp[extp.length-1]);
  } 
  return extp;
}

Used like this, where startPoint is the start of the arc, endPoint is the end of the arc and centerPoint is the center, but you can specify center, angles and radius.

var arcPts = drawArc(centerPoint, centerPoint.Bearing(startPoint), centerPoint.Bearing(endPoint), centerPoint.distanceFrom(startPoint));


var piePoly = new google.maps.Polygon({
             paths: [arcPts],
             strokeColor: "#00FF00",
             strokeOpacity: 0.5,
             strokeWeight: 2,
             fillColor: "#FF0000",
             fillOpacity: 0.35,
             map: map
 });

Ancillary functions, may no longer be necessary if you include the geometry library

var EarthRadiusMeters = 6378137.0; // meters
/* Based the on the Latitude/longitude spherical geodesy formulae & scripts
   at http://www.movable-type.co.uk/scripts/latlong.html
   (c) Chris Veness 2002-2010
*/ 
google.maps.LatLng.prototype.DestinationPoint = function (brng, dist) {
var R = EarthRadiusMeters; // earth's mean radius in meters
var brng = brng.toRad();
var lat1 = this.lat().toRad(), lon1 = this.lng().toRad();
var lat2 = Math.asin( Math.sin(lat1)*Math.cos(dist/R) + 
                      Math.cos(lat1)*Math.sin(dist/R)*Math.cos(brng) );
var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(dist/R)*Math.cos(lat1), 
                             Math.cos(dist/R)-Math.sin(lat1)*Math.sin(lat2));

return new google.maps.LatLng(lat2.toDeg(), lon2.toDeg());
}

// === A function which returns the bearing between two LatLng in radians ===
// === If v1 is null, it returns the bearing between the first and last vertex ===
// === If v1 is present but v2 is null, returns the bearing from v1 to the next vertex ===
// === If either vertex is out of range, returns void ===
google.maps.LatLng.prototype.Bearing = function(otherLatLng) {
  var from = this;
  var to = otherLatLng;
  if (from.equals(to)) {
    return 0;
  }
  var lat1 = from.latRadians();
  var lon1 = from.lngRadians();
  var lat2 = to.latRadians();
  var lon2 = to.lngRadians();
  var angle = - Math.atan2( Math.sin( lon1 - lon2 ) * Math.cos( lat2 ), Math.cos( lat1 ) * Math.sin( lat2 ) - Math.sin( lat1 ) * Math.cos( lat2 ) * Math.cos( lon1 - lon2 ) );
  if ( angle < 0.0 ) angle  += Math.PI * 2.0;
  if ( angle > Math.PI ) angle -= Math.PI * 2.0; 
  return parseFloat(angle.toDeg());
}


/**
 * Extend the Number object to convert degrees to radians
 *
 * @return {Number} Bearing in radians
 * @ignore
 */ 
Number.prototype.toRad = function () {
  return this * Math.PI / 180;
};

/**
 * Extend the Number object to convert radians to degrees
 *
 * @return {Number} Bearing in degrees
 * @ignore
 */ 
Number.prototype.toDeg = function () {
  return this * 180 / Math.PI;
};

/**
 * Normalize a heading in degrees to between 0 and +360
 *
 * @return {Number} Return 
 * @ignore
 */ 
Number.prototype.toBrng = function () {
  return (this.toDeg() + 360) % 360;
};

code snippet (using geometry library):

var EarthRadiusMeters = 6378137.0; // meters
/* Based the on the Latitude/longitude spherical geodesy formulae & scripts
   at http://www.movable-type.co.uk/scripts/latlong.html
   (c) Chris Veness 2002-2010
*/
google.maps.LatLng.prototype.DestinationPoint = function(brng, dist) {
  var R = EarthRadiusMeters; // earth's mean radius in meters
  var brng = brng.toRad();
  var lat1 = this.lat().toRad(),
    lon1 = this.lng().toRad();
  var lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist / R) +
    Math.cos(lat1) * Math.sin(dist / R) * Math.cos(brng));
  var lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist / R) * Math.cos(lat1),
    Math.cos(dist / R) - Math.sin(lat1) * Math.sin(lat2));

  return new google.maps.LatLng(lat2.toDeg(), lon2.toDeg());
}

/**
 * Extend the Number object to convert degrees to radians
 *
 * @return {Number} Bearing in radians
 * @ignore
 */
Number.prototype.toRad = function() {
  return this * Math.PI / 180;
};

/**
 * Extend the Number object to convert radians to degrees
 *
 * @return {Number} Bearing in degrees
 * @ignore
 */
Number.prototype.toDeg = function() {
  return this * 180 / Math.PI;
};

var infowindow = new google.maps.InfoWindow({
  size: new google.maps.Size(150, 50)
});

function createMarker(latlng, html) {
  var contentString = html;
  var marker = new google.maps.Marker({
    position: latlng,
    map: map,
    zIndex: Math.round(latlng.lat() * -100000) << 5
  });
  bounds.extend(latlng);
  google.maps.event.addListener(marker, 'click', function() {
    infowindow.setContent(contentString);
    infowindow.open(map, marker);
  });
}

function drawArc(center, initialBearing, finalBearing, radius) {
  var d2r = Math.PI / 180; // degrees to radians 
  var r2d = 180 / Math.PI; // radians to degrees 

  var points = 32;

  // find the raidus in lat/lon 
  var rlat = (radius / EarthRadiusMeters) * r2d;
  var rlng = rlat / Math.cos(center.lat() * d2r);

  var extp = new Array();

  if (initialBearing > finalBearing) finalBearing += 360;
  var deltaBearing = finalBearing - initialBearing;
  deltaBearing = deltaBearing / points;
  for (var i = 0;
    (i < points + 1); i++) {
    extp.push(center.DestinationPoint(initialBearing + i * deltaBearing, radius));
    bounds.extend(extp[extp.length - 1]);
  }
  return extp;
}

function drawCircle(point, radius) {
  var d2r = Math.PI / 180; // degrees to radians 
  var r2d = 180 / Math.PI; // radians to degrees 
  var EarthRadiusMeters = 6378137.0; // meters
  var earthsradius = 3963; // 3963 is the radius of the earth in miles

  var points = 32;

  // find the raidus in lat/lon 
  var rlat = (radius / EarthRadiusMeters) * r2d;
  var rlng = rlat / Math.cos(point.lat() * d2r);


  var extp = new Array();
  for (var i = 0; i < points + 1; i++) // one extra here makes sure we connect the 
  {
    var theta = Math.PI * (i / (points / 2));
    ey = point.lng() + (rlng * Math.cos(theta)); // center a + radius x * cos(theta) 
    ex = point.lat() + (rlat * Math.sin(theta)); // center b + radius y * sin(theta) 
    extp.push(new google.maps.LatLng(ex, ey));
    bounds.extend(extp[extp.length - 1]);
  }
  // alert(extp.length);
  return extp;
}

var map = null;
var bounds = null;

function initialize() {
  var myOptions = {
    zoom: 10,
    center: new google.maps.LatLng(-33.9, 151.2),
    mapTypeControl: true,
    mapTypeControlOptions: {
      style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
    },
    navigationControl: true,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  }
  map = new google.maps.Map(document.getElementById("map_canvas"),
    myOptions);

  bounds = new google.maps.LatLngBounds();

  google.maps.event.addListener(map, 'click', function() {
    infowindow.close();
  });

  var startPoint = new google.maps.LatLng(48.610335003092956, -1.6123447775299600);
  var endPoint = new google.maps.LatLng(48.596190206866830, -1.5551704322317228);
  var centerPoint = new google.maps.LatLng(48.565630000000006, -1.6050300000000002);
  createMarker(startPoint, "start: " + startPoint.toUrlValue(6) + "<br>distance to center: " + (google.maps.geometry.spherical.computeDistanceBetween(centerPoint, startPoint) / 1000).toFixed(3) + " km<br>Bearing: " + google.maps.geometry.spherical.computeHeading(centerPoint, startPoint) + "<br><a href='javascript:map.setCenter(new google.maps.LatLng(" + startPoint.toUrlValue(6) + "));map.setZoom(20);'>zoom in</a> - <a href='javascript:map.fitBounds(bounds);'>zoom out</a>");
  createMarker(endPoint, "end: " + endPoint.toUrlValue(6) + "<br>distance to center: " + (google.maps.geometry.spherical.computeDistanceBetween(centerPoint, endPoint) / 1000).toFixed(3) + " km<br>Bearing: " + google.maps.geometry.spherical.computeHeading(centerPoint, endPoint) + "<br><a href='javascript:map.setCenter(new google.maps.LatLng(" + endPoint.toUrlValue(6) + "));map.setZoom(20);'>zoom in</a> - <a href='javascript:map.fitBounds(bounds);'>zoom out</a>");
  createMarker(centerPoint, "center: " + centerPoint.toUrlValue(6));

  var arcPts = drawArc(centerPoint, google.maps.geometry.spherical.computeHeading(centerPoint, startPoint), google.maps.geometry.spherical.computeHeading(centerPoint, endPoint), google.maps.geometry.spherical.computeDistanceBetween(centerPoint, startPoint));
  // add the start and end lines
  arcPts.push(centerPoint);
  bounds.extend(centerPoint);
  arcPts.push(startPoint);

  var piePoly = new google.maps.Polygon({
    paths: [arcPts],
    strokeColor: "#00FF00",
    strokeOpacity: 0.5,
    strokeWeight: 2,
    fillColor: "#FF0000",
    fillOpacity: 0.35,
    map: map
  });

  map.fitBounds(bounds);
}
google.maps.event.addDomListener(window, 'load', initialize);

html,
body,
#map_canvas {
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 0;
}

<script type="text/javascript" src="http://maps.google.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=geometry"></script>
<div id="map_canvas"></div>

这篇关于在谷歌地图上画圆弧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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