//随机生成十六进制颜色
|
function randomHexColor() {
|
let hex = Math.floor(Math.random() * 16777216).toString(16); //生成ffffff以内16进制数
|
while (hex.length < 6) { //while循环判断hex位数,少于6位前面加0凑够6位
|
hex = '0' + hex;
|
}
|
return '#' + hex; //返回‘#'开头16进制颜色
|
}
|
|
Array.prototype.getRandomItem = function () {
|
return this[Math.floor(Math.random() * this.length)];
|
};
|
|
//字符串数据转数字字符串
|
function stringToNumber(stringInput) {
|
let stringArray = stringInput.split(",");
|
let numberArrayOutput = [];
|
for (let i = 0; i < stringArray.length; i++) {
|
numberArrayOutput.push(Number(stringArray[i]));
|
}
|
return numberArrayOutput;
|
}
|
|
//截取字符串,返回经度数值,cj添加,mty改为判断
|
function substringLon(str) {
|
let lon, lon1, lon2;
|
if (str.toString().substring(0, 1) !== '1') {
|
lon1 = str.toString().substring(0, 2);
|
lon2 = str.toString().substring(2);
|
} else {
|
lon1 = str.toString().substring(0, 3);
|
lon2 = str.toString().substring(3);
|
}
|
if (str.indexOf('.') === -1) {
|
lon = Number(lon1 + "." + lon2);
|
} else {
|
lon = Number(lon1 + lon2);
|
}
|
return lon;
|
}
|
|
//截取字符串,返回纬度数值,cj添加
|
function substringLat(str) {
|
let lat1 = str.toString().substring(0, 2);
|
let lat2 = str.toString().substring(2);
|
let lat;
|
if (str.indexOf('.') === -1) {
|
lat = Number(lat1 + "." + lat2);
|
} else {
|
lat = Number(lat1 + lat2);
|
}
|
return lat;
|
}
|
|
//定义一些常量
|
let x_PI = 3.14159265358979324 * 3000.0 / 180.0;
|
let C_PI = 3.1415926535897932384626;
|
let a = 6378245.0;
|
let ee = 0.00669342162296594323;
|
|
//将WGS84坐标系,转换成百度坐标体系
|
function wgs84tobd09(lon, lat) {
|
let gcj02poi1 = wgs84togcj02(lon, lat);
|
let baidupoi1 = gcj02tobd09(gcj02poi1[0], gcj02poi1[1]);
|
return baidupoi1;
|
}
|
|
//将百度坐标体系,转换成WGS84坐标系
|
function bd09towgs84(lon, lat) {
|
let gcj02poi1 = bd09togcj02(lon, lat);
|
let wgs84poi1 = gcj02towgs84(gcj02poi1[0], gcj02poi1[1]);
|
return wgs84poi1;
|
}
|
|
/**
|
* 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
|
* 即 百度 转 谷歌、高德
|
* @param bd_lon
|
* @param bd_lat
|
* @returns {*[]}
|
*/
|
function bd09togcj02(bd_lon, bd_lat) {
|
let x_pi = 3.14159265358979324 * 3000.0 / 180.0;
|
let x = bd_lon - 0.0065;
|
let y = bd_lat - 0.006;
|
let z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
|
let theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
|
let gg_lng = z * Math.cos(theta);
|
let gg_lat = z * Math.sin(theta);
|
return [gg_lng, gg_lat];
|
}
|
|
/**
|
* GCJ02 转换为 WGS84
|
* @param lng
|
* @param lat
|
* @returns {*[]}
|
*/
|
function gcj02towgs84(lng, lat) {
|
if (out_of_china(lng, lat)) {
|
return [lng, lat];
|
} else {
|
let dlat = transformlat(lng - 105.0, lat - 35.0);
|
let dlng = transformlng(lng - 105.0, lat - 35.0);
|
let radlat = lat / 180.0 * C_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) * C_PI);
|
dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * C_PI);
|
let mglat = lat + dlat;
|
let mglng = lng + dlng;
|
return [lng * 2 - mglng, lat * 2 - mglat];
|
}
|
}
|
|
//WGS84转GCj02
|
function wgs84togcj02(lng, lat) {
|
if (out_of_china(lng, lat)) {
|
return [lng, lat];
|
} else {
|
let dlat = transformlat(lng - 105.0, lat - 35.0);
|
let dlng = transformlng(lng - 105.0, lat - 35.0);
|
let radlat = lat / 180.0 * C_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) * C_PI);
|
dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * C_PI);
|
let mglat = lat + dlat;
|
let mglng = lng + dlng;
|
return [mglng, mglat];
|
}
|
}
|
|
function convertWGS84ToGCJ02(wgs) {
|
const { longitude, latitude } = wgs;
|
let lon_ = transformLon(longitude - 105, latitude - 35);
|
let lat_ = transformLat(longitude - 105, latitude - 35);
|
const latRad = latitude * PI / 180;
|
let magic = Math.sin(latRad);
|
magic = 1 - EE * magic * magic;
|
const sqrtMagic = Math.sqrt(magic);
|
lon_ = (lon_ * 180) / (EARTH_RADIUS / sqrtMagic * Math.cos(latRad) * PI);
|
lat_ = (lat_ * 180) / ((EARTH_RADIUS * (1 - EE)) / (magic * sqrtMagic) * PI);
|
return { longitude: longitude + lon_, latitude: latitude + lat_ };
|
}
|
|
|
/**
|
* 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
|
* 即谷歌、高德 转 百度
|
* @param lng
|
* @param lat
|
* @returns {*[]}
|
*/
|
function gcj02tobd09(lng, lat) {
|
let z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI);
|
let theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI);
|
let bd_lng = z * Math.cos(theta) + 0.0065;
|
let bd_lat = z * Math.sin(theta) + 0.006;
|
return [bd_lng, bd_lat]
|
}
|
|
/**
|
* 笛卡尔坐标转WGS84
|
* @param Cartesian3
|
* @returns {*[]}
|
*/
|
function Cartesian3ToWGS84(Cartesian3) {
|
if (!Cartesian3 || !Cartesian3.x) {
|
throw "Error in parameters";
|
}
|
let _cartesian3 = new Cesium.Cartesian3(Cartesian3.x, Cartesian3.y, Cartesian3.z);
|
let _cartographic = Cesium.Cartographic.fromCartesian(_cartesian3);
|
let _lat = Cesium.Math.toDegrees(_cartographic.latitude);
|
let _lng = Cesium.Math.toDegrees(_cartographic.longitude);
|
let _alt = _cartographic.height;
|
return {longitude: _lng, latitude: _lat, altitude: _alt};
|
}
|
|
|
/**
|
* 判断是否在国内,不在国内则不做偏移
|
* @param lng
|
* @param lat
|
* @returns {boolean}
|
*/
|
function out_of_china(lng, lat) {
|
return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false);
|
}
|
|
function transformlat(lng, lat) {
|
let ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
|
ret += (20.0 * Math.sin(6.0 * lng * C_PI) + 20.0 * Math.sin(2.0 * lng * C_PI)) * 2.0 / 3.0;
|
ret += (20.0 * Math.sin(lat * C_PI) + 40.0 * Math.sin(lat / 3.0 * C_PI)) * 2.0 / 3.0;
|
ret += (160.0 * Math.sin(lat / 12.0 * C_PI) + 320 * Math.sin(lat * C_PI / 30.0)) * 2.0 / 3.0;
|
return ret
|
}
|
|
function transformlng(lng, lat) {
|
let ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
|
ret += (20.0 * Math.sin(6.0 * lng * C_PI) + 20.0 * Math.sin(2.0 * lng * C_PI)) * 2.0 / 3.0;
|
ret += (20.0 * Math.sin(lng * C_PI) + 40.0 * Math.sin(lng / 3.0 * C_PI)) * 2.0 / 3.0;
|
ret += (150.0 * Math.sin(lng / 12.0 * C_PI) + 300.0 * Math.sin(lng / 30.0 * C_PI)) * 2.0 / 3.0;
|
return ret
|
}
|
|
/**
|
* approx distance between two points on earth ellipsoid
|
* @param {Object} lat1
|
* @param {Object} lng1
|
* @param {Object} lat2
|
* @param {Object} lng2
|
*/
|
let EARTH_RADIUS = 6378137.0; //单位M
|
let E_PI = Math.PI;
|
|
function getRad(d) {
|
return d * E_PI / 180.0;
|
}
|
|
//计算两个经纬度之间的距离
|
function getFlatternDistance(lng1, lat1, lng2, lat2) {
|
let f = getRad((lat1 + lat2) / 2);
|
let g = getRad((lat1 - lat2) / 2);
|
let l = getRad((lng1 - lng2) / 2);
|
|
let sg = Math.sin(g);
|
let sl = Math.sin(l);
|
let sf = Math.sin(f);
|
|
let s,
|
c,
|
w,
|
r,
|
d,
|
h1,
|
h2;
|
let a = EARTH_RADIUS;
|
let fl = 1 / 298.257;
|
|
sg = sg * sg;
|
sl = sl * sl;
|
sf = sf * sf;
|
|
s = sg * (1 - sl) + (1 - sf) * sl;
|
c = (1 - sg) * (1 - sl) + sf * sl;
|
|
w = Math.atan(Math.sqrt(s / c));
|
r = Math.sqrt(s * c) / w;
|
d = 2 * w * a;
|
h1 = (3 * r - 1) / 2 / c;
|
h2 = (3 * r + 1) / 2 / s;
|
|
return d * (1 + fl * (h1 * sf * (1 - sg) - h2 * (1 - sf) * sg));
|
}
|
|
/**
|
* 判断一个点是否在多边形内部
|
* @param points 多边形坐标集合
|
* @param testPoint 需检测点坐标
|
* 返回true为真,false为假
|
* */
|
function insidePolygon(points, testPoint) {
|
let x = testPoint[0],
|
y = testPoint[1];
|
let inside = false;
|
for (let i = 0, j = points.length - 1; i < points.length; j = i++) {
|
let xi = points[i][0],
|
yi = points[i][1];
|
let xj = points[j][0],
|
yj = points[j][1];
|
|
let intersect = ((yi > y) !== (yj > y))
|
&& (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
|
if (intersect)
|
inside = !inside;
|
}
|
return inside;
|
}
|
|
/**
|
* 判断一个点是否在圆内部
|
* @param point 需检测点坐标
|
* @param circle 圆心坐标
|
* @param r 圆心半径
|
* 返回true为真,false为假
|
* */
|
function insideCircle(point, circle, r) {
|
let inside = false;
|
let a = Cesium.Cartesian3.fromDegrees(Number(point[0]),Number(point[1]),Number(point[2]));
|
let b = Cesium.Cartesian3.fromDegrees(Number(circle[0]),Number(circle[1]),Number(circle[2]));
|
let measureValue = Cesium.Cartesian3.distance(a, b);
|
inside = measureValue*measureValue <= r*r;
|
return inside;
|
}
|
|
/**
|
* 将秒转换为 分:秒
|
* s int 秒数
|
*/
|
function s_to_hs(s) {
|
//计算分钟
|
//算法:将秒数除以60,然后下舍入,既得到分钟数
|
let h;
|
h = Math.floor(s / 60);
|
//计算秒
|
//算法:取得秒%60的余数,既得到秒数
|
s = s % 60;
|
//将变量转换为字符串
|
h += '';
|
s += '';
|
//如果只有一位数,前面增加一个0
|
h = (h.length === 1) ? '0' + h : h;
|
s = (s.length === 1) ? '0' + s : s;
|
return h + ':' + s;
|
}
|
|
//判断点是否在另一平面图中
|
//点: { x: xxx, y: xxx }
|
//线: [{ x: xxx, y: xxx }, { x: xxx, y: xxx }]
|
//面: [{ x: xxx, y: xxx }, { x: xxx, y: xxx }, { x: xxx, y: xxx }...]
|
function isPointInPolygon(point, polygon) {
|
//下述代码来源:http://paulbourke.net/geometry/insidepoly/,进行了部分修改
|
//基本思想是利用射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则
|
//在多边形内。还会考虑一些特殊情况,如点在多边形顶点上,点在多边形边上等特殊情况。
|
|
let N = polygon.length;
|
let boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
|
let intersectCount = 0; //cross points count of x
|
let precision = 2e-10; //浮点类型计算时候与0比较时候的容差
|
let p1, p2; //neighbour bound vertices
|
let p = point; //测试点
|
|
p1 = polygon[0]; //left vertex
|
for (let i = 1; i <= N; ++i) { //check all rays
|
if (p.x === p1.x && p.y === p1.y) {
|
return boundOrVertex; //p is an vertex
|
}
|
|
p2 = polygon[i % N]; //right vertex
|
if (p.y < Math.min(p1.y, p2.y) || p.y > Math.max(p1.y, p2.y)) { //ray is outside of our interests
|
p1 = p2;
|
continue; //next ray left point
|
}
|
|
if (p.y > Math.min(p1.y, p2.y) && p.y < Math.max(p1.y, p2.y)) { //ray is crossing over by the algorithm (common part of)
|
if (p.x <= Math.max(p1.x, p2.x)) { //x is before of ray
|
if (p1.y === p2.y && p.x >= Math.min(p1.x, p2.x)) { //overlies on a horizontal ray
|
return boundOrVertex;
|
}
|
|
if (p1.x === p2.x) { //ray is vertical
|
if (p1.x === p.x) { //overlies on a vertical ray
|
return boundOrVertex;
|
} else { //before ray
|
++intersectCount;
|
}
|
} else { //cross point on the left side
|
let xinters = (p.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x; //cross point of x
|
if (Math.abs(p.x - xinters) < precision) { //overlies on a ray
|
return boundOrVertex;
|
}
|
|
if (p.x < xinters) { //before ray
|
++intersectCount;
|
}
|
}
|
}
|
} else { //special case when ray is crossing through the vertex
|
if (p.y === p2.y && p.x <= p2.x) { //p crossing over p2
|
let p3 = polygon[(i + 1) % N]; //next vertex
|
if (p.y >= Math.min(p1.y, p3.y) && p.y <= Math.max(p1.y, p3.y)) { //p.y lies between p1.y & p3.y
|
++intersectCount;
|
} else {
|
intersectCount += 2;
|
}
|
}
|
}
|
p1 = p2; //next ray left point
|
}
|
|
if (intersectCount % 2 === 0) { //偶数在多边形外
|
return false;
|
} else { //奇数在多边形内
|
return true;
|
}
|
}
|
|
//判断两多变形是否存在点与区域的包含关系(A的点在B的区域内或B的点在A的区域内)
|
function isPointInPolygonBidirectional(plyA, plyB) {
|
let [a, b] = [false, false];
|
a = plyA.some(item => isPointInPolygon(item, plyB));
|
if (!a) {
|
b = plyB.some(item => isPointInPolygon(item, plyA));
|
}
|
return a || b;
|
}
|
|
//根据两点坐标计算方位角
|
function azimuthtwopoi(x1, y1, x2, y2) {
|
let result;
|
let a = Math.abs(Math.atan((y2 - y1) / (x2 - x1))) * 180 / Math.PI;
|
if ((x2 - x1) < 0) {
|
if ((y2 - y1) > 0) {
|
result = a + 270;
|
} else {
|
result = 90 - a + 180;
|
}
|
} else {
|
if ((y2 - y1) > 0) {
|
result = 90 - a;
|
} else {
|
result = a + 90;
|
}
|
}
|
return result;
|
}
|
|
//获取立方体中心点、方位角、边线长度
|
function fixtoboxvertex(floorPoiStrArr) {
|
let oriLonArr = [], oriLatArr = [];
|
for (let i = 0; i < 12; i = i + 3) {
|
oriLonArr.push(Number(floorPoiStrArr[i]));
|
oriLatArr.push(Number(floorPoiStrArr[i + 1]));
|
}
|
oriLonArr.push(Number(floorPoiStrArr[0]));
|
oriLatArr.push(Number(floorPoiStrArr[1]));
|
let sumLon = 0, sumLat = 0;
|
let heading = [], distance = [];
|
for (let i = 0; i < oriLonArr.length - 1; i++) {
|
sumLon += oriLonArr[i];
|
sumLat += oriLatArr[i];
|
heading.push(azimuthtwopoi(oriLonArr[i], oriLatArr[i], oriLonArr[i + 1], oriLatArr[i + 1]));
|
distance.push(getFlatternDistance(oriLonArr[i], oriLatArr[i], oriLonArr[i + 1], oriLatArr[i + 1]));
|
}
|
let centerLon = sumLon / 4;
|
let centerLat = sumLat / 4;
|
return {centerLon, centerLat, heading, distance};
|
}
|
//获取高德导航路径
|
function amapDriving(startPoi,endPoi){
|
let driving = new AMap.Driving();
|
driving.search(startPoi.split(','), endPoi.split(','), function(status, result) {
|
console.log(status)
|
console.log(result)
|
return result;
|
})
|
}
|
//通视线判断(交点与目标点距离小于1米视为通视)
|
function computeVisible(origin, target) {
|
let direction = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(target,origin, new Cesium.Cartesian3()), new Cesium.Cartesian3());
|
let drillPickHeight = 0;
|
let drillPickPoi = Cesium.Cartesian3.fromDegrees(0,0,0);
|
// 建立射线
|
var ray = new Cesium.Ray(origin, direction);
|
var drillPickresults = viewer.scene.drillPickFromRay(ray, 10);
|
for (var i = 0; i < drillPickresults.length; i++) {
|
if(!drillPickresults[i].object || (drillPickresults[i].object && !drillPickresults[i].object.id)){
|
let resultHeight = Cesium.Cartographic.fromCartesian(drillPickresults[i].position).height;
|
let resultPoi = drillPickresults[i].position;
|
drillPickHeight = resultHeight >= drillPickHeight ? resultHeight : drillPickHeight;
|
drillPickPoi = resultHeight >= drillPickHeight ? resultPoi : drillPickPoi;
|
}
|
}
|
let measureValue = Cesium.Cartesian3.distance(drillPickPoi, target);
|
return measureValue<3;
|
}
|
//计算空间两点距离
|
function getSpaceDistance(positions){
|
let distance = 0;
|
for (var i = 0; i < positions.length - 1; i++) {
|
var point1cartographic = Cesium.Cartographic.fromCartesian(positions[i]);
|
var point2cartographic = Cesium.Cartographic.fromCartesian(positions[i+1]);
|
/**根据经纬度计算出距离**/
|
var geodesic = new Cesium.EllipsoidGeodesic();
|
geodesic.setEndPoints(point1cartographic, point2cartographic);
|
var s = geodesic.surfaceDistance;
|
//console.log(Math.sqrt(Math.pow(distance, 2) + Math.pow(endheight, 2)));
|
//返回两点之间的距离
|
s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2));
|
distance = distance + s;
|
}
|
return distance.toFixed(2);
|
}
|
|
/**
|
* 对Date的扩展,将 Date 转化为指定格式的String
|
* 月(M)、日(d)、12小时(h)、24小时(H)、分(m)、秒(s)、周(E)、季度(q) 可以用 1-2 个占位符
|
* 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
|
* eg:
|
* (new Date()).pattern("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
|
* (new Date()).pattern("yyyy-MM-dd E HH:mm:ss") ==> 2009-03-10 二 20:09:04
|
* (new Date()).pattern("yyyy-MM-dd EE hh:mm:ss") ==> 2009-03-10 周二 08:09:04
|
* (new Date()).pattern("yyyy-MM-dd EEE hh:mm:ss") ==> 2009-03-10 星期二 08:09:04
|
* (new Date()).pattern("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18
|
*/
|
Date.prototype.pattern = function (fmt) {
|
let o = {
|
"M+": this.getMonth() + 1, //月份
|
"d+": this.getDate(), //日
|
"h+": this.getHours() % 12 === 0 ? 12 : this.getHours() % 12, //小时
|
"H+": this.getHours(), //小时
|
"m+": this.getMinutes(), //分
|
"s+": this.getSeconds(), //秒
|
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
|
"S": this.getMilliseconds() //毫秒
|
};
|
let week = {
|
"0": "/u65e5",
|
"1": "/u4e00",
|
"2": "/u4e8c",
|
"3": "/u4e09",
|
"4": "/u56db",
|
"5": "/u4e94",
|
"6": "/u516d"
|
};
|
if (/(y+)/.test(fmt)) {
|
fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
|
}
|
if (/(E+)/.test(fmt)) {
|
fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? "/u661f/u671f" : "/u5468") : "") + week[this.getDay() + ""]);
|
}
|
for (var k in o) {
|
if (new RegExp("(" + k + ")").test(fmt)) {
|
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
|
}
|
}
|
return fmt;
|
};
|