321 lines
12 KiB
HTML
321 lines
12 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="./Build168/Cesium/Cesium.js"></script>
|
||
<script src="./js/turf.min.js"></script>
|
||
<style>
|
||
@import url(./Build/Cesium/Widgets/widgets.css);
|
||
html,
|
||
body,
|
||
#cesiumContainer {
|
||
width: 100%;
|
||
height: 100%;
|
||
margin: 0;
|
||
padding: 0;
|
||
overflow: hidden;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="cesiumContainer"></div>
|
||
<script>
|
||
Cesium.Ion.defaultAccessToken =
|
||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5ZjRjNTZkNC01NDYxLTRhMjQtOGEwZC1kZjA3YzQ5YTJlZDkiLCJpZCI6MjYwODQsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJpYXQiOjE1ODcxOTMwODN9.prGsSKyAW_9Ow5zHYPhbm3LsQL-ApQw5-5PNJkDaHi8";
|
||
|
||
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,
|
||
selectionIndicator: false, //是否显示选中的矩形框
|
||
});
|
||
// var viewer = new Cesium.Viewer('cesiumContainer', {
|
||
// terrainProvider: Cesium.createWorldTerrain()
|
||
// });
|
||
|
||
// var tileset = viewer.scene.primitives.add(
|
||
// new Cesium.Cesium3DTileset({
|
||
// url: Cesium.IonResource.fromAssetId(115448),
|
||
// })
|
||
// );
|
||
// viewer.zoomTo(tileset)
|
||
|
||
// let url = "./SampleData/cesiumlab/tileset.json";
|
||
let url = 'http://localhost:8078/3dtiles/zhudian/tileset.json'
|
||
let tileset = loadTileset(url);
|
||
// 创建切面平面集合
|
||
// var planes = [];
|
||
// var clippingPlanes = new Cesium.ClippingPlaneCollection({
|
||
// // planes: [
|
||
// // new Cesium.ClippingPlane(new Cesium.Cartesian3(0, 0, -1), 0) // 平面的方向(x,y,z) 以及 平面到原点的距离
|
||
// // ],
|
||
// planes: planes,
|
||
// edgeColor: Cesium.Color.WHITE, // 平面切割时模型的边缘颜色
|
||
// edgeWidth: 0, // 平面切割时模型的边缘宽度
|
||
// });
|
||
|
||
function loadTileset(tilesetUrl) {
|
||
let vm = this;
|
||
let tileset = new Cesium.Cesium3DTileset({
|
||
url: tilesetUrl,
|
||
// clippingPlanes: clippingPlanes,
|
||
maximumScreenSpaceError: 8,
|
||
dynamicScreenSpaceError: true,
|
||
dynamicScreenSpaceErrorDensity: 0.00278,
|
||
dynamicScreenSpaceErrorFactor: 4.0,
|
||
dynamicScreenSpaceErrorHeightFalloff: 0.25,
|
||
});
|
||
viewer.scene.primitives.add(tileset);
|
||
viewer.zoomTo(tileset);
|
||
tileset.readyPromise.then(function (tileset_) {
|
||
console.log("tileset_", tileset_);
|
||
setTilesetHeightAndOffset(tileset_, -40);
|
||
});
|
||
return tileset;
|
||
}
|
||
function 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;
|
||
}
|
||
|
||
/**
|
||
* 根据文档中的介绍可知,ClippingPlane所位于的坐标系应该是,以3DTiles原点为坐标原点,
|
||
* 该点正东为x轴正方向,该点正北为y轴正方向,该点的地球椭球体法线为z轴,远离地心的那一端为z轴正方向。
|
||
*/
|
||
function getInverseTransform(tileSet) {
|
||
let transform;
|
||
let tmp =
|
||
(tileSet.root && tileSet.root.transform) || tileSet.modelMatrix;
|
||
if ((tmp && tmp.equals(Cesium.Matrix4.IDENTITY)) || !tmp) {
|
||
// 如果root.transform不存在,则3DTiles的原点变成了boundingSphere.center
|
||
transform = Cesium.Transforms.eastNorthUpToFixedFrame(
|
||
tileSet.boundingSphere.center
|
||
);
|
||
} else {
|
||
transform = Cesium.Matrix4.fromArray(tileSet.root.transform);
|
||
}
|
||
return Cesium.Matrix4.inverseTransformation(
|
||
transform,
|
||
new Cesium.Matrix4()
|
||
);
|
||
}
|
||
/**
|
||
* 对点进行坐标转换的方法
|
||
*
|
||
*/
|
||
function getOriginCoordinateSystemPoint(point, inverseTransform) {
|
||
let val = Cesium.Cartesian3.fromDegrees(point.lng, point.lat);
|
||
return Cesium.Matrix4.multiplyByPoint(
|
||
inverseTransform,
|
||
val,
|
||
new Cesium.Cartesian3(0, 0, 0)
|
||
);
|
||
}
|
||
/**
|
||
* 下面就构造了一个由地平面两点p1,p2定义的剪裁面,这个剪裁面始终剪裁掉位于p1指向p2的向量的左侧。
|
||
*
|
||
*/
|
||
function createPlane(p1, p2, inverseTransform) {
|
||
// 将仅包含经纬度信息的p1,p2,转换为相应坐标系的cartesian3对象
|
||
let p1C3 = getOriginCoordinateSystemPoint(p1, inverseTransform);
|
||
let p2C3 = getOriginCoordinateSystemPoint(p2, inverseTransform);
|
||
|
||
// 定义一个垂直向上的向量up
|
||
let up = new Cesium.Cartesian3(0, 0, 10);
|
||
// right 实际上就是由p1指向p2的向量
|
||
let 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
|
||
let planeTmp = Cesium.Plane.fromPointNormal(p1C3, normal);
|
||
return Cesium.ClippingPlane.fromPlane(planeTmp);
|
||
}
|
||
|
||
// 需要裁剪的面的四个点,由3可以得到一个剪裁面了。那么对于数组[p1,p2,p3…pN],
|
||
// 当该数组中的点是按照顺时针排序时(因为3中叉乘的方向是right × up),相邻点两两构成一个剪裁面,就可以达到如上图2的效果
|
||
// 顺时针数组
|
||
// var coords = [
|
||
// [114.792694, 32.276356],
|
||
// [114.792761, 32.276744],
|
||
// [114.793105, 32.276702],
|
||
// [114.793045, 32.276312],
|
||
// ];
|
||
// 逆时针数组
|
||
// var coords = [
|
||
// [114.79271634627476,32.2763556665484],
|
||
// [114.79304073862163,32.27632363445024],
|
||
// [114.79309289472988,32.27668610700086],
|
||
// [114.79276024896451,32.27672647537516]
|
||
// ]
|
||
|
||
// 顺时针
|
||
var coords = [
|
||
[114.90848378, 32.3870309],
|
||
[114.90946223, 32.38700814],
|
||
[114.90944923, 32.38673509],
|
||
[114.90847078, 32.38676434],
|
||
[114.90848378, 32.3870309]
|
||
];
|
||
// coords = coords.reverse()
|
||
tileset.readyPromise.then(function (tileset_) {
|
||
console.log("tileset_", tileset_);
|
||
clippingTileset(tileset_)
|
||
});
|
||
|
||
function clippingTileset(tileset_){
|
||
// 构造裁切面 clippingPanel
|
||
// 1.计算转换需要的用到的矩阵
|
||
let matrix = getInverseTransform(tileset_);
|
||
let modelType = "1";//外部裁剪为"0",内部裁剪为"1"
|
||
const unionClippingRegions = modelType === "0" ? true : false;
|
||
console.log("before:",coords)
|
||
coords = isDirRes(coords,unionClippingRegions)
|
||
console.log("after:",coords)
|
||
const Planes = [];
|
||
for (let i = 0; i < coords.length-1; i++) {
|
||
// if(i === coords.length - 1){
|
||
// let p1 = { lng: coords[coords.length - 1][0], lat: coords[coords.length - 1][1], };
|
||
// let p2 = { lng: coords[0][0], lat: coords[0][1] };
|
||
// let plane = createPlane(p1, p2, matrix);
|
||
// Planes.push(plane);
|
||
// }else{
|
||
let p1 = { lng: coords[i][0], lat: coords[i][1] };
|
||
let p2 = { lng: coords[i+1][0], lat: coords[i+1][1] };
|
||
let plane = createPlane(p1, p2, matrix);
|
||
Planes.push(plane);
|
||
// }
|
||
}
|
||
console.log(Planes);
|
||
const PlaneCollection = new Cesium.ClippingPlaneCollection({
|
||
planes: Planes,
|
||
unionClippingRegions,
|
||
});
|
||
tileset_.clippingPlanes = PlaneCollection;
|
||
}
|
||
/**
|
||
* ring 为闭合的环
|
||
* isClockwise 需要返回的数组方向
|
||
*/
|
||
function isDirRes(ring, isClockwise) {
|
||
debugger;
|
||
var lineStringList = [];
|
||
ring.forEach((p) => {
|
||
lineStringList.push([p[0], p[1]]);
|
||
});
|
||
var clockwiseRing = turf.lineString(lineStringList);
|
||
let isR = turf.booleanClockwise(clockwiseRing);
|
||
console.log("isR",isR);
|
||
var points = [];
|
||
if(!isClockwise){// 需要逆时针
|
||
points = isR?[...ring.reverse()]:[...ring]
|
||
}else{// 需要顺时针
|
||
points = isR?[...ring]:[...ring.reverse()]
|
||
}
|
||
return points;
|
||
}
|
||
|
||
// viewer.scene.primitives.add(
|
||
// new Cesium.Primitive({
|
||
// geometryInstances: new Cesium.GeometryInstance({
|
||
// geometry: new Cesium.PolygonGeometry({
|
||
// polygonHierarchy: new Cesium.PolygonHierarchy(
|
||
// Cesium.Cartesian3.fromDegreesArray(coords.flat())
|
||
// ),
|
||
// vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
|
||
// height: 6,
|
||
// }),
|
||
// }),
|
||
// appearance: new Cesium.EllipsoidSurfaceAppearance({
|
||
// material: new Cesium.Material({
|
||
// fabric: {
|
||
// type: "Image",
|
||
// uniforms: {
|
||
// image: "./images/贴图/草坪/草坪1.jpg",
|
||
// },
|
||
// },
|
||
// }),
|
||
// }),
|
||
// })
|
||
// );
|
||
|
||
let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
|
||
handler.setInputAction(function (movement) {
|
||
//捕获椭球体,将笛卡尔二维平面坐标转为椭球体的笛卡尔三维坐标,返回球体表面的点
|
||
var cartesian3 = viewer.camera.pickEllipsoid(movement.position);
|
||
if (cartesian3) {
|
||
//将笛卡尔三维坐标转为地图坐标(弧度)
|
||
var cartographic =
|
||
viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian3);
|
||
//将地图坐标(弧度)转为十进制的度数
|
||
var lat_String = Cesium.Math.toDegrees(cartographic.latitude).toFixed(
|
||
6
|
||
);
|
||
var log_String = Cesium.Math.toDegrees(
|
||
cartographic.longitude
|
||
).toFixed(6);
|
||
var alti_String = (
|
||
viewer.camera.positionCartographic.height / 1000
|
||
).toFixed(2);
|
||
console.log(log_String + "," + lat_String);
|
||
}
|
||
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
||
</script>
|
||
</body>
|
||
</html>
|