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!
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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With