10 lines
9.5 KiB
JavaScript
10 lines
9.5 KiB
JavaScript
/*! geolib 1.3.5 by Manuel Bieh
|
|
* A growing library to provide some basic geo functions like distance calculation,
|
|
* conversion of decimal coordinates to sexagesimal and vice versa, etc.
|
|
* WGS 84 (World Geodetic System 1984)
|
|
*
|
|
* @author Manuel Bieh
|
|
* @url http://www.manuelbieh.com/
|
|
* @version 1.3.5
|
|
* @license LGPL
|
|
**/!function(a){var b=6378137,c=/^([0-9]{1,3})°\s*([0-9]{1,3})'\s*(([0-9]{1,3}(\.([0-9]{1,2}))?)"\s*)?([NEOSW]?)$/,d=-90,e=90,f=-180,g=180,h={decimal:{},sexagesimal:{},distance:0,measures:{m:1,km:.001,cm:100,mm:1e3,mi:1/1609.344,sm:1/1852.216,ft:100/30.48,"in":100/2.54,yd:1/.9144},getKeys:function(a){var b=a.hasOwnProperty("lat")?"lat":"latitude",c=(a.hasOwnProperty("lng")?"lng":!1)||(a.hasOwnProperty("long")?"long":!1)||"longitude",d=(a.hasOwnProperty("alt")?"alt":!1)||(a.hasOwnProperty("altitude")?"altitude":!1)||(a.hasOwnProperty("elev")?"elev":!1)||"elevation";return{latitude:b,longitude:c,elevation:d}},getDistance:function(a,b,c){var d=h.getKeys(a),e=d.latitude,f=d.longitude,g=d.elevation;c=Math.floor(c)||1;var i={},j={};i[e]=h.useDecimal(a[e]),i[f]=h.useDecimal(a[f]),j[e]=h.useDecimal(b[e]),j[f]=h.useDecimal(b[f]);var k,l,m,n,o,p,q,r=6378137,s=6356752.314245,t=1/298.257223563,u=(j[f]-i[f]).toRad(),v=Math.atan((1-t)*Math.tan(parseFloat(i[e]).toRad())),w=Math.atan((1-t)*Math.tan(parseFloat(j[e]).toRad())),x=Math.sin(v),y=Math.cos(v),z=Math.sin(w),A=Math.cos(w),B=u,C=100;do{var D=Math.sin(B),E=Math.cos(B);if(p=Math.sqrt(A*D*A*D+(y*z-x*A*E)*(y*z-x*A*E)),0===p)return h.distance=0;k=x*z+y*A*E,l=Math.atan2(p,k),m=y*A*D/p,n=1-m*m,o=k-2*x*z/n,isNaN(o)&&(o=0);var F=t/16*n*(4+t*(4-3*n));q=B,B=u+(1-F)*t*m*(l+F*p*(o+F*k*(-1+2*o*o)))}while(Math.abs(B-q)>1e-12&&--C>0);if(0===C)return 0/0;var G=n*(r*r-s*s)/(s*s),H=1+G/16384*(4096+G*(-768+G*(320-175*G))),I=G/1024*(256+G*(-128+G*(74-47*G))),J=I*p*(o+I/4*(k*(-1+2*o*o)-I/6*o*(-3+4*p*p)*(-3+4*o*o))),K=s*H*(l-J);if(K=K.toFixed(3),a.hasOwnProperty(g)&&b.hasOwnProperty(g)){var L=Math.abs(a[g]-b[g]);K=Math.sqrt(K*K+L*L)}return h.distance=Math.floor(Math.round(K/c)*c)},getDistanceSimple:function(a,c,d){var e=h.getKeys(a),f=e.latitude,g=e.longitude;d=Math.floor(d)||1;var i={},j={};i[f]=parseFloat(h.useDecimal(a[f])).toRad(),i[g]=parseFloat(h.useDecimal(a[g])).toRad(),j[f]=parseFloat(h.useDecimal(c[f])).toRad(),j[g]=parseFloat(h.useDecimal(c[g])).toRad();var k=Math.round(Math.acos(Math.sin(j[f])*Math.sin(i[f])+Math.cos(j[f])*Math.cos(i[f])*Math.cos(i[g]-j[g]))*b);return h.distance=Math.floor(Math.round(k/d)*d)},getCenter:function(a){if(!a.length)return!1;var b,c,d=h.getKeys(a[0]),e=d.latitude,f=d.longitude,g=function(a){return Math.max.apply(Math,a)},i=function(a){return Math.min.apply(Math,a)},j={lat:[],lng:[]};for(var k in a)j.lat.push(h.useDecimal(a[k][e])),j.lng.push(h.useDecimal(a[k][f]));var l=i(j.lat),m=i(j.lng),n=g(j.lat),o=g(j.lng);b=((l+n)/2).toFixed(6),c=((m+o)/2).toFixed(6);var p=h.convertUnit("km",h.getDistance({lat:l,lng:m},{lat:n,lng:o}));return{latitude:b,longitude:c,distance:p}},getBounds:function(a){if(!a.length)return!1;var b=h.getKeys(a[0]),c=b.latitude,d=b.longitude,e=b.elevation,f=a[0].hasOwnProperty(e),g={maxLat:-1/0,minLat:1/0,maxLng:-1/0,minLng:1/0};f&&(g.maxElev=0,g.minElev=1/0);for(var i=0,j=a.length;j>i;++i)g.maxLat=Math.max(a[i][c],g.maxLat),g.minLat=Math.min(a[i][c],g.minLat),g.maxLng=Math.max(a[i][d],g.maxLng),g.minLng=Math.min(a[i][d],g.minLng),f&&(g.maxElev=Math.max(a[i][e],g.maxElev),g.minElev=Math.min(a[i][e],g.minElev));return g},getBoundsOfDistance:function(a,c){var i=h.getKeys(a),j=i.latitude,k=i.longitude,l={};l[j]=h.useDecimal(a[j]),l[k]=h.useDecimal(a[k]);var m,n,o=l[j].toRad(),p=l[k].toRad(),q=c/b,r=o-q,s=o+q,t=e.toRad(),u=d.toRad(),v=g.toRad(),w=f.toRad();if(r>u&&t>s){var x=Math.asin(Math.sin(q)/Math.cos(o));m=p-x,w>m&&(m+=2*Math.PI),n=p+x,n>v&&(n-=2*Math.PI)}else r=Math.max(r,u),s=Math.min(s,t),m=w,n=v;return[{latitude:r.toDeg(),longitude:m.toDeg()},{latitude:s.toDeg(),longitude:n.toDeg()}]},isPointInside:function(a,b){for(var c=h.getKeys(a),d=c.latitude,e=c.longitude,f=!1,g=-1,i=b.length,j=i-1;++g<i;j=g)(b[g][e]<=a[e]&&a[e]<b[j][e]||b[j][e]<=a[e]&&a[e]<b[g][e])&&a[d]<(b[j][d]-b[g][d])*(a[e]-b[g][e])/(b[j][e]-b[g][e])+b[g][d]&&(f=!f);return f},isInside:function(){return h.isPointInside.apply(h,arguments)},isPointInCircle:function(a,b,c){return h.getDistance(a,b)<c},withinRadius:function(){return h.isPointInCircle.apply(h,arguments)},getRhumbLineBearing:function(a,b){var c=h.getKeys(a),d=c.latitude,e=c.longitude,f=h.useDecimal(b[e]).toRad()-h.useDecimal(a[e]).toRad(),g=Math.log(Math.tan(h.useDecimal(b[d]).toRad()/2+Math.PI/4)/Math.tan(h.useDecimal(a[d]).toRad()/2+Math.PI/4));return Math.abs(f)>Math.PI&&(f=f>0?-1*(2*Math.PI-f):2*Math.PI+f),(Math.atan2(f,g).toDeg()+360)%360},getBearing:function(a,b){var c=h.getKeys(a),d=c.latitude,e=c.longitude;b[d]=h.useDecimal(b[d]),b[e]=h.useDecimal(b[e]),a[d]=h.useDecimal(a[d]),a[e]=h.useDecimal(a[e]);var f=(Math.atan2(Math.sin(b[e].toRad()-a[e].toRad())*Math.cos(b[d].toRad()),Math.cos(a[d].toRad())*Math.sin(b[d].toRad())-Math.sin(a[d].toRad())*Math.cos(b[d].toRad())*Math.cos(b[e].toRad()-a[e].toRad())).toDeg()+360)%360;return f},getCompassDirection:function(a,b,c){var d,e;switch(e="circle"==c?h.getBearing(a,b):h.getRhumbLineBearing(a,b),Math.round(e/22.5)){case 1:d={exact:"NNE",rough:"N"};break;case 2:d={exact:"NE",rough:"N"};break;case 3:d={exact:"ENE",rough:"E"};break;case 4:d={exact:"E",rough:"E"};break;case 5:d={exact:"ESE",rough:"E"};break;case 6:d={exact:"SE",rough:"E"};break;case 7:d={exact:"SSE",rough:"S"};break;case 8:d={exact:"S",rough:"S"};break;case 9:d={exact:"SSW",rough:"S"};break;case 10:d={exact:"SW",rough:"S"};break;case 11:d={exact:"WSW",rough:"W"};break;case 12:d={exact:"W",rough:"W"};break;case 13:d={exact:"WNW",rough:"W"};break;case 14:d={exact:"NW",rough:"W"};break;case 15:d={exact:"NNW",rough:"N"};break;default:d={exact:"N",rough:"N"}}return d.bearing=e,d},getDirection:function(){return h.getCompassDirection.apply(h,arguments)},orderByDistance:function(a,b){var c=h.getKeys(a),d=c.latitude,e=c.longitude,f=[];for(var g in b){var i=h.getDistance(a,b[g]);f.push({key:g,latitude:b[g][d],longitude:b[g][e],distance:i})}return f.sort(function(a,b){return a.distance-b.distance})},findNearest:function(a,b,c){c=c||0;var d=h.orderByDistance(a,b);return d[c]},getPathLength:function(a){for(var b,c=0,d=0,e=a.length;e>d;++d)b&&(c+=h.getDistance(a[d],b)),b=a[d];return c},getSpeed:function(a,b,c){var d=c&&c.unit||"km";"mph"==d?d="mi":"kmh"==d&&(d="km");var e=h.getDistance(a,b),f=1*b.time/1e3-1*a.time/1e3,g=3600*(e/f),i=Math.round(1e4*g*h.measures[d])/1e4;return i},convertUnit:function(a,b,c){if(0===b||"undefined"==typeof b){if(0===h.distance)return 0;b=h.distance}if(a=a||"m",c=null==c?4:c,"undefined"!=typeof h.measures[a])return h.round(b*h.measures[a],c);throw new Error("Unknown unit for conversion.")},useDecimal:function(a){if(a=a.toString().replace(/\s*/,""),isNaN(parseFloat(a))||parseFloat(a)!=a){if(h.isSexagesimal(a)===!0)return parseFloat(h.sexagesimal2decimal(a));throw"Unknown format."}return parseFloat(a)},decimal2sexagesimal:function(a){if(a in h.sexagesimal)return h.sexagesimal[a];var b=a.toString().split("."),c=Math.abs(b[0]),d=60*("0."+b[1]),e=d.toString().split(".");return d=Math.floor(d),e=(60*("0."+e[1])).toFixed(2),h.sexagesimal[a]=c+"° "+d+"' "+e+'"',h.sexagesimal[a]},sexagesimal2decimal:function(a){if(a in h.decimal)return h.decimal[a];var b=new RegExp(c),d=b.exec(a),e=0,f=0;d&&(e=parseFloat(d[2]/60),f=parseFloat(d[4]/3600)||0);var g=(parseFloat(d[1])+e+f).toFixed(8);return g="S"==d[7]||"W"==d[7]?-1*g:g,h.decimal[a]=g,g},isSexagesimal:function(a){return c.test(a)},round:function(a,b){var c=Math.pow(10,b);return Math.round(a*c)/c}};h.getElevation=function(){"undefined"!=typeof window.navigator?h.getElevationClient.apply(this,arguments):h.getElevationServer.apply(this,arguments)},h.getElevationClient=function(a,b){if(!window.google)throw new Error("Google maps api not loaded");if(0===a.length)return b(null,null);if(1===a.length)return b(new Error("getElevation requires at least 2 points."));for(var c=[],d=h.getKeys(a[0]),e=d.latitude,f=d.longitude,g=0;g<a.length;g++)c.push(new google.maps.LatLng(h.useDecimal(a[g][e]),h.useDecimal(a[g][f])));var i={path:c,samples:c.length},j=new google.maps.ElevationService;j.getElevationAlongPath(i,function(c,e){h.elevationHandler(c,e,a,d,b)})},h.getElevationServer=function(a,b){if(0===a.length)return b(null,null);if(1===a.length)return b(new Error("getElevation requires at least 2 points."));for(var c=require("googlemaps"),d=[],e=h.getKeys(a[0]),f=e.latitude,g=e.longitude,i=0;i<a.length;i++)d.push(h.useDecimal(a[i][f])+","+h.useDecimal(a[i][g]));c.elevationFromPath(d.join("|"),d.length,function(c,d){h.elevationHandler(d.results,d.status,a,e,b)})},h.elevationHandler=function(a,b,c,d,e){var f=[],g=d.latitude,h=d.longitude;if("OK"==b){for(var i=0;i<a.length;i++)f.push({lat:c[i][g],lng:c[i][h],elev:a[i].elevation});e(null,f)}else e(new Error("Could not get elevation using Google's API"),elevationResult.status)},h.getGrade=function(a){var b=h.getKeys(a[0]),c=b.elevation,d=Math.abs(a[a.length-1][c]-a[0][c]),e=h.getPathLength(a);return Math.floor(100*(d/e))},h.getTotalElevationGainAndLoss=function(a){for(var b=h.getKeys(a[0]),c=b.elevation,d=0,e=0,f=0;f<a.length-1;f++){var g=a[f][c]-a[f+1][c];g>0?e+=g:d+=Math.abs(g)}return{gain:d,loss:e}},"undefined"==typeof Number.prototype.toRad&&(Number.prototype.toRad=function(){return this*Math.PI/180}),"undefined"==typeof Number.prototype.toDeg&&(Number.prototype.toDeg=function(){return 180*this/Math.PI}),"undefined"!=typeof module?a.geolib=module.exports=h:"function"==typeof define&&define.amd?define("geolib",[],function(){return h}):a.geolib=h}(this); |