import { showDeviceDetail, deviceDetail, className, dialogPositon } from "@/store"; export function addTerrain(url) { // console.log("加载地形"); var terrainProvider = new Cesium.CesiumTerrainProvider({ // 切片地址 // url: `${process.env.VUE_APP_MAP_API}/DEM/`, // url: `{MAP_API}/dixing/切片/`, // url: `{MAP_API}/QJDEM/`, url, // 地形服务源自SuperMap iServer发布时需设置isSct为true isSct: false, invisibility: true, }); viewer.terrainProvider = terrainProvider; } export function addImageLayer(url) { const imageLayer = viewer.scene.imageryLayers.addImageryProvider( new Cesium.UrlTemplateImageryProvider({ url, // url: `{MAP_API}/yingxiang/切片/{z}/{x}/{y}.png`, // url: `{MAP_API}/QJZXSQYX/{z}/{x}/{y}.png`, // maximumLevel: 16, }) ); } export async function addTileset(url) { const tileset = await Cesium.Cesium3DTileset.fromUrl(url); viewer.scene.primitives.add(tileset); console.log("palaceTileset", tileset); // Cesium Cesium3DTileset 贴地 tileset.heightReference = Cesium.HeightReference.RELATIVE_TO_GROUND; tileset.clampToGround = true; //高度偏差,正数为向上偏,负数为向下偏,根据真实的模型位置不断进行调整 var heightOffset = 0; let name = tileset._url || ""; //计算tileset的绑定范围 var boundingSphere = tileset.boundingSphere; //计算中心点位置 var cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center); //计算中心点位置坐标 var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0); //偏移后的三维坐标 var offset = Cesium.Cartesian3.fromRadians( cartographic.longitude, cartographic.latitude, heightOffset ); var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3()); //tileset.modelMatrix转换 if (heightOffset) { tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation); } return tileset; } let entities = []; export function createPoint(option) { const { id, type = "", name = "默认名称", view, latitude, longitude, height, callback, imgWidth = 56, imgHeight = 67, showBillboard = true, showLabel = true, className = "device", } = option; let position = Cesium.Cartesian3.fromDegrees(longitude, latitude, 50); let model = { id, name: name, position: position, type: type, view: view, attrs: option, className: className, label: { // 文本。支持显式换行符“ \ n” text: name || "默认标签", // 字体样式,以CSS语法指定字体 font: "14pt Source Han Sans CN", // 字体颜色 fillColor: type.includes("active") ? Cesium.Color.AQUA : Cesium.Color.WHITE, // 背景颜色 backgroundColor: showBillboard ? Cesium.Color.BLACK.withAlpha(0.5) : Cesium.Color.SKYBLUE, // 是否显示背景颜色 showBackground: true, // 字体边框 outline: false, // 字体边框颜色 outlineColor: Cesium.Color.WHITE, // 字体边框尺寸 outlineWidth: 0, // 应用于图像的统一比例。比例大于会1.0放大标签,而比例小于会1.0缩小标签。 scale: 1.0, scaleByDistance: new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.5), // 设置样式:FILL:填写标签的文本,但不要勾勒轮廓;OUTLINE:概述标签的文本,但不要填写;FILL_AND_OUTLINE:填写并概述标签文本。 style: Cesium.LabelStyle.FILL_AND_OUTLINE, // 相对于坐标的水平位置 verticalOrigin: Cesium.VerticalOrigin.CENTER, // 相对于坐标的水平位置 horizontalOrigin: Cesium.HorizontalOrigin.CENTER, // 该属性指定标签在屏幕空间中距此标签原点的像素偏移量 pixelOffset: new Cesium.Cartesian2(0, -40), // pixelOffset: new Cesium.Cartesian2(0, 0), // 显示在距相机的距离处的属性,多少区间内是可以显示的 distanceDisplayCondition: type.includes("河流") ? new Cesium.DistanceDisplayCondition(0, 5000000) : new Cesium.DistanceDisplayCondition(0, 50000), heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND, // heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, // 是否显示 show: showLabel, }, }; model.billboard = { // 图像地址,URI或Canvas的属性 image: type ? `/images/poi/${type}.png` : `/images/poi/村庄.png`, // 高度(以像素为单位) height: imgHeight || 20, // 宽度(以像素为单位) width: imgWidth || 20, // 逆时针旋转 // 大小是否以米为单位 sizeInMeters: false, // 相对于坐标的垂直位置 verticalOrigin: Cesium.VerticalOrigin.CENTER, // 相对于坐标的水平位置 horizontalOrigin: Cesium.HorizontalOrigin.CENTER, // 该属性指定标签在屏幕空间中距此标签原点的像素偏移量 pixelOffset: new Cesium.Cartesian2(0, 3), // 应用于图像的统一比例。比例大于会1.0放大标签,而比例小于会1.0缩小标签。 scale: 0.8, scaleByDistance: new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.5), // 显示在距相机的距离处的属性,多少区间内是可以显示的 distanceDisplayCondition: type.includes("河流") ? new Cesium.DistanceDisplayCondition(0, 5000000) : new Cesium.DistanceDisplayCondition(0, 50000), // 是否显示 show: showBillboard, heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND, backgroundColor: showBillboard ? Cesium.Color.BLACK.withAlpha(0.8) : Cesium.Color.SKYBLUE, }; const entity = viewer.entities.add(model); entities.push(entity); return entity; } export function removeEntities() { entities.forEach(entity => { // viewer.entities.remove(entity) entity.show = false; }); // entities = [] } function removeHandler() { if (interativeHandler != null && Cesium.defined(interativeHandler)) { //清除添加的楼栋包围盒 entities.forEach(entity => { viewer.entities.remove(entity); }); entities = []; this.interativeHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); this.interativeHandler = null; const highlightedFeature = this.highlightedFeature; if (Cesium.defined(highlightedFeature.feature)) { highlightedFeature.feature.color = new Cesium.Color(); this.highlightedFeature.feature = null; } } } export function initHandler() { const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); handler.setInputAction(movement => { const position = getPickPositon(movement.position); console.log("getPickPositon", position); const picked = viewer.scene.pick(movement.position); const id = picked?.id?.id; console.log("picked", picked); if (Cesium.defined(picked) && id) { const entity = picked?.id; if (entity && entity.className) { showDeviceDetail.value = true; deviceDetail.value = entity.attrs; className.value = entity.className; dialogPositon.value = entity.position._value; } // const callback = this.eventMap.get(id) // if (callback && typeof callback === "function") { // callback(picked.id) // } // this.resetAllPointColor(picked.id.id) } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); } export function dbClickHandler() { const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); handler.setInputAction(movement => { const picked = viewer.scene.pick(movement.position); const id = picked?.id?.id; if (Cesium.defined(picked) && id) { const type = picked?.id?.type; const view = picked?.id?.view; if (view) { view.duration = 5; // view.easingFunction = Cesium.EasingFunction.QUADRATIC_IN_OUT, viewer.scene.camera.flyTo(view); } else { viewer.flyTo(picked.id); } } }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); } window.getCameraPosition = function getCameraPosition() { const camera = viewer.scene.camera; const position = camera.position; const cartographic = Cesium.Cartographic.fromCartesian(position); const longitude = Cesium.Math.toDegrees(cartographic.longitude); const latitude = Cesium.Math.toDegrees(cartographic.latitude); const height = cartographic.height; const pitch = camera.pitch; const roll = camera.roll; const heading = camera.heading; return { destination: position, orientation: { pitch, roll, heading, }, }; }; export function calcPosition(positionArray) { if (!Array.isArray(positionArray)) { return []; } const result = positionArray.map(item => { const position = cartesianToXY(item); return [position.longitude, position.latitude, position.height]; }); console.log("calcPosition", result); return result; } window.calcPosition = calcPosition; export function cartesianToXY(cartesian) { var scene = viewer.scene; var ellipsoid = scene.globe.ellipsoid; if (cartesian) { var cartographic = ellipsoid.cartesianToCartographic(cartesian); var longitude = Cesium.Math.toDegrees(cartographic.longitude).toFixed(7); var latitude = Cesium.Math.toDegrees(cartographic.latitude).toFixed(7); // 地理高度 var height = (cartographic.height + 1).toFixed(2); // 相机高度 // var height = viewer.camera.positionCartographic.height.toFixed(0); // 方向 围绕Z轴旋转 var heading = Cesium.Math.toDegrees(viewer.camera.heading); // 倾斜角度 围绕Y轴旋转 var pitch = Cesium.Math.toDegrees(viewer.camera.pitch); // 围绕X轴旋转 var roll = Cesium.Math.toDegrees(viewer.camera.roll); return { longitude: Number(longitude), latitude: Number(latitude), height: Number(height), heading: Number(heading), pitch: Number(pitch), roll: Number(roll), }; } } export function initView(option) { let view = { destination: { x: -2256394.3617862244, y: 4620836.918376569, z: 4049368.785453873, }, orientation: { pitch: -0.7862789841268825, roll: 0.00003453626288862921, heading: 0.18702357350897447, }, }; viewer.scene.camera.flyTo(view); } //获取点击坐标 export function getPickPositon(position) { let cartesianCoordinate = viewer.scene.pickPosition(position); if (!cartesianCoordinate) { return null; } let cartographic = Cesium.Cartographic.fromCartesian(cartesianCoordinate); let longitude = Cesium.Math.toDegrees(cartographic.longitude); let latitude = Cesium.Math.toDegrees(cartographic.latitude); let height = cartographic.height; let result = { longitude: Number(longitude.toFixed(6)), latitude: Number(latitude.toFixed(6)), altitude: Number(height.toFixed(2)), }; return result; } // 坐标转换函数 function transformCoordinates(coordinates) { return coordinates.map(ring => ring.map(point => { const [lon, lat] = utmToWgs84(point[0], point[1]); return [lon, lat, point[2]]; // 保留高程 }) ); } function utmToWgs84(x, y) { return proj4("EPSG:32650", "EPSG:4326", [x, y]); } export function geomToGeoJSON(geomString) { const geom = JSON.parse(geomString); // 定义 UTM Zone 50N 投影 // proj4.defs("EPSG:32650", "+proj=utm +zone=40 +datum=WGS84 +units=m +no_defs") // 生成 GeoJSON const geoJson = { type: "Feature", properties: {}, geometry: { type: geom.type, coordinates: geom.coordinates, }, }; return geoJson; }