2025-07-03 13:54:01 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import Tools from '../../../Tools';
|
|
|
|
|
class ContourAnalysis {
|
|
|
|
|
/**
|
|
|
|
|
* @constructor 等高线分析
|
|
|
|
|
* @param sdk
|
|
|
|
|
* **/
|
|
|
|
|
constructor(sdk, options = {}) {
|
|
|
|
|
this.viewer = sdk.viewer
|
|
|
|
|
let terrainAvailability = this.viewer.terrainProvider.availability;
|
|
|
|
|
if (!terrainAvailability) {
|
|
|
|
|
this.error = '未加载地形数据!'
|
|
|
|
|
window.ELEMENT && window.ELEMENT.Message({
|
|
|
|
|
message: '未加载地形数据!',
|
|
|
|
|
type: 'warning',
|
|
|
|
|
duration: 1500
|
|
|
|
|
});
|
|
|
|
|
console.warn(this.error)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
this.positions = options.positions
|
|
|
|
|
this.interfaceNum = options.interfaceNum || 25 //内插时均分的数量,即沿着边界长或宽均分成n分进行插点,默认值25
|
|
|
|
|
this.colorFill = options.colorFill || [
|
|
|
|
|
"#8CEA00",
|
|
|
|
|
"#B7FF4A",
|
|
|
|
|
"#FFFF37",
|
|
|
|
|
"#FFE66F",
|
|
|
|
|
"#FFD1A4",
|
|
|
|
|
"#FFCBB3",
|
|
|
|
|
"#FFBD9D",
|
|
|
|
|
"#FFAD86",
|
|
|
|
|
"#FF9D6F",
|
|
|
|
|
"#FF8F59",
|
|
|
|
|
"#FF8040",
|
|
|
|
|
"#FF5809",
|
|
|
|
|
"#F75000",
|
|
|
|
|
"#D94600",
|
|
|
|
|
"#BB3D00",
|
|
|
|
|
"#A23400",
|
|
|
|
|
"#842B00",
|
|
|
|
|
"#642100",
|
|
|
|
|
"#4D0000",
|
|
|
|
|
"#2F0000",
|
|
|
|
|
]; //等高线赋值颜色,内含default值
|
|
|
|
|
this.countorLineList = Cesium.defaultValue(options.countorLineList, []);
|
2025-07-03 18:18:08 +08:00
|
|
|
|
YJ.Analysis.AnalysesResults.push(this)
|
2025-07-03 13:54:01 +08:00
|
|
|
|
this.createNewLine();
|
|
|
|
|
}
|
2025-07-23 16:42:47 +08:00
|
|
|
|
|
|
|
|
|
get type() {
|
|
|
|
|
return 'ContourAnalysis'
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-03 13:54:01 +08:00
|
|
|
|
createNewLine() {
|
|
|
|
|
ContourAnalysis.interpolatePoint(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//利用turf在box内进行插点
|
|
|
|
|
static interpolatePoint(that) {
|
|
|
|
|
let curPoints = that.positions
|
|
|
|
|
let features = [];
|
|
|
|
|
const boundaryCoord = {
|
|
|
|
|
minX: 360,
|
|
|
|
|
maxX: -360,
|
|
|
|
|
minY: 180,
|
|
|
|
|
maxY: -180,
|
|
|
|
|
}; //绘制几何图形的外围矩形box
|
|
|
|
|
for (let index = 0; index < curPoints.length; index++) {
|
|
|
|
|
const element = Cesium.Cartesian3.fromDegrees(curPoints[index].lng, curPoints[index].lat, curPoints[index].alt);
|
|
|
|
|
let ellipsoid = that.viewer.scene.globe.ellipsoid;
|
|
|
|
|
let cartographic = ellipsoid.cartesianToCartographic(element);
|
|
|
|
|
let lat = Cesium.Math.toDegrees(cartographic.latitude);
|
|
|
|
|
let lng = Cesium.Math.toDegrees(cartographic.longitude);
|
|
|
|
|
boundaryCoord.maxY = Math.max(lat, boundaryCoord.maxY);
|
|
|
|
|
boundaryCoord.minY = Math.min(lat, boundaryCoord.minY);
|
|
|
|
|
boundaryCoord.maxX = Math.max(lng, boundaryCoord.maxX);
|
|
|
|
|
boundaryCoord.minX = Math.min(lng, boundaryCoord.minX);
|
|
|
|
|
|
|
|
|
|
let curFeature = {
|
|
|
|
|
type: "Feature",
|
|
|
|
|
properties: {},
|
|
|
|
|
geometry: {
|
|
|
|
|
type: "Point",
|
|
|
|
|
coordinates: [lng, lat],
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
features.push(curFeature);
|
|
|
|
|
}
|
|
|
|
|
let boundaryJson = {
|
|
|
|
|
type: "FeatureCollection",
|
|
|
|
|
features: features,
|
|
|
|
|
};
|
|
|
|
|
turf.featureEach(boundaryJson, function (point) {
|
|
|
|
|
point.properties.height = 0;
|
|
|
|
|
});
|
|
|
|
|
let options = {
|
|
|
|
|
gridType: "points",
|
|
|
|
|
property: "height",
|
|
|
|
|
units: "kilometers",
|
|
|
|
|
};
|
|
|
|
|
let from = turf.point([boundaryCoord.minX, boundaryCoord.minY]);
|
|
|
|
|
let to = turf.point([boundaryCoord.maxX, boundaryCoord.maxY]);
|
|
|
|
|
let diagonalDistance = turf.rhumbDistance(from, to, {
|
|
|
|
|
units: "kilometers",
|
|
|
|
|
});
|
|
|
|
|
let grid = turf.interpolate(
|
|
|
|
|
boundaryJson,
|
|
|
|
|
diagonalDistance / that.interfaceNum,
|
|
|
|
|
options
|
|
|
|
|
);
|
|
|
|
|
let minHeight = 10000000; //最低点高程值
|
|
|
|
|
let maxHeight = -100000000; //最高点高程值
|
|
|
|
|
turf.featureEach(grid, function (point) {
|
|
|
|
|
let pos = point.geometry.coordinates;
|
|
|
|
|
let cartographic = Cesium.Cartographic.fromDegrees(pos[0], pos[1]);
|
|
|
|
|
let height = that.viewer.scene.globe.getHeight(cartographic);
|
|
|
|
|
maxHeight = Math.max(height, maxHeight);
|
|
|
|
|
minHeight = Math.min(height, minHeight);
|
|
|
|
|
point.properties.height = height;
|
|
|
|
|
});
|
|
|
|
|
let breaks = [];
|
|
|
|
|
let stepCount = that.colorFill.length - 1;
|
|
|
|
|
let step = (maxHeight - minHeight) / stepCount;
|
|
|
|
|
for (let index = 0; index < stepCount + 1; index++) {
|
|
|
|
|
breaks.push(Math.ceil(minHeight + step * index));
|
|
|
|
|
}
|
|
|
|
|
// console.log('grid', grid)
|
|
|
|
|
let linesJson = turf.isolines(grid, breaks, { zProperty: "height" });
|
|
|
|
|
let _countorLine = Cesium.GeoJsonDataSource.load(linesJson, {
|
|
|
|
|
clampToGround: true,
|
|
|
|
|
});
|
|
|
|
|
// console.log(linesJson)
|
|
|
|
|
_countorLine.then(function (dataSource) {
|
|
|
|
|
console.log(dataSource)
|
|
|
|
|
that.countorLine = dataSource; //最终计算生成的等高线对象,GeoJsonDataSource
|
|
|
|
|
that.countorLineList.push(dataSource); //等高线数组
|
|
|
|
|
that.viewer.dataSources.add(dataSource);
|
|
|
|
|
let entities = dataSource.entities.values;
|
|
|
|
|
for (let index = 0; index < entities.length; index++) {
|
|
|
|
|
const element = entities[index];
|
|
|
|
|
let center = getPolylineCenter(element.polyline);
|
|
|
|
|
element.position = center;
|
|
|
|
|
// dataSource.entities.add(new Cesium.Entity({
|
|
|
|
|
// position: center,
|
|
|
|
|
// label: {
|
|
|
|
|
// text: element.properties.height._value + '',
|
|
|
|
|
// font: '20px Microsoft YaHei',
|
|
|
|
|
// fillColor: Cesium.Color.fromCssColorString('#f1d20c'),
|
|
|
|
|
// style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
|
|
|
|
// disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
|
|
|
|
// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
|
|
|
|
|
// },
|
|
|
|
|
// }))
|
|
|
|
|
// element.label = new Cesium.LabelGraphics({
|
|
|
|
|
|
|
|
|
|
// })
|
|
|
|
|
let cur_index = that.getObjectIndex(
|
|
|
|
|
breaks,
|
|
|
|
|
element.properties.height._value
|
|
|
|
|
);
|
|
|
|
|
if (cur_index) {
|
|
|
|
|
element.polyline.material = Cesium.Color.fromCssColorString(
|
|
|
|
|
that.colorFill[cur_index - 1]
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function getPolylineCenter(polyline) {
|
|
|
|
|
let tools = new Tools()
|
|
|
|
|
let positions = polyline.positions;
|
|
|
|
|
let length = positions._value.length;
|
|
|
|
|
let array = []
|
|
|
|
|
for (let i = 0; i < length; i++) {
|
|
|
|
|
let pos = tools.cartesian3Towgs84(positions._value[i], that.viewer)
|
|
|
|
|
array.push([pos.lng, pos.lat])
|
|
|
|
|
}
|
|
|
|
|
let line = turf.lineString(array);
|
|
|
|
|
let distance = turf.length(line, { units: "kilometers" });
|
|
|
|
|
let along = turf.along(line, distance/2, { units: "kilometers" });
|
|
|
|
|
return Cesium.Cartesian3.fromDegrees(along.geometry.coordinates[0], along.geometry.coordinates[1], 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 返回随机插入的数在数组中的位置
|
|
|
|
|
* @param {*} arr 元数组
|
|
|
|
|
* @param {*} num 随机数
|
|
|
|
|
* @returns 序号
|
|
|
|
|
* @example getObjectIndex([0,218,325,333,444],354)=>4;
|
|
|
|
|
*/
|
|
|
|
|
getObjectIndex(arr, num) {
|
|
|
|
|
for (let i = 0; i < arr.length; i++) {
|
|
|
|
|
if (arr[i] > num) {
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
clear(countorLine) {
|
|
|
|
|
if (countorLine) {
|
|
|
|
|
this.viewer.dataSources.remove(countorLine);
|
|
|
|
|
let index = this.countorLineList.indexOf(countorLine);
|
|
|
|
|
this.countorLineList.splice(index, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
destroy() {
|
|
|
|
|
this.countorLineList.forEach((element) => {
|
|
|
|
|
this.viewer.dataSources.remove(element);
|
|
|
|
|
});
|
|
|
|
|
this.countorLineList = [];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
export default ContourAnalysis;
|