代码迁移
This commit is contained in:
32
src/Obj/Analysis/TerrainExcavation/_element.js
Normal file
32
src/Obj/Analysis/TerrainExcavation/_element.js
Normal 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 }
|
459
src/Obj/Analysis/TerrainExcavation/index.js
Normal file
459
src/Obj/Analysis/TerrainExcavation/index.js
Normal 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;
|
Reference in New Issue
Block a user