|
|
@@ -0,0 +1,149 @@
|
|
|
+import { actions } from '../store/store.js';
|
|
|
+
|
|
|
+function loadWaterLayer(url, name, callback) {
|
|
|
+ try {
|
|
|
+ fetch(url)
|
|
|
+ .then(response => response.json())
|
|
|
+ .then(geoJson => {
|
|
|
+ const waterPrimitives = [];
|
|
|
+
|
|
|
+ async function processFeature(feature) {
|
|
|
+ if (!feature || !feature.geometry) return;
|
|
|
+
|
|
|
+ const geometryType = feature.geometry.type;
|
|
|
+ const coordinates = feature.geometry.coordinates;
|
|
|
+
|
|
|
+ if (geometryType === 'Polygon') {
|
|
|
+ await createWaterFromPolygon(coordinates);
|
|
|
+ } else if (geometryType === 'MultiPolygon') {
|
|
|
+ for (const polygonCoords of coordinates) {
|
|
|
+ await createWaterFromPolygon(polygonCoords);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async function createWaterFromPolygon(polygonCoords) {
|
|
|
+ if (!polygonCoords || polygonCoords.length === 0) return;
|
|
|
+
|
|
|
+ const outerRing = polygonCoords[0];
|
|
|
+ if (!outerRing || outerRing.length === 0) return;
|
|
|
+
|
|
|
+ const positions = [];
|
|
|
+ const cartographics = [];
|
|
|
+
|
|
|
+ for (let i = 0; i < outerRing.length; i++) {
|
|
|
+ const coord = outerRing[i];
|
|
|
+ const longitude = coord[0];
|
|
|
+ const latitude = coord[1];
|
|
|
+ const cartographic = Cesium.Cartographic.fromDegrees(longitude, latitude, 0);
|
|
|
+ cartographics.push(cartographic);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cartographics.length < 3) return;
|
|
|
+
|
|
|
+ let terrainHeight = 0;
|
|
|
+ try {
|
|
|
+ const sampledPositions = await Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, cartographics);
|
|
|
+ const totalHeight = sampledPositions.reduce((sum, pos) => sum + pos.height, 0);
|
|
|
+ terrainHeight = totalHeight / sampledPositions.length;
|
|
|
+ } catch (e) {
|
|
|
+ console.warn('地形采样失败,使用默认高度:', e);
|
|
|
+ }
|
|
|
+
|
|
|
+ const waterHeight = terrainHeight - 22;
|
|
|
+
|
|
|
+ for (let i = 0; i < outerRing.length; i++) {
|
|
|
+ const coord = outerRing[i];
|
|
|
+ const longitude = coord[0];
|
|
|
+ const latitude = coord[1];
|
|
|
+ positions.push(Cesium.Cartesian3.fromDegrees(longitude, latitude, waterHeight));
|
|
|
+ }
|
|
|
+
|
|
|
+ const polygonGeometry = new Cesium.PolygonGeometry({
|
|
|
+ polygonHierarchy: new Cesium.PolygonHierarchy(positions),
|
|
|
+ height: waterHeight,
|
|
|
+ extrudedHeight: waterHeight,
|
|
|
+ vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT
|
|
|
+ });
|
|
|
+
|
|
|
+ const geometryInstance = new Cesium.GeometryInstance({
|
|
|
+ geometry: polygonGeometry,
|
|
|
+ id: name || 'water'
|
|
|
+ });
|
|
|
+
|
|
|
+ const waterMaterial = Cesium.Material.fromType('Water');
|
|
|
+ waterMaterial.uniforms.baseWaterColor = new Cesium.Color(0.02, 0.15, 0.25, 0.85);
|
|
|
+ waterMaterial.uniforms.blendColor = new Cesium.Color(0.05, 0.25, 0.4, 0.3);
|
|
|
+ waterMaterial.uniforms.specularMap = 'Cesium/Assets/Textures/water/watermask.png';
|
|
|
+ waterMaterial.uniforms.normalMap = 'Cesium/Assets/Textures/water_normals.jpg';
|
|
|
+ waterMaterial.uniforms.frequency = 4000.0;
|
|
|
+ waterMaterial.uniforms.animationSpeed = 0.015;
|
|
|
+ waterMaterial.uniforms.amplitude = 3.0;
|
|
|
+ waterMaterial.uniforms.specularIntensity = 0.8;
|
|
|
+ waterMaterial.uniforms.fadeFactor = 1.0;
|
|
|
+
|
|
|
+ const waterPrimitive = viewer.scene.primitives.add(new Cesium.Primitive({
|
|
|
+ geometryInstances: geometryInstance,
|
|
|
+ appearance: new Cesium.EllipsoidSurfaceAppearance({
|
|
|
+ material: waterMaterial
|
|
|
+ })
|
|
|
+ }));
|
|
|
+
|
|
|
+ waterPrimitives.push(waterPrimitive);
|
|
|
+ }
|
|
|
+
|
|
|
+ async function processAllFeatures() {
|
|
|
+ if (geoJson.type === 'FeatureCollection') {
|
|
|
+ for (const feature of geoJson.features) {
|
|
|
+ await processFeature(feature);
|
|
|
+ }
|
|
|
+ } else if (geoJson.type === 'Feature') {
|
|
|
+ await processFeature(geoJson);
|
|
|
+ }
|
|
|
+
|
|
|
+ actions.setChangeLayers();
|
|
|
+ if (callback) callback(waterPrimitives);
|
|
|
+ }
|
|
|
+
|
|
|
+ processAllFeatures();
|
|
|
+ })
|
|
|
+ .catch(error => {
|
|
|
+ console.error("加载水体GeoJSON失败:", error);
|
|
|
+ });
|
|
|
+ } catch (e) {
|
|
|
+ console.error("加载水体GeoJSON异常:", e);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function removeWaterLayer(name) {
|
|
|
+ if (viewer.scene && viewer.scene.primitives) {
|
|
|
+ const primitives = viewer.scene.primitives;
|
|
|
+ for (let i = primitives.length - 1; i >= 0; i--) {
|
|
|
+ const primitive = primitives.get(i);
|
|
|
+ if (primitive && primitive.geometryInstances) {
|
|
|
+ const instances = primitive.geometryInstances;
|
|
|
+ if (Array.isArray(instances)) {
|
|
|
+ for (const instance of instances) {
|
|
|
+ if (instance.id === name || (instance.id && instance.id.includes(name))) {
|
|
|
+ primitives.remove(primitive);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (instances && instances.id === name || (instances.id && instances.id.includes(name))) {
|
|
|
+ primitives.remove(primitive);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ actions.setChangeLayers();
|
|
|
+}
|
|
|
+
|
|
|
+export default {
|
|
|
+ loadWaterLayer,
|
|
|
+ removeWaterLayer
|
|
|
+};
|
|
|
+export {
|
|
|
+ loadWaterLayer,
|
|
|
+ removeWaterLayer
|
|
|
+};
|