参数方程放置传单上的标记圆的周长是不是precise?传单、方程、标记、参数

2023-09-11 04:33:13 作者:莪是妳的無関痛痒

我工作的一个应用程序,我有一个圆圈,半径的中心,我策划与宣传单的帮助下圆。

I am working on an application where I have the center of a circle and the radius and I am plotting the circle with the help of Leaflet.

我放在北部的一个标志物周围的最末尾,并使其可拖动。

I placed a marker on the north most end of the circumference and made it draggable.

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);

现在,这增加了标记的圆周,现在我想它是只可拖动圆周上的本身,我用的参数方程。

Now, this adds the marker to the circumference and now I wanted it to be draggable only on the circumference itself for which I used the parametric equation.

参数方程

x = Xc + R * cos(theta)
y = Yc + R * sin(theta)

$ C $下拖

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]);
});

bearingTo 方法:

The bearingTo method:

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;
};

问题

当我开始拖动标记,这code是工作的罚款,并把它带回给围在处标记拖动到轴承。但有一个问题,在圆周上的COORDS稍微偏离和经度的条款。当轴承为0(北),所述的coords是完美的,但是当它是90(东),经度是略少,它应用于上述标志是在圆周

When I start dragging the marker, this code is working fine and brings it back to the circumference at the bearing at which the marker is dragged to. But there is one problem, the coords on the circumference are slightly off and in terms of longitude. When the bearing is 0 (north), the coords are perfect, but when it is 90 (east), the longitude is slightly less that it should for the marker to be at the circumference.

再在180(南),COORDS是完美的,但在270(西),计算经度略少和标记趋于半径了。

Again at 180 (south), coords are perfect, but at 270 (west), the longitude calculated is slightly less and the marker tends towards the radius again.

因此​​,基本上,如果你想象的标记被拖动,它开始完美的北端,并开始传来的圆圈内略有增加与轴承,直到它reacher 90,然后开始将逐步转向圆周再次到180时,它是完美的再次

So basically if you visualize the marker being dragged, it starts perfectly on the north end and starts coming inside the circle slightly increasing with the bearing till it reacher 90 and then starts going towards the circumference again till 180 when it is perfect again.

它形成更像是一个椭圆,如果你得到它的要点。

It forms more like a ellipse if you get the gist of it.

谁能告诉我,为什么是经度即将有点过,为什么在一个椭圆形的路径移动游标。有它是与世界坐标和窗口坐标。或者是我的公式稍微偏离的地方?

Could anyone tell me why is longitude coming a little off and why the marker moves in an elliptical path. Has it something to do with the world coordinates and window coordinates. Or are my equations slightly off somewhere?

推荐答案

它看起来像一个突出的问题。在您拖动code你基本上是在做

It does look like a projection issue. In your dragging code you are basically doing

 lat = a + r cos(baring)
 long = b + r sin(baring)

在纬度龙坐标给出了一圈。这将正常工作,如果你在用墨卡托投影赤道。你会得到更多的失真你走向投票站继续移动。

giving a circle in the Lat-Long coordinates. This would work fine if you were at the equator with Mercator projection. You will get more distortion as you move further towards the polls.

假设你使用的是默认传单参考文档你有EPSG3857 网络墨卡托的坐标。

Assume you are using the defaults for Leaflet reference doc You have the EPSG3857 Web Mercator coordinates.

。你可以得到这些在 ICRS 对象使用的方法。首先得到坐标系 L.CRS.EPSG3857 并使用 latLngToPoint pointToLatLng 的方法。

If you want to ensure you have a exact circle it will be better to work using screen coordinates. You can get these using methods on the ICRS objects. First get the coordinate system L.CRS.EPSG3857 and use the latLngToPoint and pointToLatLng methods.

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);
});