Google 地图 V3 几何库 - 插值不返回预期的纬度/经度

发布于 2024-12-07 22:59:40 字数 2439 浏览 1 评论 0原文

我花了几个小时研究谷歌地图几何库的插值函数的一个奇怪问题。 (请参阅:http://code.google.com/apis/地图/文档/javascript/reference.html#spherical) 我使用以下 javascript 代码来说明问题:

// be sure to include: https://maps.googleapis.com/maps/api/js?libraries=geometry&sensor=false

// this works just as expected

var origin = new google.maps.LatLng(47.45732443, 8.570993570000041);
var destination = new google.maps.LatLng(47.45733, 8.570889999999963);
var distance = google.maps.geometry.spherical.computeDistanceBetween(origin, destination);

console.log("origin:\r\nlat: " + origin.lat() + ", lng: " + origin.lng());
console.log("destination:\r\nlat: " + destination.lat() + ", lng: " + destination.lng());
console.log("distance between origin and destination: " + distance);

console.log("interpolating 50 equal segments between origin and destination");
for (i=1; i <= 50; i++) {
    var step = (1/50);
    var interpolated = google.maps.geometry.spherical.interpolate(origin, destination, step * i);
    var distance = google.maps.geometry.spherical.computeDistanceBetween(origin, interpolated);

    console.log("lat: " + interpolated.lat() + ", lng: " + interpolated.lng() + ", dist: " + distance);
}

// the following does not work as expected
// the "interpolated" location is always equal to the origin

var origin = new google.maps.LatLng(47.45756, 8.572350000000029);
var destination = new google.maps.LatLng(47.45753, 8.57233999999994);
var distance = google.maps.geometry.spherical.computeDistanceBetween(origin, destination);

console.log("origin:\r\nlat: " + origin.lat() + ", lng: " + origin.lng());
console.log("destination:\r\nlat: " + destination.lat() + ", lng: " + destination.lng());
console.log("distance between origin and destination: " + distance);

console.log("interpolating 50 equal segments between origin and destination");
for (i=1; i <= 50; i++) {
    var step = (1/50);
    var interpolated = google.maps.geometry.spherical.interpolate(origin, destination, step * i);
    var distance = google.maps.geometry.spherical.computeDistanceBetween(origin, interpolated);

    console.log("lat: " + interpolated.lat() + ", lng: " + interpolated.lng() + ", dist: " + distance);
}

插值函数似乎不喜欢第二组纬度/经度对。它始终返回原点纬度/经度,而不是基于传递的分数 (1/50 * i) 的正确插值位置。

我尝试颠倒出发地和目的地,但结果是一样的。

任何关于我做错了什么的想法都非常感谢!

I have spent hours on a strange problem with the interpolate function of google maps' geometry library. (see: http://code.google.com/apis/maps/documentation/javascript/reference.html#spherical)
I use the following javascript code to illustrate the problem:

// be sure to include: https://maps.googleapis.com/maps/api/js?libraries=geometry&sensor=false

// this works just as expected

var origin = new google.maps.LatLng(47.45732443, 8.570993570000041);
var destination = new google.maps.LatLng(47.45733, 8.570889999999963);
var distance = google.maps.geometry.spherical.computeDistanceBetween(origin, destination);

console.log("origin:\r\nlat: " + origin.lat() + ", lng: " + origin.lng());
console.log("destination:\r\nlat: " + destination.lat() + ", lng: " + destination.lng());
console.log("distance between origin and destination: " + distance);

console.log("interpolating 50 equal segments between origin and destination");
for (i=1; i <= 50; i++) {
    var step = (1/50);
    var interpolated = google.maps.geometry.spherical.interpolate(origin, destination, step * i);
    var distance = google.maps.geometry.spherical.computeDistanceBetween(origin, interpolated);

    console.log("lat: " + interpolated.lat() + ", lng: " + interpolated.lng() + ", dist: " + distance);
}

// the following does not work as expected
// the "interpolated" location is always equal to the origin

var origin = new google.maps.LatLng(47.45756, 8.572350000000029);
var destination = new google.maps.LatLng(47.45753, 8.57233999999994);
var distance = google.maps.geometry.spherical.computeDistanceBetween(origin, destination);

console.log("origin:\r\nlat: " + origin.lat() + ", lng: " + origin.lng());
console.log("destination:\r\nlat: " + destination.lat() + ", lng: " + destination.lng());
console.log("distance between origin and destination: " + distance);

console.log("interpolating 50 equal segments between origin and destination");
for (i=1; i <= 50; i++) {
    var step = (1/50);
    var interpolated = google.maps.geometry.spherical.interpolate(origin, destination, step * i);
    var distance = google.maps.geometry.spherical.computeDistanceBetween(origin, interpolated);

    console.log("lat: " + interpolated.lat() + ", lng: " + interpolated.lng() + ", dist: " + distance);
}

It appears that the interpolate function does NOT like the second set of lat/lng pairs. It always returns the origin lat/lng rather than the correctly interpolated location based on the fraction passed (1/50 * i).

I tried reversing origin and destination, but the outcome is the same.

Any ideas as to what I'm doing wrong are much appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

极度宠爱 2024-12-14 22:59:41

我已提交有关此问题的问题:

https://issuetracker.google.com/issues/260343763

对我来说,问题是我正在使用这个函数来插入动画。我最终将该函数复制到我自己的源代码中,并删除了检查“r<1.0E-6”的 if 语句(正如 @davethebrave 所指出的)

I have filed an issue concerning this problem:

https://issuetracker.google.com/issues/260343763

For me the problem was that I am using this function to interpolate an animation. I ended up copying the function into my own source code and removing the if statement that checks for "r<1.0E-6" (as @davethebrave has pointed out)

卷耳 2024-12-14 22:59:40

事实证明,插值函数有一个内置限制,指定两点之间的距离必须大于 1.0E-6。

function (a,b,c){
var d=L(a.Ja),e=L(a.Ka),f=L(b.Ja),g=L(b.Ka),h=n.cos(d),o=n.cos(f),b=zx.se(a,b),r=n.sin(b);

// here lies the problem:
if(r<1.0E-6)return new Q(a.lat(),a.lng());

a=n.sin((1-c)*b)/r;
c=n.sin(c*b)/r;
b=a*h*n.cos(e)+c*o*n.cos(g);
e=a*h*n.sin(e)+c*o*n.sin(g);
return new Q(Fd(n[zb](a*n.sin(d)+c*n.sin(f),n[Db](b*b+e*e))),Fd(n[zb](e,b)))
}

这对我来说仍然有点神秘,因为 1.0E-6 应该是 0.000001,而不是我测试中的 6.0。也许这是一个仅在使用 google.maps.gjsload 时才会出现的错误?我将进行更多测试并评论我的发现。

我通过简单地注释掉 if 语句来解决这个问题:

google.maps.__gjsload__('geometry', 'var zx={computeHeading:function(a,b){var c=L(a.Ja),d=L(b.Ja),e=L(b.Ka)-L(a.Ka);return Dd(Fd(n[zb](n.sin(e)*n.cos(d),n.cos(c)*n.sin(d)-n.sin(c)*n.cos(d)*n.cos(e))),-180,180)},computeOffset:function(a,b,c,d){b/=d||6378137;var c=L(c),e=L(a.Ja),d=n.cos(b),b=n.sin(b),f=n.sin(e),e=n.cos(e),g=d*f+b*e*n.cos(c);return new Q(Fd(n[Dc](g)),Fd(L(a.Ka)+n[zb](b*e*n.sin(c),d-f*g)))},interpolate:function(a,b,c){var d=L(a.Ja),e=L(a.Ka),f=L(b.Ja),g=L(b.Ka),h=n.cos(d),o=n.cos(f),b=zx.se(a,b),r=n.sin(b);/*if(r<1.0E-6)return new Q(a.lat(),\na.lng());*/a=n.sin((1-c)*b)/r;c=n.sin(c*b)/r;b=a*h*n.cos(e)+c*o*n.cos(g);e=a*h*n.sin(e)+c*o*n.sin(g);return new Q(Fd(n[zb](a*n.sin(d)+c*n.sin(f),n[Db](b*b+e*e))),Fd(n[zb](e,b)))},se:function(a,b){var c=L(a.Ja),d=L(b.Ja);return 2*n[Dc](n[Db](n.pow(n.sin((c-d)/2),2)+n.cos(c)*n.cos(d)*n.pow(n.sin((L(a.Ka)-L(b.Ka))/2),2)))}};zx.computeDistanceBetween=function(a,b,c){return zx.se(a,b)*(c||6378137)};\nzx.computeLength=function(a,b){var c=b||6378137,d=0;a instanceof Lf&&(a=a[tc]());for(var e=0,f=a[B]-1;e<f;++e)d+=zx.computeDistanceBetween(a[e],a[e+1],c);return d};zx.computeArea=function(a,b){return n.abs(zx.computeSignedArea(a,b))};zx.computeSignedArea=function(a,b){var c=b||6378137;a instanceof Lf&&(a=a[tc]());for(var d=a[0],e=0,f=1,g=a[B]-1;f<g;++f)e+=zx.Hj(d,a[f],a[f+1]);return e*c*c};zx.Hj=function(a,b,c){return zx.xj(a,b,c)*zx.yj(a,b,c)};\nzx.xj=function(a,b,c){for(var d=[a,b,c,a],a=[],c=b=0;c<3;++c)a[c]=zx.se(d[c],d[c+1]),b+=a[c];b/=2;d=n.tan(b/2);for(c=0;c<3;++c)d*=n.tan((b-a[c])/2);return 4*n[pc](n[Db](n.abs(d)))};zx.yj=function(a,b,c){a=[a,b,c];b=[];for(c=0;c<3;++c){var d=a[c],e=L(d.Ja),d=L(d.Ka),f=b[c]=[];f[0]=n.cos(e)*n.cos(d);f[1]=n.cos(e)*n.sin(d);f[2]=n.sin(e)}return b[0][0]*b[1][1]*b[2][2]+b[1][0]*b[2][1]*b[0][2]+b[2][0]*b[0][1]*b[1][2]-b[0][0]*b[2][1]*b[1][2]-b[1][0]*b[0][1]*b[2][2]-b[2][0]*b[1][1]*b[0][2]>0?1:-1};var Ax={decodePath:function(a){for(var b=J(a),c=ga(n[jb](a[B]/2)),d=0,e=0,f=0,g=0;d<b;++g){var h=1,o=0,r;do r=a[sc](d++)-63-1,h+=r<<o,o+=5;while(r>=31);e+=h&1?~(h>>1):h>>1;h=1;o=0;do r=a[sc](d++)-63-1,h+=r<<o,o+=5;while(r>=31);f+=h&1?~(h>>1):h>>1;c[g]=new Q(e*1.0E-5,f*1.0E-5,i)}Ma(c,g);return c}};Ax.encodePath=function(a){a instanceof Lf&&(a=a[tc]());return Ax.Lj(a,function(a){return[rd(a.lat()*1E5),rd(a.lng()*1E5)]})};\nAx.Lj=function(a,b){for(var c=[],d=[0,0],e,f=0,g=J(a);f<g;++f)e=b?b(a[f]):a[f],Ax.mg(e[0]-d[0],c),Ax.mg(e[1]-d[1],c),d=e;return c[Hc]("")};Ax.$j=function(a){for(var b=J(a),c=ga(b),d=0;d<b;++d)c[d]=a[sc](d)-63;return c};Ax.mg=function(a,b){Ax.Mj(a<0?~(a<<1):a<<1,b)};Ax.Mj=function(a,b){for(;a>=32;)b[p](na.fromCharCode((32|a&31)+63)),a>>=5;b[p](na.fromCharCode(a+63))};function Bx(){}Bx[C].Jb=Ax;Bx[C].computeDistanceBetween=zx.computeDistanceBetween;var Cx=new Bx;df[se]=function(a){eval(a)};l.google.maps[se]={encoding:Ax,spherical:zx};gf(se,Cx);\n')

我希望这能帮助其他遇到同样问题的人。

As it turns out, the interpolate function has a built in limitation that specifies that the distance between the two points must be larger than 1.0E-6.

function (a,b,c){
var d=L(a.Ja),e=L(a.Ka),f=L(b.Ja),g=L(b.Ka),h=n.cos(d),o=n.cos(f),b=zx.se(a,b),r=n.sin(b);

// here lies the problem:
if(r<1.0E-6)return new Q(a.lat(),a.lng());

a=n.sin((1-c)*b)/r;
c=n.sin(c*b)/r;
b=a*h*n.cos(e)+c*o*n.cos(g);
e=a*h*n.sin(e)+c*o*n.sin(g);
return new Q(Fd(n[zb](a*n.sin(d)+c*n.sin(f),n[Db](b*b+e*e))),Fd(n[zb](e,b)))
}

This is still somewhat a mystery to me, as 1.0E-6 should be 0.000001 and not 6.0 as it is in my tests. Perhaps this is a bug that only shows when using google.maps.gjsload? I'll test a bit more and comment on my findings.

I got around this by simply commenting out the if statement:

google.maps.__gjsload__('geometry', 'var zx={computeHeading:function(a,b){var c=L(a.Ja),d=L(b.Ja),e=L(b.Ka)-L(a.Ka);return Dd(Fd(n[zb](n.sin(e)*n.cos(d),n.cos(c)*n.sin(d)-n.sin(c)*n.cos(d)*n.cos(e))),-180,180)},computeOffset:function(a,b,c,d){b/=d||6378137;var c=L(c),e=L(a.Ja),d=n.cos(b),b=n.sin(b),f=n.sin(e),e=n.cos(e),g=d*f+b*e*n.cos(c);return new Q(Fd(n[Dc](g)),Fd(L(a.Ka)+n[zb](b*e*n.sin(c),d-f*g)))},interpolate:function(a,b,c){var d=L(a.Ja),e=L(a.Ka),f=L(b.Ja),g=L(b.Ka),h=n.cos(d),o=n.cos(f),b=zx.se(a,b),r=n.sin(b);/*if(r<1.0E-6)return new Q(a.lat(),\na.lng());*/a=n.sin((1-c)*b)/r;c=n.sin(c*b)/r;b=a*h*n.cos(e)+c*o*n.cos(g);e=a*h*n.sin(e)+c*o*n.sin(g);return new Q(Fd(n[zb](a*n.sin(d)+c*n.sin(f),n[Db](b*b+e*e))),Fd(n[zb](e,b)))},se:function(a,b){var c=L(a.Ja),d=L(b.Ja);return 2*n[Dc](n[Db](n.pow(n.sin((c-d)/2),2)+n.cos(c)*n.cos(d)*n.pow(n.sin((L(a.Ka)-L(b.Ka))/2),2)))}};zx.computeDistanceBetween=function(a,b,c){return zx.se(a,b)*(c||6378137)};\nzx.computeLength=function(a,b){var c=b||6378137,d=0;a instanceof Lf&&(a=a[tc]());for(var e=0,f=a[B]-1;e<f;++e)d+=zx.computeDistanceBetween(a[e],a[e+1],c);return d};zx.computeArea=function(a,b){return n.abs(zx.computeSignedArea(a,b))};zx.computeSignedArea=function(a,b){var c=b||6378137;a instanceof Lf&&(a=a[tc]());for(var d=a[0],e=0,f=1,g=a[B]-1;f<g;++f)e+=zx.Hj(d,a[f],a[f+1]);return e*c*c};zx.Hj=function(a,b,c){return zx.xj(a,b,c)*zx.yj(a,b,c)};\nzx.xj=function(a,b,c){for(var d=[a,b,c,a],a=[],c=b=0;c<3;++c)a[c]=zx.se(d[c],d[c+1]),b+=a[c];b/=2;d=n.tan(b/2);for(c=0;c<3;++c)d*=n.tan((b-a[c])/2);return 4*n[pc](n[Db](n.abs(d)))};zx.yj=function(a,b,c){a=[a,b,c];b=[];for(c=0;c<3;++c){var d=a[c],e=L(d.Ja),d=L(d.Ka),f=b[c]=[];f[0]=n.cos(e)*n.cos(d);f[1]=n.cos(e)*n.sin(d);f[2]=n.sin(e)}return b[0][0]*b[1][1]*b[2][2]+b[1][0]*b[2][1]*b[0][2]+b[2][0]*b[0][1]*b[1][2]-b[0][0]*b[2][1]*b[1][2]-b[1][0]*b[0][1]*b[2][2]-b[2][0]*b[1][1]*b[0][2]>0?1:-1};var Ax={decodePath:function(a){for(var b=J(a),c=ga(n[jb](a[B]/2)),d=0,e=0,f=0,g=0;d<b;++g){var h=1,o=0,r;do r=a[sc](d++)-63-1,h+=r<<o,o+=5;while(r>=31);e+=h&1?~(h>>1):h>>1;h=1;o=0;do r=a[sc](d++)-63-1,h+=r<<o,o+=5;while(r>=31);f+=h&1?~(h>>1):h>>1;c[g]=new Q(e*1.0E-5,f*1.0E-5,i)}Ma(c,g);return c}};Ax.encodePath=function(a){a instanceof Lf&&(a=a[tc]());return Ax.Lj(a,function(a){return[rd(a.lat()*1E5),rd(a.lng()*1E5)]})};\nAx.Lj=function(a,b){for(var c=[],d=[0,0],e,f=0,g=J(a);f<g;++f)e=b?b(a[f]):a[f],Ax.mg(e[0]-d[0],c),Ax.mg(e[1]-d[1],c),d=e;return c[Hc]("")};Ax.$j=function(a){for(var b=J(a),c=ga(b),d=0;d<b;++d)c[d]=a[sc](d)-63;return c};Ax.mg=function(a,b){Ax.Mj(a<0?~(a<<1):a<<1,b)};Ax.Mj=function(a,b){for(;a>=32;)b[p](na.fromCharCode((32|a&31)+63)),a>>=5;b[p](na.fromCharCode(a+63))};function Bx(){}Bx[C].Jb=Ax;Bx[C].computeDistanceBetween=zx.computeDistanceBetween;var Cx=new Bx;df[se]=function(a){eval(a)};l.google.maps[se]={encoding:Ax,spherical:zx};gf(se,Cx);\n')

I hope this will help someone else out there running into the same problem.

回心转意 2024-12-14 22:59:40

我认为您对插值的准确性期望过高。纬度差异为47.45756 - 47.45753 = 0.00003 度 ~ 3.3 米。经度差异为 8.57235- 8.57234 = 0.00001 deg ~ 0.5 米(非常近似,请参见 维基百科)。现在,您将近似欧几里得距离 3m 划分为 50 个间隔,查找距离 ca 的点。 6 厘米。将此与长度约为 4,003,020,000 厘米的地球赤道进行比较。

I think you expect too much accuracy from the interpolation. The difference in the latitudes is 47.45756 - 47.45753 = 0.00003 deg ~ 3.3 meter. The difference in the longitudes is 8.57235- 8.57234 = 0.00001 deg ~ 0.5 meter (very appoximatively, see Wikipedia). Now you divide the approximative Euclidean distance 3m into 50 intervals, looking for points at a distance of ca. 6 cm. Compare this with the Earth equator whose length is about 4,003,020,000 cm.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文