实现一块区域的网格mesh,坡度计算,点位密集的情况下,会接近高程地形效果
var pos = [{
longitude: 120.817976,
latitude: 23.9530403,
height: 0
}, {
longitude: 120.9817976,
latitude: 23.6530403,
height: 0
}, {
longitude: 121.6517976,
latitude: 23.630403,
height: 0
}, {
longitude: 121.6917976,
latitude: 23.30403,
height: 0
}, {
longitude: 122.6917976,
latitude: 24.30403,
height: 0
}]
CreateMesh();
//创建mesh网格
function CreateMesh() {
// 1. 创建一个矩形区域
// var rectangle = Cesium.Rectangle.fromDegrees(117.09649937089316, 36.20673458245797, 117.11797117691083, 36.230040948473906)
var rectangle = Cesium.Rectangle.fromDegrees(pos[0].longitude, pos[0].latitude, pos[3].longitude, pos[3].latitude)
// 2. 在这个矩形区域内生成点集
var width = 100; // 横向点数
var height = 100; // 纵向点数
var terrainProvider = viewer.terrainProvider
var positions = [];
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var longitude = Cesium.Math.lerp(rectangle.west, rectangle.east, x / (width - 1));
var latitude = Cesium.Math.lerp(rectangle.south, rectangle.north, y / (height - 1));
positions.push(Cesium.Cartographic.fromRadians(longitude, latitude));
}
}
Cesium.sampleTerrainMostDetailed(terrainProvider, positions).then(function (samples) {
console.log(samples, "0000000000000000000000");
var points = samples.map(function (sample) {
return turf.point([Cesium.Math.toDegrees(sample.longitude), Cesium.Math.toDegrees(sample.latitude), sample.height],
{ z: sample.height }) // 将高度值保存到名为 'z' 的属性中);
});
console.log(points, "11111111111111");
//显示点集
var cartesianPoints = points.map(function (point) {
var coord = point.geometry.coordinates;
var cartographic = Cesium.Cartographic.fromDegrees(coord[0], coord[1], coord[2]);
return Cesium.Cartographic.toCartesian(cartographic);
});
var pointCollection = new Cesium.PointPrimitiveCollection();
cartesianPoints.forEach(function (position) {
pointCollection.add({
position: position,
color: Cesium.Color.RED,
pixelSize: 5
});
});
viewer.scene.primitives.add(pointCollection);
})
Cesium.sampleTerrainMostDetailed(terrainProvider, positions).then(function (samples) {
var points = samples.map(function (sample) {
return turf.point([Cesium.Math.toDegrees(sample.longitude), Cesium.Math.toDegrees(sample.latitude), sample.height],
{ z: sample.height }) // 将高度值保存到名为 'z' 的属性中);
});
// 创建一个FeatureCollection
var featureCollection = turf.featureCollection(points);
var tin = turf.tin(featureCollection, 'z');
var geometryInstances = []; // 用于存放所有的三角形GeometryInstance
var instances = [];
// 遍历每个TIN三角形
tin.features.forEach(function (feature, i) {
var coordinates = feature.geometry.coordinates[0];
var heights = [feature.properties.a, feature.properties.b, feature.properties.c];
var positions = coordinates.map(function (coord, index) {
return Cesium.Cartesian3.fromDegrees(coord[0], coord[1], heights[index]);
});
const point1 = positions[0];
const point2 = positions[1];
const point3 = positions[2];
//使用我们新定义的函数计算每个三角形的坡度
var analysisResult = calculateSlopeAndAspect(point1, point2, point3);
var slope = analysisResult.slope;
var hue = slope / 90.0; // 将坡度从0到90度映射到色调从0到1
var saturation = 1.0; // 全饱和度
var lightness = 0.5; // 正常亮度
var alpha = 1.0; // 完全不透明
//将HSL颜色转换为RGBA,当坡度为0度时,hue变为0,颜色是红色;当坡度为90度时,hue变为1,颜色是绿色;在0到90度之间的坡度将映射到从红色到绿色之间的颜色。
var color = Cesium.Color.fromHsl(hue, saturation, lightness).withAlpha(alpha);
console.log("三角形坡度:", analysisResult);
viewer.entities.add({
name: "三角面",
id: "triangle" + i,
polygon: {
hierarchy: [positions[0], positions[1], positions[2]],
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
perPositionHeight: true,
material: color,// Cesium.Color.fromCssColorString("#23B8BA").withAlpha(
// 1.0
//),
// extrudedHeight: 0,
outline: true,
outlineColor: Cesium.Color.GREEN,
}
});
});
var cartesianPoints = points.map(function (point) {
var coord = point.geometry.coordinates;
var cartographic = Cesium.Cartographic.fromDegrees(coord[0], coord[1], coord[2]);
return Cesium.Cartographic.toCartesian(cartographic);
});
var pointCollection = new Cesium.PointPrimitiveCollection();
cartesianPoints.forEach(function (position) {
pointCollection.add({
position: position,
color: Cesium.Color.RED,
pixelSize: 5
});
});
viewer.scene.primitives.add(pointCollection);
})
}
/**
* 计算三角形的坡度
* @param {*} point1
* @param {*} point2
* @param {*} point3
* @returns
*/
function calculateSlopeAndAspect(point1, point2, point3) {
console.log("point1", point1, "point2", point2, "point3", point3);
// 计算两个向量,它们位于三角形的两边
var v1 = Cesium.Cartesian3.subtract(
point1,
point2,
new Cesium.Cartesian3()
);
var v2 = Cesium.Cartesian3.subtract(
point2,
point3,
new Cesium.Cartesian3()
);
// 计算这两个向量的叉积,得到三角形的法向量
var normal = new Cesium.Cartesian3();
Cesium.Cartesian3.cross(v1, v2, normal);
Cesium.Cartesian3.normalize(normal, normal);
console.log("v1", v1, "v2", v2, "normal", normal);
// 计算三角形的中心点
var centroid = new Cesium.Cartesian3(
(point1.x + point2.x + point3.x) / 3,
(point1.y + point2.y + point3.y) / 3,
(point1.z + point2.z + point3.z) / 3
);
// 得到从地球中心到三角形中心的单位向量(这里不应该使用垂直向量(0,0,1),如果使用(0,0,1)会导致面南的坡度大,面北的坡度小)
var centerToCentroid = Cesium.Cartesian3.normalize(centroid, new Cesium.Cartesian3());
// 确保法线向量指向地球外部
if (Cesium.Cartesian3.dot(normal, centerToCentroid) < 0) {
Cesium.Cartesian3.negate(normal, normal);
}
// 计算坡度:法向量和从地球中心到三角形中心的径向向量之间的夹角
var slopeRadians = Math.acos(Cesium.Cartesian3.dot(normal, centerToCentroid));
var slopeDegrees = Cesium.Math.toDegrees(slopeRadians);
console.log("坡度:", slopeRadians, "角度:", slopeDegrees, "中心点:", centroid);
// 如果坡度大于90度,则将其减少到90度以下
if (slopeDegrees > 90) {
slopeDegrees = 180 - slopeDegrees;
}
// 返回坡度值
return { slope: slopeDegrees };
}