刚入门cesium,学着社区大佬做地图开挖,代码里面不知道是哪的问题,始终无法实现,只能显示挖掘区域
import { onMounted } from "vue"
import * as Cesium from "cesium"
import "./Widgets/widgets.css"
import CesiumInitializer from "./utils/cesiumInitializer"
let viewer = null
let handler = null
let isDrawing = false
let polygonPoints = []
let polygonEntity = null
let clippingPlaneCollection = null
let globe = null
onMounted(async () => {
viewer = await CesiumInitializer.createViewer("cesiumContainer", {
imageryProvider: new Cesium.UrlTemplateImageryProvider({
url: "http://www.google.cn/maps/vt?lyrs=s@716&x={x}&y={y}&z={z}"
}),
selectionIndicator: false,
infoBox: false
})
globe = viewer.scene.globe
globe.depthTestAgainstTerrain = true
// 初始化裁剪平面集合
clippingPlaneCollection = new Cesium.ClippingPlaneCollection({
edgeWidth: 1.0,
edgeColor: Cesium.Color.WHITE,
enabled: true
// unionClippingRegions: false
})
// 应用裁剪平面到地球并设置额外属性
globe.clippingPlanes = clippingPlaneCollection
globe.backFaceCulling = true // 启用背面剔除
globe.showSkirts = true // 显示地形裙边
globe.clippingPlanesEnabled = true
// 初始化事件处理器
handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
// 绑定鼠标左键点击事件绘制多边形顶点
handler.setInputAction((movement) => {
const cartesian = getClickPosition(movement.position)
if (!cartesian) return
if (!isDrawing) {
// 开始绘制
startDrawing(cartesian)
} else {
// 添加新顶点
addPolygonPoint(cartesian)
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
// 绑定鼠标移动事件更新多边形
handler.setInputAction((movement) => {
if (isDrawing && polygonPoints.length > 0) {
const cartesian = getClickPosition(movement.endPosition)
if (cartesian) {
updatePolygonPreview(cartesian)
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
// 绑定右键点击事件挖空区域
handler.setInputAction(() => {
if (isDrawing) {
// 完成绘制
finishDrawing()
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
// 设置初始相机位置
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(116.39, 39.9, 10000),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-45),
roll: 0
}
})
// 清除多边形
document.addEventListener("keydown", (e) => {
if (e.key === "Escape") {
clippingPlaneCollection.planes = []
viewer.entities.removeAll()
}
})
})
// 获取点击位置的三维坐标
function getClickPosition(screenPosition) {
const ray = viewer.camera.getPickRay(screenPosition)
return globe.pick(ray, viewer.scene)
}
// 开始绘制多边形
function startDrawing(initialPoint) {
isDrawing = true
polygonPoints = [initialPoint]
// 创建多边形实体用于预览
polygonEntity = viewer.entities.add({
// 创建点
// position: initialPoint,
// point: {
// pixelSize: 10,
// color: Cesium.Color.RED,
// outlineColor: Cesium.Color.WHITE,
// outlineWidth: 4
// }
polygon: {
hierarchy: new Cesium.CallbackProperty(getPolygonHierarchy, false),
material: Cesium.Color.BLUE.withAlpha(0.3),
outline: true,
outlineColor: Cesium.Color.BLACK
}
})
}
// 添加多边形顶点
function addPolygonPoint(point) {
polygonPoints.push(point)
}
// 更新多边形
function updatePolygonPreview(lastPoint) {
// 创建临时数组,包含已有顶点和当前鼠标位置
const tempPoints = [...polygonPoints, lastPoint]
// 更新多边形层级
polygonEntity.polygon.hierarchy = new Cesium.CallbackProperty(() => {
return new Cesium.PolygonHierarchy(tempPoints)
}, false)
}
// 获取多边形层级
function getPolygonHierarchy() {
return new Cesium.PolygonHierarchy(polygonPoints)
}
// 挖空地形
function createPolygonClipArea(points) {
if (points.length < 3) {
alert("至少需要3个顶点才能创建多边形裁剪区域")
return
}
// 计算每个边的裁剪平面
const clippingPlanes = []
const pointsLength = points.length
for (let i = 0; i < pointsLength; ++i) {
const p1 = points[i]
const p2 = points[(i + 1) % pointsLength]
// 计算边的中点
const midpoint = Cesium.Cartesian3.add(p1, p2, new Cesium.Cartesian3())
Cesium.Cartesian3.multiplyByScalar(midpoint, 0.5, midpoint)
// 计算法向量(使用中点和叉乘)
const up = Cesium.Cartesian3.normalize(midpoint, new Cesium.Cartesian3())
const right = Cesium.Cartesian3.subtract(p2, p1, new Cesium.Cartesian3())
Cesium.Cartesian3.normalize(right, right)
// 通过叉乘计算法向量(右手坐标系)
let normal = Cesium.Cartesian3.cross(right, up, new Cesium.Cartesian3())
Cesium.Cartesian3.normalize(normal, normal)
// 计算平面距离
const originCenteredPlane = new Cesium.Plane(normal, 0.0)
const distance = Cesium.Plane.getPointDistance(originCenteredPlane, midpoint)
clippingPlanes.push(new Cesium.ClippingPlane(normal, distance))
}
// 设置裁剪平面属性
clippingPlaneCollection.planes = clippingPlanes
clippingPlaneCollection.edgeWidth = 1.0
clippingPlaneCollection.edgeColor = Cesium.Color.WHITE
clippingPlaneCollection.enabled = true
// 预览裁剪区域
viewer.entities.add({
polygon: {
hierarchy: new Cesium.PolygonHierarchy(points),
material: Cesium.Color.RED.withAlpha(0.3),
outline: true,
outlineColor: Cesium.Color.RED
}
})
console.log(`挖空区域已创建,顶点数: ${points.length},裁剪平面数: ${clippingPlanes.length}`)
}
// 完成绘制并挖空区域
function finishDrawing() {
console.log(polygonPoints)
createPolygonClipArea(polygonPoints)
// 重置绘制状态
isDrawing = false
polygonPoints = []
polygonEntity = null
}