import * as Cesium from 'cesium';
|
import * as turf from '@turf/turf';
|
|
export const getLngLatDistance = (lat1, lng1, lat2, lng2) => {
|
const radLat1 = (lat1 * Math.PI) / 180.0;
|
const radLat2 = (lat2 * Math.PI) / 180.0;
|
const a = radLat1 - radLat2;
|
const b = (lng1 * Math.PI) / 180.0 - (lng2 * Math.PI) / 180.0;
|
let s =
|
2 *
|
Math.asin(
|
Math.sqrt(
|
Math.pow(Math.sin(a / 2), 2) +
|
Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2),
|
),
|
);
|
s = s * 6378.137; // EARTH_RADIUS;
|
s = Math.round(s * 10000) / 10000;
|
return s * 1000;
|
};
|
|
// 获取限polyline长度
|
export const getPolylineLength = (entity) => {
|
let length = 0;
|
|
// 获取Polyline的所有顶点位置
|
const positions = entity.polyline.positions.getValue();
|
|
for (let i = 0; i < positions.length - 1; ++i) {
|
const startPosition = positions[i];
|
const endPosition = positions[i + 1];
|
|
// 使用Cesium提供的distanceBetween函数计算两个顶点之间的距离
|
const distance = Cesium.Cartesian3.distance(startPosition, endPosition);
|
|
// 将每个顶点之间的距离相加得到总长度
|
length += distance;
|
}
|
|
return length;
|
};
|
|
// 创建三角广告牌
|
export const createTriangleMarker = (title, color) => {
|
// 创建canvas绘制广告牌
|
const billboard = document.createElement('canvas');
|
billboard.width = 30;
|
billboard.height = 30;
|
const ctx = billboard.getContext('2d');
|
ctx.beginPath();
|
ctx.moveTo(0, 0);
|
ctx.lineTo(30, 0);
|
ctx.lineTo(15, 22);
|
ctx.fillStyle = color;
|
ctx.fill();
|
ctx.font = '18px serif';
|
ctx.fillStyle = '#ffffff';
|
ctx.fillText(title, 10, 15);
|
ctx.closePath();
|
return billboard;
|
};
|
|
export const createCircleBillboard = (title, color) => {
|
const billboard = document.createElement('canvas');
|
const ctx = billboard.getContext('2d');
|
ctx.beginPath();
|
ctx.ellipse(150, 90, 11, 11, 0, 0, Math.PI * 2);
|
ctx.fillStyle = color;
|
ctx.fill();
|
ctx.font = 'bold 15px serif';
|
ctx.textAlign = 'center';
|
ctx.fillStyle = '#ffffff';
|
ctx.fillText(title, 150, 95);
|
ctx.closePath();
|
return billboard;
|
};
|
|
// 获取当前经纬度海拔
|
export const getHaeHeight = (start, end) => {
|
const ellipsoid = Cesium.Ellipsoid.WGS84; // 选择合适的椭圆体模型
|
// const { longitude, latitude, height } = start
|
// const { longitude: endLng, latitude: endLat, height: endHeight } = end
|
// const startC3Position = new Cesium.Cartographic(longitude, latitude, height)
|
// const endC3Position = new Cesium.Cartographic(endLng, endLat, endHeight)
|
// const startCartesianPosition = ellipsoid.cartographicToCartesian(startC3Position)
|
// const endCartesianPosition = ellipsoid.cartographicToCartesian(endC3Position)
|
// // 计算两个位置之间的距离
|
// const distance = new Cesium.EllipsoidGeodesic(startCartesianPosition, endCartesianPosition, ellipsoid)
|
// return distance
|
const { longitude, latitude, height } = end;
|
const cartographic = Cesium.Cartographic.fromDegrees(
|
longitude,
|
latitude,
|
height,
|
);
|
const cartesianPosition = ellipsoid.cartographicToCartesian(cartographic);
|
const haeHeight = ellipsoid.cartesianToCartographic(cartesianPosition).height;
|
return haeHeight;
|
};
|
|
// Cesium Cartesian3 转正常经纬度
|
export const cartesian3Convert = (cartesian3Position, viewer) => {
|
// 转换为经纬度
|
const ellipsoid = viewer.scene.globe.ellipsoid;
|
const cartographicPosition = Cesium.Cartographic.fromCartesian(
|
cartesian3Position,
|
ellipsoid,
|
);
|
const longitude = Cesium.Math.toDegrees(cartographicPosition.longitude);
|
const latitude = Cesium.Math.toDegrees(cartographicPosition.latitude);
|
const height = cartographicPosition.height;
|
|
// console.log('经度: ' + longitude);
|
// console.log('纬度: ' + latitude);
|
// console.log('高度: ' + height);
|
|
return {
|
longitude,
|
latitude,
|
height,
|
};
|
};
|
|
// Cesium Cartesian2 转正常经纬度
|
export const cartesian2Convert = (position, viewer) => {
|
const ellipsoid = viewer.scene.globe.ellipsoid;
|
const c3Position = viewer.scene.globe.pick(
|
viewer.camera.getPickRay(position),
|
viewer.scene,
|
);
|
const c2Postion = ellipsoid.cartesianToCartographic(c3Position);
|
const longitude = Cesium.Math.toDegrees(c2Postion.longitude);
|
const latitude = Cesium.Math.toDegrees(c2Postion.latitude);
|
return { longitude, latitude };
|
};
|
|
// 根据经纬度获取距离
|
export const getLnglatDist = (lng1, lat1, lng2, lat2) => {
|
const start = new Cesium.Cartesian3.fromDegrees(
|
Number(lng1),
|
Number(lat1),
|
0,
|
);
|
const end = new Cesium.Cartesian3.fromDegrees(Number(lng2), Number(lat2), 0);
|
const distance = Cesium.Cartesian3.distance(start, end);
|
return distance;
|
};
|
|
/**
|
* 地点坐标计算中心点
|
* @param coordinateList {Array<Array<Object>>} [[{lat, lng}]]
|
* @return { Object } {lat lng}
|
*/
|
export const getCenterPoint = (coordinateList) => {
|
coordinateList = coordinateList.map((item) => {
|
const [lng, lat] = item;
|
return [{ lat, lng }];
|
});
|
const geoCoordinateListFlat = coordinateList.reduce((s, v) => {
|
return (s = s.concat(v));
|
}, []);
|
const total = geoCoordinateListFlat.length;
|
let X = 0;
|
let Y = 0;
|
let Z = 0;
|
for (const g of geoCoordinateListFlat) {
|
const lat = (g.lat * Math.PI) / 180;
|
const lon = (g.lng * Math.PI) / 180;
|
const x = Math.cos(lat) * Math.cos(lon);
|
const y = Math.cos(lat) * Math.sin(lon);
|
const z = Math.sin(lat);
|
X += x;
|
Y += y;
|
Z += z;
|
}
|
|
X = X / total;
|
Y = Y / total;
|
Z = Z / total;
|
const Lon = Math.atan2(Y, X);
|
const Hyp = Math.sqrt(X * X + Y * Y);
|
const Lat = Math.atan2(Z, Hyp);
|
|
return { lng: (Lon * 180) / Math.PI, lat: (Lat * 180) / Math.PI };
|
};
|
|
/**
|
* @description: 计算两组经纬度中距离最短的两个点
|
* @param {*} lnglat1 [[xxx,xxx]]
|
* @param {*} lnglat2 [[xxx,xxx]]
|
* @return {*} { index: 1 }
|
*/
|
export const getShortestDistance = (lnglat1, lnglat2) => {
|
const arr = [];
|
lnglat1.forEach((v, i) => {
|
const [lng, lat] = v;
|
lnglat2.forEach((s, i2) => {
|
const [vLng, vLat] = s;
|
const distance = getLnglatDist(lng, lat, vLng, vLat);
|
arr.push({
|
distance,
|
index: [i, i2],
|
lnglat: [v, s],
|
});
|
});
|
});
|
const newArr = arr.sort((a, b) => a.distance - b.distance);
|
return newArr[0];
|
};
|
|
// 获取当前经纬度地形数据
|
export const getLnglatAltitude = (longitude, latitude, viewer) => {
|
return new Promise((resolve, reject) => {
|
// 假设 viewer 已经初始化并且 terrainProvider 是有效的
|
const terrainProvider = viewer?.terrainProvider;
|
|
// 创建 Cartographic 对象
|
const cartographic = Cesium.Cartographic.fromDegrees(longitude, latitude);
|
|
// 获取地形数据的Promise
|
const promise = Cesium.sampleTerrainMostDetailed(terrainProvider, [
|
cartographic,
|
]);
|
|
// 使用 Cesium.when 处理 Promise
|
promise
|
.then(function (updatedPositions) {
|
// updatedPositions 是一个数组,包含更新后的 Cartographic 对象
|
const updatedPosition = updatedPositions[0];
|
const height = updatedPosition.height;
|
|
resolve({
|
longitude,
|
latitude,
|
height,
|
});
|
// 在这里,你可以使用 height 值进行后续操作
|
})
|
.catch(function (error) {
|
// console.error('获取高程时发生错误:', error);
|
reject(error);
|
});
|
});
|
};
|
|
// 批量获取经纬度对应高度信息
|
export const getPositionsHeight = (data, viewer) => {
|
return new Promise((resolve, reject) => {
|
if (!data || !data.length) {
|
resolve([]);
|
|
return;
|
}
|
|
// 假设 viewer 已经初始化并且 terrainProvider 是有效的
|
const terrainProvider = viewer?.terrainProvider;
|
|
// 创建 Cartographic 对象
|
const cartographics = data.map((item) => {
|
const [lng, lat] = item?.['Point']?.['coordinates']?.['#text'].split(',');
|
|
return Cesium.Cartographic.fromDegrees(Number(lng), Number(lat));
|
});
|
|
// 获取地形数据的Promise
|
const promise = Cesium.sampleTerrainMostDetailed(
|
terrainProvider,
|
cartographics,
|
);
|
|
// 使用 Cesium.when 处理 Promise
|
promise
|
.then(function (updatedPositions) {
|
// updatedPositions 是一个数组,包含更新后的 Cartographic 对象
|
const newPosition = updatedPositions.map((item, index) => {
|
const longitude = Cesium.Math.toDegrees(item.longitude);
|
const latitude = Cesium.Math.toDegrees(item.latitude);
|
const FinalHeight =
|
Number(data[index]?.['ellipsoidHeight']?.['#text']) +
|
Number(item.height);
|
|
return {
|
...data[index],
|
longitude,
|
latitude,
|
FinalHeight,
|
customHeight: Number(item.height),
|
};
|
});
|
|
resolve(newPosition);
|
// 在这里,你可以使用 height 值进行后续操作
|
})
|
.catch(function (error) {
|
// console.error('获取高程时发生错误:', error);
|
reject(error);
|
});
|
});
|
};
|
|
// 获取面中最高点
|
export const getPolygonMaxHeight = (turfPolygon, viewer) => {
|
return new Promise((resolve, reject) => {
|
const turfExtent = turf.bbox(turfPolygon);
|
|
const turfSamplePoints = turf.pointGrid(turfExtent, 0.01, {
|
units: 'kilometers',
|
mask: turfPolygon,
|
});
|
|
// 假设 viewer 已经初始化并且 terrainProvider 是有效的
|
const terrainProvider = viewer?.terrainProvider;
|
|
const cesiumSamplePoints = [];
|
for (let i = 0; i < turfSamplePoints.features.length; i++) {
|
const coord = turfSamplePoints.features[i].geometry.coordinates;
|
cesiumSamplePoints.push(
|
Cesium.Cartographic.fromDegrees(coord[0], coord[1]),
|
);
|
}
|
|
// 获取地形数据的Promise
|
const promise = Cesium.sampleTerrainMostDetailed(
|
terrainProvider,
|
cesiumSamplePoints,
|
);
|
|
promise
|
.then(function (updatedPositions) {
|
const newPosition = updatedPositions.map((item) => Number(item.height));
|
|
resolve(Math.max(...newPosition));
|
})
|
.catch(function (error) {
|
reject(error);
|
});
|
});
|
};
|
|
// 展示当前的高度
|
export const getWaylineShowHeight = (positions) => {
|
const { lng, lat } = getCenterPoint(positions);
|
let maxDist = 0;
|
positions.forEach((item) => {
|
const [lng1, lat1] = item;
|
let pointsDist = getLnglatDist(lng1, lat1, lng, lat);
|
if (pointsDist > maxDist) {
|
maxDist = pointsDist;
|
}
|
});
|
return {
|
lng,
|
lat,
|
showHeight: maxDist * 8,
|
};
|
};
|
|
// 获取当前面是否有交叉点
|
export const isIntersection = (coordinates) => {
|
const polyDikuai = turf.polygon([coordinates]);
|
const result = turf.kinks(polyDikuai);
|
const resultFeatures = result.features;
|
if (resultFeatures.length == 0) {
|
//无相交
|
return false;
|
} else {
|
//有相交
|
return true;
|
}
|
};
|