195 lines
7.1 KiB
JavaScript
195 lines
7.1 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Convert = exports.pointInsideCircle = exports.isInPolygon = exports.VerifyCoordinate = void 0;
|
|
/**
|
|
* 获取中心坐标
|
|
*/
|
|
class CenterGps {
|
|
rad2degr(rad) { return rad * 180 / Math.PI; }
|
|
degr2rad(degr) { return degr * Math.PI / 180; }
|
|
/**
|
|
* 计算多个经纬度的中心点 | 在一组坐标中获取中心坐标
|
|
* @param latLngInDeg array of arrays with latitude and longtitude
|
|
* pairs in degrees. e.g. [[latitude1, longtitude1], [latitude2
|
|
* [longtitude2] ...]
|
|
*
|
|
* @return array with the center latitude longtitude pairs in
|
|
* degrees.
|
|
*/
|
|
GetCenterFromDegrees(latLngInDegr, latIdx = 0, lngIdx = 1) {
|
|
var LATIDX = latIdx;
|
|
var LNGIDX = lngIdx;
|
|
var sumX = 0;
|
|
var sumY = 0;
|
|
var sumZ = 0;
|
|
for (var i = 0; i < latLngInDegr.length; i++) {
|
|
var lat = this.degr2rad(latLngInDegr[i][LATIDX]);
|
|
var lng = this.degr2rad(latLngInDegr[i][LNGIDX]);
|
|
// sum of cartesian coordinates
|
|
sumX += Math.cos(lat) * Math.cos(lng);
|
|
sumY += Math.cos(lat) * Math.sin(lng);
|
|
sumZ += Math.sin(lat);
|
|
}
|
|
var avgX = sumX / latLngInDegr.length;
|
|
var avgY = sumY / latLngInDegr.length;
|
|
var avgZ = sumZ / latLngInDegr.length;
|
|
// convert average x, y, z coordinate to latitude and longtitude
|
|
var lng = Math.atan2(avgY, avgX);
|
|
var hyp = Math.sqrt(avgX * avgX + avgY * avgY);
|
|
var lat = Math.atan2(avgZ, hyp);
|
|
return ([this.rad2degr(lat), this.rad2degr(lng)]);
|
|
}
|
|
}
|
|
exports.default = CenterGps;
|
|
/**
|
|
* 验证经纬度格式
|
|
*/
|
|
const VerifyCoordinate = (lat, lng) => {
|
|
var latreg = /^(\-|\+)?([0-8]?\d{1}\.\d{0,}|90\.0{0,}|[0-8]?\d{1}|90)$/;
|
|
if (!latreg.test(lat.toString())) {
|
|
console.log("纬度整数部分为0-90,小数部分为0到6位!");
|
|
return false;
|
|
}
|
|
var longrg = /^(\-|\+)?(((\d|[1-9]\d|1[0-7]\d|0{1,3})\.\d{0,})|(\d|[1-9]\d|1[0-7]\d|0{1,3})|180\.0{0,}|180)$/;
|
|
if (!longrg.test(lng.toString())) {
|
|
console.log("经度整数部分为0-180,小数部分为0到6位!");
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
exports.VerifyCoordinate = VerifyCoordinate;
|
|
/**
|
|
* 判断给定坐标是否在多边形中
|
|
*/
|
|
function isInPolygon(checkPoint, polygonPoints) {
|
|
var counter = 0;
|
|
var i;
|
|
var xinters;
|
|
var p1, p2;
|
|
var pointCount = polygonPoints.length;
|
|
p1 = polygonPoints[0];
|
|
for (i = 1; i <= pointCount; i++) {
|
|
p2 = polygonPoints[i % pointCount];
|
|
if (checkPoint[0] > Math.min(p1[0], p2[0]) &&
|
|
checkPoint[0] <= Math.max(p1[0], p2[0])) {
|
|
if (checkPoint[1] <= Math.max(p1[1], p2[1])) {
|
|
if (p1[0] != p2[0]) {
|
|
xinters =
|
|
(checkPoint[0] - p1[0]) *
|
|
(p2[1] - p1[1]) /
|
|
(p2[0] - p1[0]) +
|
|
p1[1];
|
|
if (p1[1] == p2[1] || checkPoint[1] <= xinters) {
|
|
counter++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
p1 = p2;
|
|
}
|
|
if (counter % 2 == 0) {
|
|
return false;
|
|
}
|
|
else {
|
|
return true;
|
|
}
|
|
}
|
|
exports.isInPolygon = isInPolygon;
|
|
/**
|
|
* 判断一个点是否在圆的内部
|
|
* @param point 测试点坐标
|
|
* @param circle 圆心坐标
|
|
* @param r 圆半径
|
|
* 返回true为真,false为假
|
|
* */
|
|
function pointInsideCircle(point, circle, r) {
|
|
if (r === 0)
|
|
return false;
|
|
var dx = circle[0] - point[0];
|
|
var dy = circle[1] - point[1];
|
|
return dx * dx + dy * dy <= r * r;
|
|
}
|
|
exports.pointInsideCircle = pointInsideCircle;
|
|
/**
|
|
* 火星坐标,GPS,转换
|
|
*/
|
|
exports.Convert = {
|
|
PI: 3.14159265358979324,
|
|
x_pi: 3.14159265358979324 * 3000.0 / 180.0,
|
|
delta: function (lat, lng) {
|
|
let lon = lng;
|
|
// Krasovsky 1940
|
|
//
|
|
// a = 6378245.0, 1/f = 298.3
|
|
// b = a * (1 - f)
|
|
// ee = (a^2 - b^2) / a^2;
|
|
let a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
|
|
let ee = 0.00669342162296594323; // ee: 椭球的偏心率。
|
|
let dLat = this.transformLat(lon - 105.0, lat - 35.0);
|
|
let dLon = this.transformLon(lon - 105.0, lat - 35.0);
|
|
let radLat = lat / 180.0 * this.PI;
|
|
let magic = Math.sin(radLat);
|
|
magic = 1 - ee * magic * magic;
|
|
let sqrtMagic = Math.sqrt(magic);
|
|
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * this.PI);
|
|
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * this.PI);
|
|
return { 'lat': dLat, 'lon': dLon };
|
|
},
|
|
//GPS---高德
|
|
gcj_encrypt: function (wgsLat, wgsLon) {
|
|
if (this.outOfChina(wgsLat, wgsLon))
|
|
return { 'lat': wgsLat, 'lon': wgsLon };
|
|
let d = this.delta(wgsLat, wgsLon);
|
|
return { 'lat': wgsLat + d.lat, 'lon': wgsLon + d.lon };
|
|
},
|
|
/**
|
|
*百度坐标转高德(传入经度、纬度)
|
|
* @param bd_lng
|
|
* @param bd_lat
|
|
*/
|
|
bd_decrypt: function (bd_lng, bd_lat) {
|
|
var X_PI = Math.PI * 3000.0 / 180.0;
|
|
var x = bd_lng - 0.0065;
|
|
var y = bd_lat - 0.006;
|
|
var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * X_PI);
|
|
var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * X_PI);
|
|
var gg_lng = z * Math.cos(theta);
|
|
var gg_lat = z * Math.sin(theta);
|
|
return { lng: gg_lng, lat: gg_lat };
|
|
},
|
|
//高德坐标转百度(传入经度、纬度)
|
|
bd_encrypt: function (gg_lng, gg_lat) {
|
|
var X_PI = Math.PI * 3000.0 / 180.0;
|
|
var x = gg_lng, y = gg_lat;
|
|
var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * X_PI);
|
|
var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * X_PI);
|
|
var bd_lng = z * Math.cos(theta) + 0.0065;
|
|
var bd_lat = z * Math.sin(theta) + 0.006;
|
|
return {
|
|
bd_lat: bd_lat,
|
|
bd_lng: bd_lng
|
|
};
|
|
},
|
|
outOfChina: function (lat, lng) {
|
|
if (lng < 72.004 || lng > 137.8347)
|
|
return true;
|
|
if (lat < 0.8293 || lat > 55.8271)
|
|
return true;
|
|
return false;
|
|
},
|
|
transformLat: function (x, y) {
|
|
let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
|
|
ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
|
|
ret += (20.0 * Math.sin(y * this.PI) + 40.0 * Math.sin(y / 3.0 * this.PI)) * 2.0 / 3.0;
|
|
ret += (160.0 * Math.sin(y / 12.0 * this.PI) + 320 * Math.sin(y * this.PI / 30.0)) * 2.0 / 3.0;
|
|
return ret;
|
|
},
|
|
transformLon: function (x, y) {
|
|
let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
|
|
ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
|
|
ret += (20.0 * Math.sin(x * this.PI) + 40.0 * Math.sin(x / 3.0 * this.PI)) * 2.0 / 3.0;
|
|
ret += (150.0 * Math.sin(x / 12.0 * this.PI) + 300.0 * Math.sin(x / 30.0 * this.PI)) * 2.0 / 3.0;
|
|
return ret;
|
|
}
|
|
};
|