填挖结果

前端代码
let viewer=null
let baseHeight = 500
let tempEntities = []
const computeCutAndFillVolumeVoronoi = (positions) => {
const result = {
minHeight: Number.MAX_VALUE,
maxHeight: Number.MIN_VALUE,
cutVolume: 0.0,
fillVolume: 0.0,
baseArea: 0.0
};
const windowPositions = [];
positions.forEach(element => {
const cartographic = Cesium.Cartographic.fromCartesian(element);
baseHeight = Math.min(cartographic.height, baseHeight);
windowPositions.push(Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, element));
})
const bounds = getBounds(windowPositions);
const points = turf.randomPoint(50, { bbox: [bounds[0], bounds[1], bounds[2], bounds[3]] });
const mainPoly = Cartesian2turfPolygon(windowPositions);
const voronoiPolygons = turf.voronoi(points, { bbox: [bounds[0], bounds[1], bounds[2], bounds[3]] });
voronoiPolygons.features.forEach(element => {
const intersectPoints = intersect(mainPoly, element.geometry);
if (intersectPoints.length > 0) {
const cubeInfo = computeCubeInfo(intersectPoints);
if (baseHeight > cubeInfo.avgHeight) {
result.fillVolume += (baseHeight - cubeInfo.avgHeight) * result.baseArea;
} else {
result.cutVolume += (cubeInfo.avgHeight - baseHeight) * result.baseArea;
}
result.maxHeight = Math.max(result.maxHeight, cubeInfo.maxHeight);
result.minHeight = Math.min(result.minHeight, cubeInfo.minHeight);
result.baseArea += cubeInfo.baseArea;
}
});
return result;
}
const computeCubeInfo = (positions) => {
let worldPositions = [];
let minHeight = Number.MAX_VALUE;
let maxHeight = Number.MIN_VALUE;
let sumHeight = 0.0;
positions.forEach(element => {
const worldPostion = pickCartesian(viewer, element);
if (worldPostion.cartesian) {
const cartographic = Cesium.Cartographic.fromCartesian(worldPostion.cartesian);
worldPositions.push(cartographic);
minHeight = Math.min(minHeight, cartographic.height);
maxHeight = Math.max(maxHeight, cartographic.height);
sumHeight += cartographic.height;
}
});
const avgHeight = sumHeight / positions.length;
const result = {
minHeight: Number.MAX_VALUE,
maxHeight: Number.MIN_VALUE,
avgHeight: 0.0,
baseArea: 0.0
};
result.minHeight = minHeight;
result.maxHeight = maxHeight;
result.avgHeight = avgHeight;
result.baseArea = getAreaFromCartograohics(worldPositions);
return result;
}
export function getBounds(points) {
let bounds = [];
let left = Number.MAX_VALUE;
let right = Number.MIN_VALUE;
let top = Number.MAX_VALUE;
let bottom = Number.MIN_VALUE;
points.forEach(element => {
left = Math.min(left, element.x);
right = Math.max(right, element.x);
top = Math.min(top, element.y);
bottom = Math.max(bottom, element.y);
});
bounds.push(left);
bounds.push(top);
bounds.push(right);
bounds.push(bottom);
return bounds;
}
export function Cartesian2turfPolygon(positions) {
var coordinates = [[]];
positions.forEach(element => {
coordinates[0].push([element.x, element.y]);
});
coordinates[0].push([positions[0].x, positions[0].y]);
const polygon = turf.polygon(coordinates);
return polygon.geometry;
}
export function turfPloygon2CartesianArr(geometry) {
const positionArr = [];
geometry.coordinates.forEach((pointArr) => {
pointArr.forEach(point => {
positionArr.push(new Cesium.Cartesian2(point[0], point[1]));
});
});
positionArr.push(new Cesium.Cartesian2(geometry.coordinates[0][0][0], geometry.coordinates[0][0][1]));
return positionArr;
}
export function intersect(poly1, poly2) {
var intersection = turf.intersect(poly1, poly2);
if (intersection && intersection.geometry !== undefined) {
return turfPloygon2CartesianArr(intersection.geometry);
} else {
return [];
}
}
export function getAreaFromCartograohics(positions) {
const x = [0];
const y = [0];
const geodesic = new Cesium.EllipsoidGeodesic();
const radiansPerDegree = Math.PI / 180.0;
for (let i = 0; i < positions.length - 1; i++) {
const p1 = positions[i];
const p2 = positions[i + 1];
geodesic.setEndPoints(p1, p2);
const s = Math.sqrt(Math.pow(geodesic.surfaceDistance, 2));
const lat1 = p2.latitude * radiansPerDegree;
const lon1 = p2.longitude * radiansPerDegree;
const lat2 = p1.latitude * radiansPerDegree;
const lon2 = p1.longitude * radiansPerDegree;
let angle = -Math.atan2(
Math.sin(lon1 - lon2) * Math.cos(lat2),
Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2)
);
if (angle < 0) {
angle += Math.PI * 2.0;
}
y.push(Math.sin(angle) * s + y[i]);
x.push(Math.cos(angle) * s + x[i]);
}
let sum = 0;
for (let i = 0; i < x.length - 1; i++) {
sum += x[i] * y[i + 1] - x[i + 1] * y[i];
}
return Math.abs(sum + x[x.length - 1] * y[0] - x[0] * y[y.length - 1]) / 2;
}
export const CutAndFillAnalysis = (_viewer,h) => {
viewer=_viewer
baseHeight = h
clearDrawEntities();
let position = [];
let tempPoints = [];
let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (click) {
let ray = viewer.camera.getPickRay(click.position);
position = viewer.scene.globe.pick(ray, viewer.scene);
tempPoints.push(position);
let tempLength = tempPoints.length;
let point = drawPoint(position);
tempEntities.push(point);
if (tempLength > 1) {
let pointline = drawPolyline([tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]]);
tempEntities.push(pointline);
} else {
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.setInputAction(function (click) {
let cartesian = viewer.camera.pickEllipsoid(click.position, viewer.scene.globe.ellipsoid);
if (cartesian) {
let tempLength = tempPoints.length;
if (tempLength < 3) {
alert('请选择3个以上的点再执行闭合操作命令');
} else {
clearDrawEntities();
tempPoints.push(tempPoints[0])
let m = drawPolygon(tempPoints);
tempEntities.push(m);
let r = computeCutAndFillVolumeVoronoi(tempPoints)
var polyPositions = m.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions;
var polyCenter = Cesium.BoundingSphere.fromPoints(polyPositions).center;
polyCenter = Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(polyCenter);
m.position = polyCenter;
m.label = {
text: '最大高度:'+Number(r.maxHeight).toFixed(2)+'m\n最小高度:'+Number(r.minHeight).toFixed(2)+'m\n整平高度:'+Number(baseHeight).toFixed(2)+'m\n平面面积:'+Number(r.baseArea).toFixed(2)+'㎡\n填方:'+Number(r.fillVolume).toFixed(2)+'m³\n挖方:'+Number(r.cutVolume).toFixed(2)+"m³",
color: Cesium.Color.fromCssColorString('#fff'),
font: 'normal 32px MicroSoft YaHei',
showBackground: true,
scale: 0.5,
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
disableDepthTestDistance: 10000.0
};
tempEntities=[]
handler.destroy();
handler = null;
}
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}
const drawPoint = (position) => {
return viewer.entities.add({
name: "点几何对象",
position: position,
point: {
color: Cesium.Color.RED,
pixelSize: 5,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 1,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
}
});
}
const drawPolyline = (positions) => {
if (positions.length < 1) return;
return viewer.entities.add({
name: "线几何对象",
polyline: {
positions: positions,
width: 2.0,
material: new Cesium.PolylineGlowMaterialProperty({
color: Cesium.Color.RED,
}),
depthFailMaterial: new Cesium.PolylineGlowMaterialProperty({
color: Cesium.Color.RED,
}),
clampToGround: true,
}
});
}
const drawPolygon = (positions) => {
if (positions.length < 2) return;
return viewer.entities.add({
name: "面几何对象",
polygon: {
hierarchy: positions,
fill: true,
material: Cesium.Color.RED.withAlpha(.5),
outline: true,
outlinColor: Cesium.Color.WHITE,
outlineWidth: 1,
clampToGround: true,
},
});
}
const clearDrawEntities = () => {
tempEntities = [];
const entitys = viewer.entities._entities._array;
let length = entitys.length
for (let f = length - 1; f >= 0; f--) {
if (entitys[f]._name && (entitys[f]._name === '点几何对象' || entitys[f]._name === '线几何对象' || entitys[f]._name === '面几何对象')) {
viewer.entities.remove(entitys[f]);
}
}
}
const pickCartesian = (viewer, windowPosition) => {
const cartesianModel = viewer.scene.pickPosition(windowPosition);
const ray = viewer.camera.getPickRay(windowPosition);
const cartesianTerrain = viewer.scene.globe.pick(ray, viewer.scene);
const result = {};
if (typeof (cartesianModel) !== 'undefined' && typeof (cartesianTerrain) !== 'undefined') {
result.cartesian = cartesianModel || cartesianTerrain;
result.CartesianModel = cartesianModel;
result.cartesianTerrain = cartesianTerrain;
result.windowCoordinates = windowPosition.clone();
result.altitudeMode = cartesianModel.z.toFixed(0) !== cartesianTerrain.z.toFixed(0) ? Cesium.HeightReference.NONE : Cesium.HeightReference.CLAMP_TO_GROUND;
}
return result;
}
export const clearAll = () => {
clearDrawEntities();
}