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>} [[{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; } };