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)
|
return Cesium.Cartesian3.distance(start, end)
|
}
|
|
/**
|
* 地点坐标计算中心点
|
* @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, droneHeight = null) => {
|
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)
|
|
let FinalHeight =
|
Number(data[index]?.['ellipsoidHeight']?.['#text']) + Number(item.height)
|
|
if (droneHeight) {
|
FinalHeight = Number(data[index]?.['ellipsoidHeight']?.['#text']) + droneHeight
|
}
|
|
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
|
}
|
}
|
|
/**
|
* 飞到中心点并且所有点在可视范围
|
* @param lngLatArr
|
* @param viewer
|
* @param rangeMultiple 范围倍数越大飞的越高默认2
|
*/
|
export function flyVisual(lngLatArr,viewer,rangeMultiple = 2) {
|
if (!Array.isArray(lngLatArr) || lngLatArr.length === 0) return
|
const positions = lngLatArr.map(([lon, lat]) =>
|
Cesium.Cartesian3.fromDegrees(Number(lon), Number(lat))
|
)
|
// 计算包围盒 BoundingSphere(所有点的外接球)
|
const boundingSphere = Cesium.BoundingSphere.fromPoints(positions)
|
viewer.camera.flyToBoundingSphere(boundingSphere, {
|
duration: 0,
|
offset: new Cesium.HeadingPitchRange(0, 0, boundingSphere.radius * rangeMultiple),
|
})
|
}
|
|
// 获取视口地图中心点
|
export function getMapCenterPoint(viewer) {
|
const centerResult = viewer.camera.pickEllipsoid(
|
new Cesium.Cartesian2(
|
viewer.canvas.clientWidth / 2,
|
viewer.canvas.clientHeight / 2
|
)
|
);
|
const curPosition = Cesium.Ellipsoid.WGS84.cartesianToCartographic(centerResult);
|
const longitude = (curPosition.longitude * 180) / Math.PI;
|
const latitude = (curPosition.latitude * 180) / Math.PI;
|
return { longitude, latitude };
|
}
|