代码迁移

This commit is contained in:
zh
2025-07-03 13:54:01 +08:00
parent b04de8a084
commit 2a4da33e62
985 changed files with 358292 additions and 13 deletions

View File

@ -0,0 +1,32 @@
function html() {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label" style="flex: 0 0 70px;">挖掘高度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="0" max="5000000" name="height">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">绘制开挖区域</span>
<button class="start-excavation"><svg class="icon-edit"><use xlink:href="#yj-icon-edit"></use></svg>绘制</button>
</div>
<div class="col">
<span class="label">清除开挖区域</span>
<button class="clean-excavation"><svg class="icon-close"><use xlink:href="#yj-icon-close"></use></svg>清除</button>
</div>
</div>
</div>
`
}
export { html }

View File

@ -0,0 +1,459 @@
import Tools from "../../../Tools";
import DrawPolygon from "../../../Draw/drawPolygon"
import Dialog from '../../../BaseDialog';
import { html } from "./_element";
let ExcavationFaces = []
class TerrainExcavation extends Tools {
/**
* @constructor
* @description 地形开挖
* @param sdk
* */
constructor(sdk, options = {}) {
super(sdk)
this.viewer = sdk.viewer
this.options = options || {};
this.options.height = (this.options.height || this.options.height === 0) ? this.options.height : 10;
this.options.show = (this.options.show || this.options.show === false) ? this.options.show : true;
this.bottomImg = this.getSourceRootPath() + '/img/excavationregion_top.jpg';
this.wallImg = this.getSourceRootPath() + '/img/excavationregion_side.jpg';
this.splitNum = Cesium.defaultValue(options.splitNum, 50);
this.Draw = new DrawPolygon(this.sdk)
this.bottomMaterial = Cesium.Material.fromType('Color', {
color: Cesium.Color.fromAlpha(Cesium.Color.fromCssColorString('#735d4f'))
})
this.wallMaterial = Cesium.Material.fromType('Color', {
color: Cesium.Color.fromAlpha(Cesium.Color.fromCssColorString('#976b4e'))
})
let imageBottom = new Image();
let wallBottom = new Image();
imageBottom.src = this.bottomImg;
wallBottom.src = this.wallImg;
imageBottom.crossOrigin = "Anonymous";
wallBottom.crossOrigin = "Anonymous";
imageBottom.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = imageBottom.width;
canvas.height = imageBottom.height;
const context = canvas.getContext('2d');
context.drawImage(imageBottom, 0, 0, imageBottom.width, imageBottom.height);
const base64 = canvas.toDataURL('image/jpg');
this.bottomMaterial = new Cesium.Material({
fabric: {
type: "Image",
uniforms: {
image: base64,
},
},
});
if (this.bottomSurface) {
this.bottomSurface.appearance.material = this.bottomMaterial;
}
}
wallBottom.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = wallBottom.width;
canvas.height = wallBottom.height;
const context = canvas.getContext('2d');
context.drawImage(wallBottom, 0, 0, wallBottom.width, wallBottom.height);
const base64 = canvas.toDataURL('image/jpg');
this.wallMaterial = new Cesium.Material({
fabric: {
type: "Image",
uniforms: {
image: base64,
},
},
});
if (this.wellWall) {
this.wellWall.appearance.material = this.wallMaterial;
}
}
this.init();
}
get show() {
return this.options.show
}
set show(v) {
this.options.show = v;
this.switchExcavate(v);
}
get height() {
return this.options.height
}
set height(v) {
this.options.height = v;
// this.updateExcavateDepth(v);
}
init() {
TerrainExcavation.edit(this, true)
}
static async edit(that, state) {
if (that._DialogObject && that._DialogObject.close) {
that._DialogObject.close()
that._DialogObject = null
}
if (state) {
that._DialogObject = await new Dialog(that.sdk.viewer._container, {
title: '地形开挖',
closeCallBack: () => {
},
})
await that._DialogObject.init()
that._DialogObject._element.body.className = that._DialogObject._element.body.className + ' terrain-excavation'
let contentElm = document.createElement('div');
contentElm.innerHTML = html()
that._DialogObject.contentAppChild(contentElm)
// 开始
let e_start = contentElm.getElementsByClassName('start-excavation')[0]
e_start.addEventListener('click', () => {
that.startCreate()
});
// 清除
let e_clean = contentElm.getElementsByClassName('clean-excavation')[0]
e_clean.addEventListener('click', () => {
that.clear()
});
// 高度值
let e_height = contentElm.querySelector("input[name='height']")
e_height.value = that.height
e_height.addEventListener('change', (e) => {
let value = e.target.value
value = Number(value)
if (value < 0.01) {
value = 0.01
e.target.value = value
that.height = value;
}
})
e_height.addEventListener('blur', (e) => {
let value = e.target.value
value = Number(value)
if ((e.target.max) && value > Number(e.target.max)) {
value = Number(e.target.max)
}
if (value < 0.01) {
value = 0.01
}
e.target.value = value
that.height = value;
});
} else {
if (that._DialogObject && that._DialogObject.close) {
that._DialogObject.close()
that._DialogObject = null
}
}
}
startCreate() {
this.Draw.start((e, positions) => {
if (!positions || positions.length <= 2) {
window.ELEMENT && window.ELEMENT.Message({
message: '至少拥有三个坐标位置!',
type: 'warning',
duration: 1500
});
return
}
if(!this.isConvex(positions)) {
window.ELEMENT && window.ELEMENT.Message({
message: '不支持凹多边形',
type: 'warning',
duration: 1500
});
console.log('不支持凹多边形')
return
}
this.updateData(positions)
})
}
updateData(activePoints) {
let viewer = this.viewer;
this.clear();
let clippingPlanesList = [];
let array = []
for (let i = 0; i < activePoints.length; i++) {
array.push([activePoints[i].lng, activePoints[i].lat])
}
array.push([activePoints[0].lng, activePoints[0].lat])
let clockwiseRing = turf.lineString(array);
// 是否顺时针
let boolDiff = turf.booleanClockwise(clockwiseRing);
this.excavateMinHeight = 9999;
for (let index = 0; index < activePoints.length; ++index) {
let s = (index + 1) % activePoints.length;
let position1 = Cesium.Cartesian3.fromDegrees(activePoints[index].lng, activePoints[index].lat, activePoints[index].alt)
let position2 = Cesium.Cartesian3.fromDegrees(activePoints[s].lng, activePoints[s].lat, activePoints[s].alt)
let curMidPoint = Cesium.Cartesian3.midpoint(
position1,
position2,
new Cesium.Cartesian3()
);
let cartographic = Cesium.Cartographic.fromCartesian(position1);
let curHeight =
viewer.scene.globe.getHeight(cartographic) || cartographic.height;
if (curHeight < this.excavateMinHeight) {
this.excavateMinHeight = curHeight;
}
let curMidPointNormal = Cesium.Cartesian3.normalize(
curMidPoint,
new Cesium.Cartesian3()
);
let curMidPointDifference = boolDiff
? Cesium.Cartesian3.subtract(
position1,
curMidPoint,
new Cesium.Cartesian3()
)
: Cesium.Cartesian3.subtract(
position2,
curMidPoint,
new Cesium.Cartesian3()
);
curMidPointDifference = Cesium.Cartesian3.normalize(
curMidPointDifference,
curMidPointDifference
);
let curMidPointCross = Cesium.Cartesian3.cross(
curMidPointDifference,
curMidPointNormal,
new Cesium.Cartesian3()
);
curMidPointCross = Cesium.Cartesian3.normalize(
curMidPointCross,
curMidPointCross
);
let plane = new Cesium.Plane(curMidPointCross, 0);
let distance = Cesium.Plane.getPointDistance(plane, curMidPoint);
clippingPlanesList.push(
new Cesium.ClippingPlane(curMidPointCross, distance)
);
}
this.viewer.scene.globe.clippingPlanes = new Cesium.ClippingPlaneCollection(
{
planes: clippingPlanesList,
edgeWidth: 1,
edgeColor: Cesium.Color.WHITE,
enabled: true,
}
);
this.prepareWell(activePoints);
this.createWell(this.wellData);
// this.viewer.entities.remove(this.drawGeomtry);
}
clear() {
if (this.viewer.scene.globe.clippingPlanes) {
this.viewer.scene.globe.clippingPlanes.removeAll();
this.viewer.scene.primitives.remove(this.bottomSurface);
this.viewer.scene.primitives.remove(this.wellWall);
this.viewer.scene.render();
}
for (let i = ExcavationFaces.length - 1; i >= 0; i--) {
this.viewer.scene.primitives.remove(ExcavationFaces[i]);
}
ExcavationFaces = []
this.Draw && this.Draw.end()
}
destroy() {
this.clear()
}
//计算并更新wellData
prepareWell(activePoints) {
let pointLength = activePoints.length;
let heightDiff = this.excavateMinHeight - this.height;
let no_height_top = [],
bottom_pos = [],
lerp_pos = [];
for (let l = 0; l < pointLength; l++) {
let u = l == pointLength - 1 ? 0 : l + 1;
let point0 = [
Cesium.Cartographic.fromDegrees(activePoints[l].lng, activePoints[l].lat, activePoints[l].alt).longitude,
Cesium.Cartographic.fromDegrees(activePoints[l].lng, activePoints[l].lat, activePoints[l].alt).latitude,
];
let point1 = [
Cesium.Cartographic.fromDegrees(activePoints[u].lng, activePoints[u].lat, activePoints[u].alt).longitude,
Cesium.Cartographic.fromDegrees(activePoints[u].lng, activePoints[u].lat, activePoints[u].alt).latitude,
];
if (0 == l) {
lerp_pos.push(new Cesium.Cartographic(point0[0], point0[1]));
bottom_pos.push(
Cesium.Cartesian3.fromRadians(point0[0], point0[1], heightDiff)
);
no_height_top.push(
Cesium.Cartesian3.fromRadians(point0[0], point0[1], 0)
);
}
for (let p = 1; p <= this.splitNum; p++) {
let m = Cesium.Math.lerp(point0[0], point1[0], p / this.splitNum);
let g = Cesium.Math.lerp(point0[1], point1[1], p / this.splitNum);
(l == pointLength - 1 && p == this.splitNum) ||
(lerp_pos.push(new Cesium.Cartographic(m, g)),
bottom_pos.push(Cesium.Cartesian3.fromRadians(m, g, heightDiff)),
no_height_top.push(Cesium.Cartesian3.fromRadians(m, g, 0)));
}
}
this.wellData = {
lerp_pos: lerp_pos,
bottom_pos: bottom_pos,
no_height_top: no_height_top,
};
}
//开始创建底面和侧面
createWell(wallData) {
let $this = this;
if (this.viewer.terrainProvider._layers) {
this.createBottomSurface(wallData.bottom_pos);
let positions = Cesium.sampleTerrainMostDetailed(
this.viewer.terrainProvider,
wallData.lerp_pos
);
positions.then((pos) => {
let positionList = [];
for (let index = 0; index < pos.length; index++) {
const element = pos[index];
let curPos = Cesium.Cartesian3.fromRadians(
element.longitude,
element.latitude,
element.height
);
positionList.push(curPos);
}
$this.createWellWall(wallData.bottom_pos, positionList);
});
} else {
this.createBottomSurface(wallData.bottom_pos);
this.createWellWall(wallData.bottom_pos, wallData.no_height_top);
}
}
//坐标转换,转出经纬度格式
ellipsoidToDegree(pos) {
let cartesian3 = new Cesium.Cartesian3(pos.x, pos.y, pos.z);
let cartographic =
this.viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian3);
return {
longitude: Cesium.Math.toDegrees(cartographic.longitude),
latitude: Cesium.Math.toDegrees(cartographic.latitude),
altitude: cartographic.height,
};
}
//创建地形开挖的底面对象
createBottomSurface(points) {
if (points.length) {
let minHeight = this.getMinHeight(points);
let positions = [];
for (let i = 0; i < points.length; i++) {
let curPoint = this.ellipsoidToDegree(points[i]);
positions.push(curPoint.longitude, curPoint.latitude, minHeight);
}
let polygon = new Cesium.PolygonGeometry({
polygonHierarchy: new Cesium.PolygonHierarchy(
Cesium.Cartesian3.fromDegreesArrayHeights(positions)
),
perPositionHeight: true,
});
let appearance = new Cesium.MaterialAppearance({
translucent: false,
flat: true,
material: this.bottomMaterial,
});
this.bottomSurface = new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: Cesium.PolygonGeometry.createGeometry(polygon),
}),
appearance: appearance,
asynchronous: false,
});
ExcavationFaces.push(this.bottomSurface);
this.viewer.scene.primitives.add(this.bottomSurface);
}
}
// 创建地形开挖的侧面墙对象
createWellWall(bottomPos, positionList) {
let minHeight = this.getMinHeight(bottomPos);
let maxHeights = [],
minHeights = [];
for (let i = 0; i < positionList.length; i++) {
maxHeights.push(this.ellipsoidToDegree(positionList[i]).altitude);
minHeights.push(minHeight);
}
let wall = new Cesium.WallGeometry({
positions: positionList,
maximumHeights: maxHeights,
minimumHeights: minHeights,
});
let geometry = Cesium.WallGeometry.createGeometry(wall);
let appearance = new Cesium.MaterialAppearance({
translucent: false,
flat: true,
material: this.wallMaterial,
});
this.wellWall = new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: geometry,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
Cesium.Color.GREY
),
},
id: "PitWall",
}),
appearance: appearance,
asynchronous: false,
});
ExcavationFaces.push(this.wellWall);
this.viewer.scene.primitives.add(this.wellWall);
}
//获取地形开挖最低点高程值
getMinHeight(points) {
let minHeight = 5000000;
let minPoint = null;
for (let i = 0; i < points.length; i++) {
let height = points[i]["z"];
if (height < minHeight) {
minHeight = height;
minPoint = this.ellipsoidToDegree(points[i]);
}
}
return minPoint.altitude;
}
switchExcavate(show) {
if (show) {
this.viewer.scene.globe.material = null;
this.wellWall.show = true;
this.bottomSurface.show = true;
} else {
this.viewer.scene.globe.material = null;
this.wellWall.show = false;
this.bottomSurface.show = false;
}
}
updateExcavateDepth(height) {
this.viewer.scene.primitives.remove(this.bottomSurface);
this.viewer.scene.primitives.remove(this.wellWall);
if (!this.wellData) {
return
}
let lerp_pos = this.wellData.lerp_pos;
let posList = [];
for (let n = 0; n < lerp_pos.length; n++) {
posList.push(
Cesium.Cartesian3.fromRadians(
lerp_pos[n].longitude,
lerp_pos[n].latitude,
this.excavateMinHeight - height
)
);
}
this.wellData.bottom_pos = posList;
this.createWell(this.wellData);
}
}
export default TerrainExcavation;