324 lines
9.2 KiB
JavaScript
324 lines
9.2 KiB
JavaScript
|
|
//require('./transform.js')
|
||
|
|
var exports;
|
||
|
|
if (typeof module === "object" && exports) {
|
||
|
|
exports = module.exports;
|
||
|
|
} else if (typeof window !== "undefined") {
|
||
|
|
exports = window["eviltransform"] = {};
|
||
|
|
}
|
||
|
|
|
||
|
|
var earthR = 6378137.0;
|
||
|
|
|
||
|
|
function outOfChina(lat, lng) {
|
||
|
|
if ((lng < 72.004) || (lng > 137.8347)) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if ((lat < 0.8293) || (lat > 55.8271)) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
function transform(x, y) {
|
||
|
|
var xy = x * y;
|
||
|
|
var absX = Math.sqrt(Math.abs(x));
|
||
|
|
var xPi = x * Math.PI;
|
||
|
|
var yPi = y * Math.PI;
|
||
|
|
var d = 20.0*Math.sin(6.0*xPi) + 20.0*Math.sin(2.0*xPi);
|
||
|
|
|
||
|
|
var lat = d;
|
||
|
|
var lng = d;
|
||
|
|
|
||
|
|
lat += 20.0*Math.sin(yPi) + 40.0*Math.sin(yPi/3.0);
|
||
|
|
lng += 20.0*Math.sin(xPi) + 40.0*Math.sin(xPi/3.0);
|
||
|
|
|
||
|
|
lat += 160.0*Math.sin(yPi/12.0) + 320*Math.sin(yPi/30.0);
|
||
|
|
lng += 150.0*Math.sin(xPi/12.0) + 300.0*Math.sin(xPi/30.0);
|
||
|
|
|
||
|
|
lat *= 2.0 / 3.0;
|
||
|
|
lng *= 2.0 / 3.0;
|
||
|
|
|
||
|
|
lat += -100.0 + 2.0*x + 3.0*y + 0.2*y*y + 0.1*xy + 0.2*absX;
|
||
|
|
lng += 300.0 + x + 2.0*y + 0.1*x*x + 0.1*xy + 0.1*absX;
|
||
|
|
|
||
|
|
return {lat: lat, lng: lng}
|
||
|
|
}
|
||
|
|
|
||
|
|
function delta(lat, lng) {
|
||
|
|
var ee = 0.00669342162296594323;
|
||
|
|
var d = transform(lng-105.0, lat-35.0);
|
||
|
|
var radLat = lat / 180.0 * Math.PI;
|
||
|
|
var magic = Math.sin(radLat);
|
||
|
|
magic = 1 - ee*magic*magic;
|
||
|
|
var sqrtMagic = Math.sqrt(magic);
|
||
|
|
d.lat = (d.lat * 180.0) / ((earthR * (1 - ee)) / (magic * sqrtMagic) * Math.PI);
|
||
|
|
d.lng = (d.lng * 180.0) / (earthR / sqrtMagic * Math.cos(radLat) * Math.PI);
|
||
|
|
return d;
|
||
|
|
}
|
||
|
|
|
||
|
|
function wgs2gcj(wgsLat, wgsLng) {
|
||
|
|
if (outOfChina(wgsLat, wgsLng)) {
|
||
|
|
return {lat: wgsLat, lng: wgsLng};
|
||
|
|
}
|
||
|
|
var d = delta(wgsLat, wgsLng);
|
||
|
|
return {lat: wgsLat + d.lat, lng: wgsLng + d.lng};
|
||
|
|
}
|
||
|
|
exports.wgs2gcj = wgs2gcj;
|
||
|
|
|
||
|
|
function gcj2wgs(gcjLat, gcjLng) {
|
||
|
|
if (outOfChina(gcjLat, gcjLng)) {
|
||
|
|
return {lat: gcjLat, lng: gcjLng};
|
||
|
|
}
|
||
|
|
var d = delta(gcjLat, gcjLng);
|
||
|
|
return {lat: gcjLat - d.lat, lng: gcjLng - d.lng};
|
||
|
|
}
|
||
|
|
exports.gcj2wgs = gcj2wgs;
|
||
|
|
|
||
|
|
function gcj2wgs_exact(gcjLat, gcjLng) {
|
||
|
|
var initDelta = 0.01;
|
||
|
|
var threshold = 0.000001;
|
||
|
|
var dLat = initDelta, dLng = initDelta;
|
||
|
|
var mLat = gcjLat-dLat, mLng = gcjLng-dLng;
|
||
|
|
var pLat = gcjLat+dLat, pLng = gcjLng+dLng;
|
||
|
|
var wgsLat, wgsLng;
|
||
|
|
for (var i = 0; i < 30; i++) {
|
||
|
|
wgsLat = (mLat+pLat)/2;
|
||
|
|
wgsLng = (mLng+pLng)/2;
|
||
|
|
var tmp = wgs2gcj(wgsLat, wgsLng)
|
||
|
|
dLat = tmp.lat-gcjLat;
|
||
|
|
dLng = tmp.lng-gcjLng;
|
||
|
|
if ((Math.abs(dLat) < threshold) && (Math.abs(dLng) < threshold)) {
|
||
|
|
return {lat: wgsLat, lng: wgsLng};
|
||
|
|
}
|
||
|
|
if (dLat > 0) {
|
||
|
|
pLat = wgsLat;
|
||
|
|
} else {
|
||
|
|
mLat = wgsLat;
|
||
|
|
}
|
||
|
|
if (dLng > 0) {
|
||
|
|
pLng = wgsLng;
|
||
|
|
} else {
|
||
|
|
mLng = wgsLng;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return {lat: wgsLat, lng: wgsLng};
|
||
|
|
}
|
||
|
|
exports.gcj2wgs_exact = gcj2wgs_exact;
|
||
|
|
|
||
|
|
function distance(latA, lngA, latB, lngB) {
|
||
|
|
var pi180 = Math.PI / 180;
|
||
|
|
var arcLatA = latA * pi180;
|
||
|
|
var arcLatB = latB * pi180;
|
||
|
|
var x = Math.cos(arcLatA) * Math.cos(arcLatB) * Math.cos((lngA-lngB)*pi180);
|
||
|
|
var y = Math.sin(arcLatA) * Math.sin(arcLatB);
|
||
|
|
var s = x + y;
|
||
|
|
if (s > 1) {
|
||
|
|
s = 1;
|
||
|
|
}
|
||
|
|
if (s < -1) {
|
||
|
|
s = -1;
|
||
|
|
}
|
||
|
|
var alpha = Math.acos(s);
|
||
|
|
var distance = alpha * earthR;
|
||
|
|
return distance;
|
||
|
|
}
|
||
|
|
exports.distance = distance;
|
||
|
|
|
||
|
|
function gcj2bd(gcjLat, gcjLng) {
|
||
|
|
if (outOfChina(gcjLat, gcjLng)) {
|
||
|
|
return {lat: gcjLat, lng: gcjLng};
|
||
|
|
}
|
||
|
|
|
||
|
|
var x = gcjLng, y = gcjLat;
|
||
|
|
var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * Math.PI);
|
||
|
|
var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * Math.PI);
|
||
|
|
var bdLng = z * Math.cos(theta) + 0.0065;
|
||
|
|
var bdLat = z * Math.sin(theta) + 0.006;
|
||
|
|
return {lat: bdLat, lng: bdLng};
|
||
|
|
}
|
||
|
|
exports.gcj2bd = gcj2bd;
|
||
|
|
|
||
|
|
function bd2gcj(bdLat, bdLng) {
|
||
|
|
if (outOfChina(bdLat, bdLng)) {
|
||
|
|
return {lat: bdLat, lng: bdLng};
|
||
|
|
}
|
||
|
|
|
||
|
|
var x = bdLng - 0.0065, y = bdLat - 0.006;
|
||
|
|
var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * Math.PI);
|
||
|
|
var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * Math.PI);
|
||
|
|
var gcjLng = z * Math.cos(theta);
|
||
|
|
var gcjLat = z * Math.sin(theta);
|
||
|
|
return {lat: gcjLat, lng: gcjLng};
|
||
|
|
}
|
||
|
|
exports.bd2gcj = bd2gcj;
|
||
|
|
|
||
|
|
function wgs2bd(wgsLat, wgsLng) {
|
||
|
|
var gcj = wgs2gcj(wgsLat, wgsLng);
|
||
|
|
return gcj2bd(gcj.lat, gcj.lng);
|
||
|
|
}
|
||
|
|
exports.wgs2bd = wgs2bd;
|
||
|
|
|
||
|
|
function bd2wgs(bdLat, bdLng) {
|
||
|
|
var gcj = bd2gcj(bdLat, bdLng);
|
||
|
|
return gcj2wgs(gcj.lat, gcj.lng);
|
||
|
|
}
|
||
|
|
exports.bd2wgs = bd2wgs;
|
||
|
|
/**
|
||
|
|
* Projection class for Baidu Spherical Mercator
|
||
|
|
*
|
||
|
|
* @class BaiduSphericalMercator
|
||
|
|
*/
|
||
|
|
L.Projection.GCJ02SphericalMercator = {
|
||
|
|
/**
|
||
|
|
* Project latLng to point coordinate
|
||
|
|
*
|
||
|
|
* @method project
|
||
|
|
* @param {Object} latLng coordinate for a point on earth
|
||
|
|
* @return {Object} leafletPoint point coordinate of L.Point
|
||
|
|
*/
|
||
|
|
project: function(latLng) {
|
||
|
|
//1.gcj02 to wgs84 lat lon
|
||
|
|
//2.wgs84 lat lon to point
|
||
|
|
var wgs84_latlon = gcj2wgs(latLng.lat, latLng.lng)
|
||
|
|
// var MAX_LATITUDE = 85.0511287798;
|
||
|
|
// var R = 6378137;
|
||
|
|
// var d = Math.PI/ 180;
|
||
|
|
// var max = MAX_LATITUDE;
|
||
|
|
// var lat = Math.max(Math.min(max, wgs84_latlon.lat), -max);
|
||
|
|
// var sin = Math.sin(lat * d);
|
||
|
|
|
||
|
|
// var x = R * wgs84_latlon.lng * d;
|
||
|
|
// var y = R * Math.log((1 + sin) / (1 - sin)) / 2;
|
||
|
|
|
||
|
|
var x = wgs84_latlon.lng * 20037508.34 / 180;
|
||
|
|
var y = Math.log(Math.tan((90 + wgs84_latlon.lat) * Math.PI / 360)) / (Math.PI / 180);
|
||
|
|
y = y * 20037508.34 / 180;
|
||
|
|
|
||
|
|
var leafletPoint = new L.Point(x, y);
|
||
|
|
return leafletPoint;
|
||
|
|
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* unproject point coordinate to latLng
|
||
|
|
*
|
||
|
|
* @method unproject
|
||
|
|
* @param {Object} bpoint baidu point coordinate
|
||
|
|
* @return {Object} latitude and longitude
|
||
|
|
*/
|
||
|
|
unproject: function (bpoint) {
|
||
|
|
//1. x,y to wgs84 lat lon
|
||
|
|
//2. wgs84 to gcj02 lat lon
|
||
|
|
// var R = 6378137;
|
||
|
|
// var d = 180 / Math.PI;
|
||
|
|
// var lng = bpoint.x * d / R;
|
||
|
|
// var lat = (2 * Math.atan(Math.exp(bpoint.y / R)) - (Math.PI / 2)) * d;
|
||
|
|
|
||
|
|
var lng = (bpoint.x / 20037508.34) * 180;
|
||
|
|
var lat = (bpoint.y / 20037508.34) * 180;
|
||
|
|
|
||
|
|
lat = 180/Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180)) - Math.PI / 2);
|
||
|
|
|
||
|
|
gcj02_latlon = wgs2gcj(lat, lng);
|
||
|
|
var latLng = new L.LatLng(gcj02_latlon.lat, gcj02_latlon.lng);
|
||
|
|
return latLng;
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Don't know how it used currently.
|
||
|
|
*
|
||
|
|
* However, I guess this is the range of coordinate.
|
||
|
|
* Range of pixel coordinate is gotten from
|
||
|
|
* BMap.MercatorProjection.lngLatToPoint(180, -90) and (180, 90)
|
||
|
|
* After getting max min value of pixel coordinate, use
|
||
|
|
* pointToLngLat() get the max lat and Lng.
|
||
|
|
*/
|
||
|
|
// bounds: (function () {
|
||
|
|
// var MAX_X= 20037726.37;
|
||
|
|
// var MIN_Y= -11708041.66;
|
||
|
|
// var MAX_Y= 12474104.17;
|
||
|
|
// var bounds = L.bounds(
|
||
|
|
// [-MAX_X, MIN_Y], //180, -71.988531
|
||
|
|
// [MAX_X, MAX_Y] //-180, 74.000022
|
||
|
|
// );
|
||
|
|
// return bounds;
|
||
|
|
// })()
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
L.GCJ02Transformation = L.extend({}, L.Transformation, {
|
||
|
|
MAXZOOM: 30,
|
||
|
|
/**
|
||
|
|
* Don't know how it used currently.
|
||
|
|
*/
|
||
|
|
transform: function (point, zoom) {
|
||
|
|
console.log("11");
|
||
|
|
return this._transform(point.clone(), zoom);
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* transform point coordinate to pixel coordinate
|
||
|
|
*
|
||
|
|
* @method _transform
|
||
|
|
* @param {Object} point point coordinate
|
||
|
|
* @param {Number} zoom zoom level of the map
|
||
|
|
* @return {Object} point, pixel coordinate
|
||
|
|
*/
|
||
|
|
_transform: function (point, zoom) {
|
||
|
|
console.log("22");
|
||
|
|
point.x = point.x >> (this.MAXZOOM - zoom);
|
||
|
|
point.y = point.y >> (this.MAXZOOM - zoom);
|
||
|
|
return point;
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* transform pixel coordinate to point coordinate
|
||
|
|
*
|
||
|
|
* @method untransform
|
||
|
|
* @param {Object} point pixel coordinate
|
||
|
|
* @param {Number} zoom zoom level of the map
|
||
|
|
* @return {Object} point, point coordinate
|
||
|
|
*/
|
||
|
|
untransform: function (point, zoom) {
|
||
|
|
point.x = point.x << (this.MAXZOOM - zoom);
|
||
|
|
point.y = point.y << (this.MAXZOOM - zoom);
|
||
|
|
return point;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Coordinate system for Baidu EPSG3857
|
||
|
|
*
|
||
|
|
* @class BEPSG3857
|
||
|
|
*/
|
||
|
|
L.CRS.GCJ02 = L.extend({}, L.CRS, {
|
||
|
|
/**
|
||
|
|
* transform latLng to pixel coordinate
|
||
|
|
*
|
||
|
|
* @method untransform
|
||
|
|
* @param {Object} latlng latitude and longitude
|
||
|
|
* @param {Number} zoom zoom level of the map
|
||
|
|
* @return {Object} pixel coordinate calculated for latLng
|
||
|
|
*/
|
||
|
|
latLngToPoint: function (latlng, zoom) { // (LatLng, Number) -> Point
|
||
|
|
var projectedPoint = L.Projection.GCJ02SphericalMercator.project(latlng);
|
||
|
|
return L.GCJ02Transformation._transform(projectedPoint, zoom);
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* transform pixel coordinate to latLng
|
||
|
|
*
|
||
|
|
* @method untransform
|
||
|
|
* @param {Object} point pixel coordinate
|
||
|
|
* @param {Number} zoom zoom level of the map
|
||
|
|
* @return {Object} latitude and longitude
|
||
|
|
*/
|
||
|
|
pointToLatLng: function (point, zoom) { // (Point, Number[, Boolean]) -> LatLng
|
||
|
|
var untransformedPoint = L.GCJ02Transformation.untransform(point, zoom);
|
||
|
|
return L.Projection.GCJ02SphericalMercator.unproject(untransformedPoint);
|
||
|
|
},
|
||
|
|
|
||
|
|
code: 'EPSG:3857',
|
||
|
|
projection: L.Projection.GCJ02SphericalMercator,
|
||
|
|
transformation: L.GCJ02Transformation
|
||
|
|
});
|