500 lines
17 KiB
HTML
500 lines
17 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<!-- Use correct character set. -->
|
||
<meta charset="utf-8" />
|
||
<!-- Tell IE to use the latest, best version. -->
|
||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||
<!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
|
||
<meta
|
||
name="viewport"
|
||
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
|
||
/>
|
||
<title>Learning Cesium!</title>
|
||
<script src="./Build/Cesium/Cesium.js"></script>
|
||
<style>
|
||
@import url(./Build/Cesium/Widgets/widgets.css);
|
||
html,
|
||
body,
|
||
#app,
|
||
#cesiumContainer {
|
||
width: 100%;
|
||
height: 100%;
|
||
margin: 0;
|
||
padding: 0;
|
||
overflow: hidden;
|
||
}
|
||
|
||
#geologyClipPlanDiv td {
|
||
padding: 4px 2px;
|
||
}
|
||
.closerGeologyClipPlan {
|
||
text-decoration: none;
|
||
position: absolute;
|
||
top: 20px;
|
||
right: 10px;
|
||
z-index: 20;
|
||
}
|
||
.closerGeologyClipPlan:after {
|
||
content: "\e60b";
|
||
font-family: "iconfont";
|
||
font-size: 22px;
|
||
color: rgba(gray, 0.8);
|
||
}
|
||
#geologyClipPlanDiv {
|
||
position: absolute;
|
||
top: 10px;
|
||
color: rgba(29, 164, 220, 0.9);
|
||
background: rgba(34, 69, 91, 0.7);
|
||
border-radius: 6px;
|
||
padding: 10px;
|
||
}
|
||
#geologyClipPlanDiv .closerGeologyClipPlan {
|
||
top: 1vh;
|
||
right: 0.6vw;
|
||
cursor: pointer;
|
||
}
|
||
</style>
|
||
<!-- 引入样式 -->
|
||
<link rel="stylesheet" href="./js/elementui/index.css" />
|
||
<!-- import Vue before Element -->
|
||
<script src="./js/vue2710.js"></script>
|
||
<!-- import JavaScript -->
|
||
<script src="./js/elementui/index.js"></script>
|
||
<script src="./js/turf.min.js"></script>
|
||
</head>
|
||
<body>
|
||
<div id="app">
|
||
<div id="cesiumContainer"></div>
|
||
<div id="geologyClipPlanDiv" v-if="geologyClipPlanIsShow">
|
||
<table style="text-align: right">
|
||
<tr>
|
||
<td colspan="2" style="text-align: left">
|
||
<span style="font-size: 18px; font-weight: 600"
|
||
>模型裁剪分析</span
|
||
>
|
||
<div
|
||
class="closerGeologyClipPlan"
|
||
@click="handCloserGeologyClipPlan"
|
||
></div>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td colspan="2">
|
||
<div
|
||
style="
|
||
height: 4px;
|
||
background-color: rgba(29, 164, 220, 0.6);
|
||
margin: 4px;
|
||
"
|
||
></div>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>裁剪类型:</td>
|
||
<td>
|
||
<el-radio v-model="modelType" label="0">外部裁剪</el-radio>
|
||
<el-radio v-model="modelType" label="1">内部裁剪</el-radio>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td colspan="2">
|
||
<el-button
|
||
size="mini"
|
||
:disabled="isDrawGeologyClipPlan"
|
||
@click="drawGeologyClipPlan"
|
||
>绘制裁剪范围</el-button
|
||
>
|
||
<el-button size="mini" @click="clearGeologyClipPlan"
|
||
>清除</el-button
|
||
>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
Cesium.Ion.defaultAccessToken =
|
||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5ZjRjNTZkNC01NDYxLTRhMjQtOGEwZC1kZjA3YzQ5YTJlZDkiLCJpZCI6MjYwODQsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJpYXQiOjE1ODcxOTMwODN9.prGsSKyAW_9Ow5zHYPhbm3LsQL-ApQw5-5PNJkDaHi8";
|
||
|
||
var geologyClipPlanObj = null;
|
||
var handlerGeologyClipPlan = null;
|
||
var floatingPointList = [];
|
||
var activeShapePoints = [];
|
||
|
||
var floatingPoint = undefined;
|
||
var activeShape = undefined;
|
||
|
||
var my3dtiles;
|
||
var drawList = [];
|
||
var inverseTransform = undefined;
|
||
|
||
var TilesetsList = [];
|
||
new Vue({
|
||
el: "#app",
|
||
data: {
|
||
geologyClipPlanIsShow: true,
|
||
isDrawGeologyClipPlan: false,
|
||
modelType: "0", // 开挖深度
|
||
},
|
||
methods: {
|
||
initViewer() {
|
||
var viewer = new Cesium.Viewer("cesiumContainer", {
|
||
geocoder: false, //位置查找
|
||
homeButton: false, //视图返回初始位置
|
||
sceneModePicker: false, //视角选择器
|
||
// baseLayerPicker:false,//底图选择器
|
||
navigationHelpButton: false, //导航帮助按钮
|
||
animation: false, //动画控制器
|
||
// creditContainer:"credit",//版权显示
|
||
timeline: false, //时间线
|
||
fullscreenButton: false, //全屏控件
|
||
vrButton: false,
|
||
infoBox: false,
|
||
selectionIndicator: false,
|
||
});
|
||
window.viewer = viewer;
|
||
this.addTiles();
|
||
},
|
||
addTiles() {
|
||
var tileset = new Cesium.Cesium3DTileset({
|
||
url: "./SampleData/cesiumlab/tileset.json",
|
||
dynamicScreenSpaceError: true,
|
||
dynamicScreenSpaceErrorDensity: 0.00278,
|
||
dynamicScreenSpaceErrorFactor: 4.0,
|
||
dynamicScreenSpaceErrorHeightFalloff: 0.25,
|
||
});
|
||
viewer.scene.primitives.add(tileset);
|
||
viewer.zoomTo(tileset);
|
||
tileset.readyPromise.then((palaceTileset) => {
|
||
this.my3dtiles = palaceTileset;
|
||
this.setTilesetHeightAndOffset(palaceTileset, -40);
|
||
});
|
||
},
|
||
setTilesetHeightAndOffset(tileset, height, x, y) {
|
||
x = x ? x : 0;
|
||
y = y ? y : 0;
|
||
let center;
|
||
if (tileset.boundingSphere) {
|
||
// 3dtiles
|
||
center = tileset.boundingSphere.center;
|
||
} else if (
|
||
tileset._boundingSpheres &&
|
||
tileset._boundingSpheres.length > 0
|
||
) {
|
||
// Primitive
|
||
center = tileset._boundingSpheres[0].center;
|
||
}
|
||
const cartographic = Cesium.Cartographic.fromCartesian(center);
|
||
const surface = Cesium.Cartesian3.fromRadians(
|
||
cartographic.longitude,
|
||
cartographic.latitude,
|
||
0.0
|
||
);
|
||
const offset = Cesium.Cartesian3.fromRadians(
|
||
cartographic.longitude + x,
|
||
cartographic.latitude + y,
|
||
height
|
||
);
|
||
const translation = Cesium.Cartesian3.subtract(
|
||
offset,
|
||
surface,
|
||
new Cesium.Cartesian3()
|
||
);
|
||
const modelMaxtrix = Cesium.Matrix4.fromTranslation(translation);
|
||
tileset.modelMatrix = modelMaxtrix;
|
||
},
|
||
|
||
handCloserGeologyClipPlan() {
|
||
this.geologyClipPlanIsShow = false;
|
||
this.clearGeologyClipPlan();
|
||
},
|
||
|
||
drawGeologyClipPlan() {
|
||
this.clearGeologyClipPlan();
|
||
this.isDrawGeologyClipPlan = true;
|
||
|
||
inverseTransform = this.getInverseTransform(this.my3dtiles);
|
||
|
||
window.viewer._container.style.cursor = "pointer";
|
||
|
||
// 取消双击事件-追踪该位置
|
||
window.viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
|
||
Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
|
||
);
|
||
|
||
handlerGeologyClipPlan = new Cesium.ScreenSpaceEventHandler(
|
||
window.viewer.scene.canvas
|
||
);
|
||
handlerGeologyClipPlan.setInputAction((event) => {
|
||
if (
|
||
!this.my3dtiles.clippingPlanes ||
|
||
!this.my3dtiles.clippingPlanes._planes.length
|
||
) {
|
||
const pick = window.viewer.scene.pickPosition(event.position);
|
||
const pickWGS = this.cart3ToWGS(pick);
|
||
const pickModel = window.viewer.scene.pick(event.position);
|
||
if (pickModel) {
|
||
drawList.push(pickWGS);
|
||
|
||
if (activeShapePoints.length === 0) {
|
||
floatingPoint = this.createPoint(pick);
|
||
floatingPointList.push(floatingPoint);
|
||
activeShapePoints.push(pick);
|
||
var dynamicPositions = new Cesium.CallbackProperty(
|
||
function () {
|
||
return new Cesium.PolygonHierarchy(activeShapePoints);
|
||
},
|
||
false
|
||
);
|
||
activeShape = this.drawShape(dynamicPositions);
|
||
}
|
||
activeShapePoints.push(pick);
|
||
floatingPointList.push(this.createPoint(pick));
|
||
}
|
||
}
|
||
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
||
|
||
handlerGeologyClipPlan.setInputAction((event) => {
|
||
if (Cesium.defined(floatingPoint)) {
|
||
var newPosition = window.viewer.scene.pickPosition(
|
||
event.endPosition
|
||
);
|
||
if (Cesium.defined(newPosition)) {
|
||
floatingPoint.position.setValue(newPosition);
|
||
activeShapePoints.pop();
|
||
activeShapePoints.push(newPosition);
|
||
}
|
||
}
|
||
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
|
||
|
||
handlerGeologyClipPlan.setInputAction((event) => {
|
||
if (
|
||
!this.my3dtiles.clippingPlanes ||
|
||
!this.my3dtiles.clippingPlanes._planes.length
|
||
) {
|
||
if (drawList.length < 3) {
|
||
this.$message({
|
||
message: "提示:需要绘制三个以上点, 请继续绘制!",
|
||
type: "warning",
|
||
});
|
||
} else {
|
||
this.terminateShape();
|
||
const unionClippingRegions =
|
||
this.modelType === "0" ? true : false;
|
||
drawList = this.isDirRes(drawList, unionClippingRegions);
|
||
const Planes = [];
|
||
for (let i = 0; i < drawList.length; i++) {
|
||
if (i === drawList.length - 1) {
|
||
Planes.push(
|
||
this.createPlane(
|
||
drawList[i],
|
||
drawList[0],
|
||
inverseTransform
|
||
)
|
||
);
|
||
} else {
|
||
Planes.push(
|
||
this.createPlane(
|
||
drawList[i],
|
||
drawList[i + 1],
|
||
inverseTransform
|
||
)
|
||
);
|
||
}
|
||
}
|
||
console.log(Planes);
|
||
const PlaneCollection = new Cesium.ClippingPlaneCollection({
|
||
planes: Planes,
|
||
unionClippingRegions, // 再做优化
|
||
});
|
||
this.my3dtiles.clippingPlanes = PlaneCollection;
|
||
}
|
||
|
||
handlerGeologyClipPlan.removeInputAction(
|
||
Cesium.ScreenSpaceEventType.LEFT_CLICK
|
||
);
|
||
handlerGeologyClipPlan.removeInputAction(
|
||
Cesium.ScreenSpaceEventType.RIGHT_CLICK
|
||
);
|
||
handlerGeologyClipPlan.removeInputAction(
|
||
Cesium.ScreenSpaceEventType.MOUSE_MOVE
|
||
);
|
||
handlerGeologyClipPlan = null;
|
||
this.isDrawGeologyClipPlan = false;
|
||
window.viewer._container.style.cursor = "default";
|
||
}
|
||
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
|
||
},
|
||
getInverseTransform(tileSet) {
|
||
let transform;
|
||
const tmp = tileSet.root.transform;
|
||
if ((tmp && tmp.equals(Cesium.Matrix4.IDENTITY)) || !tmp) {
|
||
transform = Cesium.Transforms.eastNorthUpToFixedFrame(
|
||
tileSet.boundingSphere.center
|
||
);
|
||
} else {
|
||
transform = Cesium.Matrix4.fromArray(tileSet.root.transform);
|
||
}
|
||
return Cesium.Matrix4.inverseTransformation(
|
||
transform,
|
||
new Cesium.Matrix4()
|
||
);
|
||
},
|
||
|
||
cart3ToWGS(cart3) {
|
||
return {
|
||
lat: Cesium.Math.toDegrees(
|
||
Cesium.Cartographic.fromCartesian(cart3).latitude
|
||
),
|
||
lng: Cesium.Math.toDegrees(
|
||
Cesium.Cartographic.fromCartesian(cart3).longitude
|
||
),
|
||
};
|
||
},
|
||
|
||
createPlane(p1, p2, inverseTransform) {
|
||
// 将仅包含经纬度信息的p1,p2,转换为相应坐标系的cartesian3对象
|
||
const p1C3 = this.getOriginCoordinateSystemPoint(
|
||
p1,
|
||
inverseTransform
|
||
);
|
||
const p2C3 = this.getOriginCoordinateSystemPoint(
|
||
p2,
|
||
inverseTransform
|
||
);
|
||
|
||
// 定义一个垂直向上的向量up
|
||
const up = new Cesium.Cartesian3(0, 0, 10);
|
||
// right 实际上就是由p1指向p2的向量
|
||
const right = Cesium.Cartesian3.subtract(
|
||
p2C3,
|
||
p1C3,
|
||
new Cesium.Cartesian3()
|
||
);
|
||
|
||
// 计算normal, right叉乘up,得到平面法向量,这个法向量指向right的右侧
|
||
let normal = Cesium.Cartesian3.cross(
|
||
right,
|
||
up,
|
||
new Cesium.Cartesian3()
|
||
);
|
||
normal = Cesium.Cartesian3.normalize(normal, normal);
|
||
|
||
// 由于已经获得了法向量和过平面的一点,因此可以直接构造Plane,并进一步构造ClippingPlane
|
||
const planeTmp = Cesium.Plane.fromPointNormal(p1C3, normal);
|
||
return Cesium.ClippingPlane.fromPlane(planeTmp);
|
||
},
|
||
|
||
getOriginCoordinateSystemPoint(point, inverseTransform) {
|
||
const val = Cesium.Cartesian3.fromDegrees(point.lng, point.lat);
|
||
return Cesium.Matrix4.multiplyByPoint(
|
||
inverseTransform,
|
||
val,
|
||
new Cesium.Cartesian3(0, 0, 0)
|
||
);
|
||
},
|
||
clearGeologyClipPlan() {
|
||
floatingPointList = [];
|
||
activeShapePoints = [];
|
||
if (geologyClipPlanObj) {
|
||
geologyClipPlanObj.clear();
|
||
geologyClipPlanObj = null;
|
||
}
|
||
this.isDrawGeologyClipPlan = false;
|
||
if (window.TilesetsList.length > 0) {
|
||
let tilestObj = window.TilesetsList[0].tileset;
|
||
tilestObj.clippingPlanes
|
||
? (tilestObj.clippingPlanes.removeAll(),
|
||
(tilestObj.clippingPlanes = undefined))
|
||
: "";
|
||
}
|
||
|
||
my3dtiles = undefined;
|
||
drawList = [];
|
||
},
|
||
|
||
isDirRes(polygon, isClockwise) {
|
||
debugger;
|
||
var lineStringList = [];
|
||
polygon.forEach((p) => {
|
||
lineStringList.push([p.lng, p.lat]);
|
||
});
|
||
// lineStringList.push([polygon[0]['lng'],polygon[0]['lat']]);
|
||
|
||
var clockwiseRing = turf.lineString(lineStringList);
|
||
let isR = turf.booleanClockwise(clockwiseRing);
|
||
|
||
var points = [];
|
||
if (isClockwise) {
|
||
if (!isR) {
|
||
points = polygon;
|
||
} else {
|
||
var count = 0;
|
||
for (var ii = polygon.length - 1; ii >= 0; ii--) {
|
||
points[count] = polygon[ii];
|
||
count++;
|
||
}
|
||
}
|
||
} else {
|
||
if (isR) {
|
||
points = polygon;
|
||
} else {
|
||
var count = 0;
|
||
for (var ii = polygon.length - 1; ii >= 0; ii--) {
|
||
points[count] = polygon[ii];
|
||
count++;
|
||
}
|
||
}
|
||
}
|
||
return points;
|
||
},
|
||
|
||
drawShape(positionData) {
|
||
var shape = window.viewer.entities.add({
|
||
polygon: {
|
||
hierarchy: positionData,
|
||
material: new Cesium.ColorMaterialProperty(
|
||
Cesium.Color.BLUE.withAlpha(0.2)
|
||
),
|
||
},
|
||
});
|
||
return shape;
|
||
},
|
||
|
||
createPoint(worldPosition) {
|
||
var point = window.viewer.entities.add({
|
||
position: worldPosition,
|
||
point: {
|
||
color: Cesium.Color.RED,
|
||
pixelSize: 5,
|
||
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
|
||
},
|
||
});
|
||
return point;
|
||
},
|
||
|
||
terminateShape() {
|
||
activeShapePoints.pop();
|
||
var pol = this.drawShape(activeShapePoints);
|
||
floatingPointList.forEach((p) => {
|
||
window.viewer.entities.remove(p);
|
||
});
|
||
window.viewer.entities.remove(floatingPoint);
|
||
window.viewer.entities.remove(activeShape);
|
||
window.viewer.entities.remove(pol);
|
||
floatingPoint = undefined;
|
||
activeShape = undefined;
|
||
|
||
activeShapePoints = [];
|
||
},
|
||
},
|
||
mounted() {
|
||
this.initViewer();
|
||
},
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|