Roh*_*han 7 javascript algorithm math leaflet mapbox
我正在开发一个应用程序,我有一个圆心和半径,我在Leaflet的帮助下绘制圆圈.
我在圆周的最北端放置了一个标记,使其可以拖动.
var circle = L.circle(coords, radius).addTo(map);
convertRadiusToLatitude = parseInt(response.radius)/111111;
var coordsOnRadius = [parseFloat(response.lat) + convertRadiusToLatitude, parseFloat(response.long)];
var markerOnRadius = L.marker(coordsOnRadius, {draggable: true}).addTo(map);
Run Code Online (Sandbox Code Playgroud)
现在,这将标记添加到圆周,现在我希望它只能在我使用参数方程的圆周上拖动.
参数方程
x = Xc + R * cos(theta)
y = Yc + R * sin(theta)
Run Code Online (Sandbox Code Playgroud)
拖动代码
markerOnRadius.on('drag', function(e){
bearing = marker.getLatLng().bearingTo(markerOnRadius.getLatLng());
var markerOnRadiusX = parseFloat(response.lat) + ((0.000009 * parseFloat(response.radius)) * Math.cos( toRad(bearing) ));
var markerOnRadiusY = parseFloat(response.long) + ((0.000009 * parseFloat(response.radius)) * Math.sin( toRad(bearing) ));
markerOnRadius.setLatLng([markerOnRadiusX, markerOnRadiusY]);
});
Run Code Online (Sandbox Code Playgroud)
该bearingTo方法:
L.LatLng.prototype.bearingTo = function(other) {
var d2r = L.LatLng.DEG_TO_RAD;
var r2d = L.LatLng.RAD_TO_DEG;
var lat1 = this.lat * d2r;
var lat2 = other.lat * d2r;
var dLon = (other.lng-this.lng) * d2r;
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
var brng = Math.atan2(y, x);
brng = parseInt( brng * r2d );
brng = (brng + 360) % 360;
return brng;
};
Run Code Online (Sandbox Code Playgroud)
问题
当我开始拖动标记时,此代码工作正常并将其拖回到拖动标记的方位的圆周上.但是存在一个问题,圆周上的坐标略微偏离并且就经度而言.当轴承为0(北)时,坐标是完美的,但是当它为90(东)时,经度略小于标记在圆周上的经度.
同样在180(南),坐标是完美的,但在270(西),计算的经度略小,标记再次朝向半径.
因此,基本上如果您想象拖动的标记,它会在北端完美地开始并开始进入圆圈内部,随着轴承略微增加直到它达到90,然后再次开始朝向圆周再次到达圆周时再次完美.
如果你得到它的要点,它就更像椭圆形.





任何人都可以告诉我为什么经度有点偏离以及为什么标记在椭圆形路径中移动.它与世界坐标和窗口坐标有关.或者我的方程式稍微偏离某个地方?
它看起来确实是一个投影问题。在你的拖动代码中你基本上是在做
lat = a + r cos(baring)
long = b + r sin(baring)
Run Code Online (Sandbox Code Playgroud)
在经纬度坐标中给出一个圆。如果您使用墨卡托投影位于赤道,这会很好地工作。当你进一步接近民意调查时,你会得到更多的扭曲。
假设您使用的是 Leaflet参考文档的默认值您有 EPSG3857 Web 墨卡托坐标。
如果您想确保有一个精确的圆,最好使用屏幕坐标。您可以使用ICRS对象上的方法获取这些内容。首先获取坐标系L.CRS.EPSG3857并使用latLngToPoint和pointToLatLng方法。
var crs = L.CRS.EPSG3857;
var zoom = ...; // how you calculate your zoom factor
markerOnRadius.on('drag', function(e){
var markerLL = marker.getLatLng()
var morLL = markerOnRadius.getLatLng();
var markerP = crs.latLngToPoint(markerLL,zoom);
var morP = crs.latLngToPoint(morLL,zoom);
// get the distance between the two points
var dist = markerP.distanceTo(morP);
// Get the vector from center to point
var A = morP.subtract(markerP);
// scale so its of the desired length
var B = A. multiplyBy( factor / dist);
// Add on the center
var C = markerP.add(B);
// Convert back to LatLong
var D = crs.pointToLatLng(C,zoom);
markerOnRadius.setLatLong(D);
});
Run Code Online (Sandbox Code Playgroud)