在 openlayers 5 中创建大圆
Create great circle in openlayers 5
我需要创建一个 X 半径的圆,以米为单位,考虑到地球的曲率。
回到 OpenLayers 2,我们有 destinationVincenty
,这有助于从一个点计算目的地,同时考虑角度。
然而,这似乎在 OpenLayers 5 中缺失。
我已经测试了 Cricle
几何形状,但它太不精确了(检查图像)。
如何在 OpenLayers 5 中执行此操作?
蓝色圆圈画的是245公里半径,但实际的245公里半径应该一直延伸到Sedalia附近的红线附近。
如果您需要 destinationVincenty 函数,很容易从 OL2 源中复制。
我已经添加了 3 个明显的依赖项并将输入 lonlat 和 return 值更改为 OL3/4/5 类型坐标数组,但还没有测试任何东西。
destinationVincenty = function(lonlat, brng, dist) {
//var u = OpenLayers.Util;
var u = {};
u.rad = function(x) {return x*Math.PI/180;};
u.deg = function(x) {return x*180/Math.PI;};
u.VincentyConstants = {
a: 6378137,
b: 6356752.3142,
f: 1/298.257223563
};
var ct = u.VincentyConstants;
var a = ct.a, b = ct.b, f = ct.f;
var lon1 = lonlat[0]; //lonlat.lon;
var lat1 = lonlat[1]; //lonlat.lat;
var s = dist;
var alpha1 = u.rad(brng);
var sinAlpha1 = Math.sin(alpha1);
var cosAlpha1 = Math.cos(alpha1);
var tanU1 = (1-f) * Math.tan(u.rad(lat1));
var cosU1 = 1 / Math.sqrt((1 + tanU1*tanU1)), sinU1 = tanU1*cosU1;
var sigma1 = Math.atan2(tanU1, cosAlpha1);
var sinAlpha = cosU1 * sinAlpha1;
var cosSqAlpha = 1 - sinAlpha*sinAlpha;
var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
var sigma = s / (b*A), sigmaP = 2*Math.PI;
while (Math.abs(sigma-sigmaP) > 1e-12) {
var cos2SigmaM = Math.cos(2*sigma1 + sigma);
var sinSigma = Math.sin(sigma);
var cosSigma = Math.cos(sigma);
var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
sigmaP = sigma;
sigma = s / (b*A) + deltaSigma;
}
var tmp = sinU1*sinSigma - cosU1*cosSigma*cosAlpha1;
var lat2 = Math.atan2(sinU1*cosSigma + cosU1*sinSigma*cosAlpha1,
(1-f)*Math.sqrt(sinAlpha*sinAlpha + tmp*tmp));
var lambda = Math.atan2(sinSigma*sinAlpha1, cosU1*cosSigma - sinU1*sinSigma*cosAlpha1);
var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
var L = lambda - (1-C) * f * sinAlpha *
(sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
var revAz = Math.atan2(sinAlpha, -tmp); // final bearing
//return new OpenLayers.LonLat(lon1+u.deg(L), u.deg(lat2));
return [lon1+u.deg(L), u.deg(lat2)];
};
最接近的可用方法是 OL3/4/5 是 ol.geom.Polygon.circular()
我需要创建一个 X 半径的圆,以米为单位,考虑到地球的曲率。
回到 OpenLayers 2,我们有 destinationVincenty
,这有助于从一个点计算目的地,同时考虑角度。
然而,这似乎在 OpenLayers 5 中缺失。
我已经测试了 Cricle
几何形状,但它太不精确了(检查图像)。
如何在 OpenLayers 5 中执行此操作?
蓝色圆圈画的是245公里半径,但实际的245公里半径应该一直延伸到Sedalia附近的红线附近。
如果您需要 destinationVincenty 函数,很容易从 OL2 源中复制。 我已经添加了 3 个明显的依赖项并将输入 lonlat 和 return 值更改为 OL3/4/5 类型坐标数组,但还没有测试任何东西。
destinationVincenty = function(lonlat, brng, dist) {
//var u = OpenLayers.Util;
var u = {};
u.rad = function(x) {return x*Math.PI/180;};
u.deg = function(x) {return x*180/Math.PI;};
u.VincentyConstants = {
a: 6378137,
b: 6356752.3142,
f: 1/298.257223563
};
var ct = u.VincentyConstants;
var a = ct.a, b = ct.b, f = ct.f;
var lon1 = lonlat[0]; //lonlat.lon;
var lat1 = lonlat[1]; //lonlat.lat;
var s = dist;
var alpha1 = u.rad(brng);
var sinAlpha1 = Math.sin(alpha1);
var cosAlpha1 = Math.cos(alpha1);
var tanU1 = (1-f) * Math.tan(u.rad(lat1));
var cosU1 = 1 / Math.sqrt((1 + tanU1*tanU1)), sinU1 = tanU1*cosU1;
var sigma1 = Math.atan2(tanU1, cosAlpha1);
var sinAlpha = cosU1 * sinAlpha1;
var cosSqAlpha = 1 - sinAlpha*sinAlpha;
var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
var sigma = s / (b*A), sigmaP = 2*Math.PI;
while (Math.abs(sigma-sigmaP) > 1e-12) {
var cos2SigmaM = Math.cos(2*sigma1 + sigma);
var sinSigma = Math.sin(sigma);
var cosSigma = Math.cos(sigma);
var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
sigmaP = sigma;
sigma = s / (b*A) + deltaSigma;
}
var tmp = sinU1*sinSigma - cosU1*cosSigma*cosAlpha1;
var lat2 = Math.atan2(sinU1*cosSigma + cosU1*sinSigma*cosAlpha1,
(1-f)*Math.sqrt(sinAlpha*sinAlpha + tmp*tmp));
var lambda = Math.atan2(sinSigma*sinAlpha1, cosU1*cosSigma - sinU1*sinSigma*cosAlpha1);
var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
var L = lambda - (1-C) * f * sinAlpha *
(sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
var revAz = Math.atan2(sinAlpha, -tmp); // final bearing
//return new OpenLayers.LonLat(lon1+u.deg(L), u.deg(lat2));
return [lon1+u.deg(L), u.deg(lat2)];
};
最接近的可用方法是 OL3/4/5 是 ol.geom.Polygon.circular()