绘制圆时如何准确地将米转换为经度或纬度

时间:2016-12-06 10:14:56

标签: javascript geometry gis latitude-longitude

注意:问题不是Leaflet特有的,而是一般的GIS。

我试图在地图上绘制圆弧。我有一个生成多边形点的函数,它可以在画布上工作,但不适用于Lng,Lat地图。

问题在于我无法弄清楚如何将内/外半径从米转换为度(如在lng / lat中),到目前为止我尝试的看起来比椭圆形更像椭圆形。

如何在地球上任何一点(极点除外)准确地将米转换为经度或纬度?

这是我在画布上尝试(工作)的内容。



$(document).ready(function() {
    var d_canvas = document.getElementById('canvas');
    var c2 = d_canvas.getContext('2d');
    c2.fillStyle = '#f00';
    c2.beginPath();
    
    var fromDeg = 0;
    var toDeg = 90;
    var fromRad = getAngle(fromDeg);
    var toRad = getAngle(toDeg);
    var segments = 100;
    var step = getAngle(toDeg-fromDeg)/segments;
    var x = 250;
    var y = 250;
    var outR = 250;
    var inR = 230;
    c2.moveTo(x+(Math.sin(fromRad)*inR),y-(Math.cos(fromRad)*inR));
    //c2.moveTo(x,y);
    for (var i = fromRad; i<=toRad; i=i+step){
    	c2.lineTo(x+(Math.sin(i)*inR),y-(Math.cos(i)*inR));
    }
    //c2.closePath();
    for (var i = toRad; i>=fromRad; i=i-step){
    	c2.lineTo(x+(Math.sin(i)*outR),y-(Math.cos(i)*outR));
    }
    c2.lineTo(x+(Math.sin(fromRad)*inR),y-(Math.cos(fromRad)*inR));
    //c2.closePath();
    c2.stroke();
});

function getAngle(deg){
	var val = 2*(deg/360);
 	return Math.PI*val;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" width="500" height="500"></canvas>
&#13;
&#13;
&#13;

这是我在Leaflet地图上尝试过的(dosn工作得很好)。

&#13;
&#13;
	 	var osmUrl = 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
	 	  osmAttrib = '&copy; <a href="http://openstreetmap.org/copyright">OpenStreetMap</a> contributors',
	 	  osm = L.tileLayer(osmUrl, {
	 	    maxZoom: 18,
	 	    attribution: osmAttrib
	 	  });

	 	 // initialize the map on the "map" div with a given center and zoom
	 	var map = L.map('map').setView([59.56667, 150.80000], 12).addLayer(osm);

	 	 // Script for adding marker on map click
	 	L.polygon(getPolygon()).addTo(map);

	 	function getPolygon() {
	 	  var fromDeg = 0;
	 	  var toDeg = 90;
	 	  var fromRad = getAngle(fromDeg);
	 	  var toRad = getAngle(toDeg);
	 	  var segments = 100;
	 	  var step = getAngle(toDeg - fromDeg) / segments;
	 	  var y = 150.84229;
	 	  var x = 59.55416;
	 	  var outR = 0.05; // <------ should be dynamic?
	 	  var inR = 0.025; // <------ this also?
	 	  var polygon = [];
	 	  polygon.push([x + (Math.sin(fromRad) * inR), y + (Math.cos(fromRad) * inR)]);
	 	  for (var i = fromRad; i <= toRad; i = i + step) {
	 	    polygon.push([x + (Math.sin(i) * inR), y + (Math.cos(i) * inR)]);
	 	  }
	 	  //c2.closePath();
	 	  for (var i = toRad; i >= fromRad; i = i - step) {
	 	    polygon.push([x + (Math.sin(i) * outR), y + (Math.cos(i) * outR)]);
	 	  }
	 	  polygon.push([x + (Math.sin(fromRad) * inR), y + (Math.cos(fromRad) * inR)]);
	 	  return polygon;
	 	}

	 	function getAngle(deg) {
	 	  var val = 2 * (deg / 360);
	 	  return Math.PI * val;
	 	}
&#13;
#map {
  height: 500px;
  width: 80%;
}
&#13;
<script src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script>
<link href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css" rel="stylesheet" />
<script src="http://unpkg.com/leaflet-arc/bin/leaflet-arc.min.js"></script>
<div id="map"></div>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:4)

所以你原来的问题是

  

如何在地球上的任何一点(极点除外)准确地将米转换为经度或纬度?

但我的大脑将其视为

  

给定[lat, lng]点和距离d(以米为单位),如何计算距离第一个点[lat2, lng2]米的第二个d点?

如果你知道一些GIS行话,那就和问

一样
  

如何解决direct geodesic problem

答案涉及数学概念,如椭圆体和大圆圈。

但鉴于您正在使用Javascript和Leaflet,我将跳转到实际实现。

如果您需要超精确的答案,您需要查看the JS implementation of GeographicLib及其解决直接测地问题的方法。

如果你真的不关心准确性(特别是不关心极点的准确性),你想看看cheap-ruler,特别是它的destination(p, dist, bearing)方法。

还有更多的解决方案,比如使用以点为中心的等距地图投影,或者测地线问题的其他一些实现,或者某些turf.js技巧,或者用类似的方法在JS之外创建几何图形,或者其他什么

此问题已经解决,因此我建议使用任何现有解决方案。

答案 1 :(得分:1)

这解决了问题

&#13;
&#13;
	 	var osmUrl = 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
	 	  osmAttrib = '&copy; <a href="http://openstreetmap.org/copyright">OpenStreetMap</a> contributors',
	 	  osm = L.tileLayer(osmUrl, {
	 	    maxZoom: 18,
	 	    attribution: osmAttrib
	 	  });

	 	// initialize the map on the "map" div with a given center and zoom
	 	var map = L.map('map').setView([59.56667, 150.80000], 12).addLayer(osm);

	 	// Script for adding marker on map click
	 	L.polygon(getPolygon()).addTo(map);

	 	function getPolygon() {
	 	  var fromDeg = 0;
	 	  var toDeg = 120;
	 	  var lat = 59.56667;
	 	  var lon = 150.80000;
	 	  var outR = 200;
	 	  var inR = 180;
	 	  var polygon = [];
	 	  for (var i = fromDeg; i <= toDeg; i++) {
	 	    polygon.push(getPoint(lat, lon, inR, i));
	 	  }
	 	  for (var i = toDeg; i >= fromDeg; i--) {
	 	    polygon.push(getPoint(lat, lon, outR, i));
	 	  }
	 	  polygon.push(getPoint(lat, lon, inR, fromDeg));
	 	  return polygon;
	 	}
        /*************************
        * The solution
        *************************/
	 	function getPoint(lat, lon, r, deg) {
	 	  lat2 = (r / 111230) * Math.cos(deg2rad(deg));
	 	  lat2 += lat;
	 	  lon2 = (r / 111230) * Math.sin(deg2rad(deg));
	 	  lon2 = lon2 * (1 / Math.cos(deg2rad(lat2)));
	 	  lon2 += lon;
	 	  return [lat2, lon2];
	 	}

	 	function deg2rad(deg) {
	 	  return deg * (Math.PI / 180);
	 	}
&#13;
#map {
  height: 500px;
  width: 80%;
}
&#13;
<link href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css" rel="stylesheet"/>
<script src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script>
<div id="map"></div>
&#13;
&#13;
&#13;