فهرست منبع

Cesium上添加倾斜

WQQ 1 ماه پیش
والد
کامیت
9f26a9f97f
1فایلهای تغییر یافته به همراه210 افزوده شده و 120 حذف شده
  1. 210 120
      WebVue/TaiHufenglang/src/components/Cesium.vue

+ 210 - 120
WebVue/TaiHufenglang/src/components/Cesium.vue

@@ -48,136 +48,224 @@ onMounted(async () => {
     infoBox: false,
     //加载地形效果
     terrainProvider: await Cesium.createWorldTerrainAsync({
+      url: 'http://10.8.11.98:9003/terrain/GlobeDEM/layer.json', // 注意修正URL中的locallhost为localhost
       requestVertexNormals: true,
-      // requestWaterMask: true,
+      // requestWaterMask: true,     
     })
   });
 
-  // 定义距离显示条件和缩放属性(保持不变)
-  const distanceDisplayCondition = new Cesium.DistanceDisplayCondition(0, 10000000);
-  const pointNearFarScalar = new Cesium.NearFarScalar(10000, 1.0, 1000000, 0.3);
-  const labelNearFarScalar = new Cesium.NearFarScalar(10000, 1.0, 400000, 0);
-
-  // 存储实体与数据的映射(保持不变)
-  const entityDataMap = new Map();
-  JYLData.forEach((item) => {
-    const position = Cesium.Cartesian3.fromDegrees(
-      parseFloat(item.LGTD),
-      parseFloat(item.LTTD)
-    );
-    const entity = viewer.entities.add({
-      position: position,
-      billboard: {
-        image: '/src/assets/icon/blue.png',
-        scale: 0.4,
-        color: Cesium.Color.YELLOW,
-        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
-        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
-        distanceDisplayCondition: distanceDisplayCondition,
-        scaleByDistance: pointNearFarScalar
-      },
-      label: {
-        text: item.STNM || '未知点',
-        font: '25px 微软雅黑',
-        fillColor: Cesium.Color.WHITE,
-        backgroundColor: new Cesium.Color(0.1, 0.1, 0.1, 0.7),
-        backgroundPadding: new Cesium.Cartesian2(8, 4),
-        showBackground: true,
-        cornerRadius: 4,
-        outlineColor: Cesium.Color.BLACK,
-        outlineWidth: 1,
-        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
-        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
-        pixelOffset: new Cesium.Cartesian2(0, -32),
-        scale: 1.0,
-        disableDepthTestDistance: Number.POSITIVE_INFINITY,
-        distanceDisplayCondition: distanceDisplayCondition,
-        scaleByDistance: labelNearFarScalar
-      },
-      id: `point-${item.STCD || item.LGTD + '-' + item.LTTD}`,
-      properties: {
-        data: item
+ try {
+    // 1. 请求并解析TMS元数据XML
+    const xmlUrl = 'http://10.8.11.98:9003/image/tms/HTHDOM/tilemapresource.xml';
+    const response = await fetch(xmlUrl);
+    const xmlText = await response.text();
+    const parser = new DOMParser();
+    const xmlDoc = parser.parseFromString(xmlText, 'text/xml');
+
+    // 2. 从XML中提取关键参数
+    const tileFormat = xmlDoc.querySelector('TileFormat').getAttribute('extension'); // 如"png"
+    const maxLevel = xmlDoc.querySelectorAll('TileSet').length - 1; // 最大层级(假设层级从0开始)
+    const srs = xmlDoc.querySelector('SRS').textContent; // 如"EPSG:3857"
+
+    // 3. 加载TMS影像
+    const tmsImagery = new Cesium.UrlTemplateImageryProvider({
+      url: `http://10.8.11.98:9003/image/tms/HTHDOM/{z}/{x}/{y}.${tileFormat}`,
+      tileWidth: 256, // 从XML的TileFormat中获取width
+      tileHeight: 256, // 从XML的TileFormat中获取height
+      maximumLevel: maxLevel,
+      projection: srs === 'EPSG:3857' ? Cesium.WebMercatorProjection : Cesium.GeographicProjection,
+      // 核心:TMS行号反转(解决上下颠倒)
+      urlTemplateFunction: (x, y, level) => {
+        const tmsY = Math.pow(2, level) - 1 - y; // 反转行号
+        return `http://10.8.11.98:9003/image/tms/HTHDOM//${level}/${x}/${tmsY}.${tileFormat}`;
       }
     });
-    entityDataMap.set(entity.id, item);
-  });
 
-  // 天地图图层(保持不变)
-  const tdtLayer = new Cesium.WebMapTileServiceImageryProvider({
-    url: `http://t0.tianditu.com/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
-    layer: "tdt",
-    style: "default",
-    format: "image/jpeg",
-    tileMatrixSetID: "w",
-    maximumLevel: 18,
-    show: false,
-  });
-  viewer.imageryLayers.addImageryProvider(tdtLayer);
-
-  const tdtAnnotionLayer = new Cesium.WebMapTileServiceImageryProvider({
-    url: `http://t0.tianditu.com/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
-    layer: "tdtAnno",
-    style: "default",
-    format: "image/jpeg",
-    tileMatrixSetID: "w",
-    maximumLevel: 18,
-    show: false,
-  });
-  viewer.imageryLayers.addImageryProvider(tdtAnnotionLayer);
-
-  // 初始化视图(保持不变)
-  viewer.cesiumWidget.creditContainer.style.display = "none";
-  viewer.camera.setView({
-    destination: Cesium.Cartesian3.fromDegrees(120.169103, 31.226174, 500000),
-    orientation: {
-      heading: Cesium.Math.toRadians(0),
-      pitch: Cesium.Math.toRadians(-90),
-    },
-  });
+    viewer.imageryLayers.addImageryProvider(tmsImagery);
+    console.log('TMS影像加载成功');
+
+  } 
+  catch (error) {
+    console.error('加载TMS影像失败:', error);
+    // 检查XML URL是否正确(可能拼写错误,如localhost是否少写字母)
+    if (error.message.includes('404')) {
+      console.warn('请确认XML路径正确:', xmlUrl);
+    }
+  }
 
-  // 点击事件处理(核心修改)
-  handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
-  handler.setInputAction((click) => {
-    const scaleRatio = getScaleRatio();
-    const correctedX = click.position.x / scaleRatio;
-    const correctedY = click.position.y / scaleRatio;
-    const pickedObject = viewer.scene.pick(new Cesium.Cartesian2(correctedX, correctedY));
-
-    if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
-      const entityId = pickedObject.id.id;
-      const data = entityDataMap.get(entityId) || pickedObject.id.properties?.data?.getValue();
-      
-      if (data) {
-        selectedPoint.value = data;
-        // 关键:计算图标屏幕坐标,固定显示在图标上方
-        const entityPosition = viewer.scene.cartesianToCanvasCoordinates(pickedObject.id.position._value);
-        if (entityPosition) {
-          popupPosition.value = {
-            // 水平居中对齐图标
-            x: (entityPosition.x / scaleRatio) - 100,
-            // 固定显示在图标上方(距离图标底部10px)
-            y: (entityPosition.y / scaleRatio) - 130  // 130 = 弹框高度 + 间距
-          };
-        }
-        viewer.flyTo(pickedObject.id, {
-          offset: new Cesium.HeadingPitchRange(0, -0.5, 1500)
+// 多块倾斜摄影瓦片集的URL列表(根据实际路径修改)
+const tilesetUrls = [
+  "http://localhost:9003/model/TSQ1234/tileset.json",
+  "http://localhost:9003/model/SY123/tileset.json",
+  "http://10.8.11.98:9003/model/tvhy8PnM8/tileset.json",
+  "http://10.8.11.98:9003/model/t9or0ZtaT/tileset.json"
+
+];
+
+// 存储加载成功的瓦片集(可选,用于后续管理)
+const loadedTilesets = [];
+
+
+// 批量加载瓦片集(不调整视角)
+async function loadMultipleTilesets() {
+  try {
+    // 遍历URL列表,并行加载所有瓦片集
+    const promises = tilesetUrls.map(async (url, index) => {
+      try {
+        const tileset = await Cesium.Cesium3DTileset.fromUrl(url, {
+          maximumScreenSpaceError: 32, // 细节层级控制
+          dynamicScreenSpaceError: true,
+          skipLevelOfDetail: true,
+          maximumConcurrentRequests: 5,
+          tileCacheSize: 100
         });
+        // 添加到场景
+        viewer.scene.primitives.add(tileset);
+        loadedTilesets.push(tileset);
+        console.log(`第${index + 1}块瓦片集加载完成`);
+        return tileset;
+      } catch (error) {
+        console.error(`第${index + 1}块瓦片集加载失败:`, error);
+        return null; // 单块失败不影响其他块
       }
-    } else {
-      selectedPoint.value = null;
-    }
-  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
+    });
 
-  // 清理函数(移除鼠标移动监听)
-  onUnmounted(() => {
-    if (handler) {
-      handler.destroy();
-      handler = null;
-    }
-    if (viewer && !viewer.isDestroyed()) {
-      viewer.destroy();
+    // 等待所有瓦片集加载(无论成功与否)
+    await Promise.all(promises);
+    console.log("所有瓦片集加载操作已完成");
+  } catch (error) {
+    console.error("批量加载逻辑出错:", error);
+  }
+}
+
+// 执行加载(加载后保持原有视口)
+loadMultipleTilesets();
+
+// 定义距离显示条件和缩放属性(保持不变)
+const distanceDisplayCondition = new Cesium.DistanceDisplayCondition(0, 10000000);
+const pointNearFarScalar = new Cesium.NearFarScalar(10000, 1.0, 1000000, 0.3);
+const labelNearFarScalar = new Cesium.NearFarScalar(10000, 1.0, 400000, 0);
+
+// 存储实体与数据的映射(保持不变)
+const entityDataMap = new Map();
+JYLData.forEach((item) => {
+  const position = Cesium.Cartesian3.fromDegrees(
+    parseFloat(item.LGTD),
+    parseFloat(item.LTTD)
+  );
+  const entity = viewer.entities.add({
+    position: position,
+    billboard: {
+      image: '/src/assets/icon/blue.png',
+      scale: 0.4,
+      color: Cesium.Color.YELLOW,
+      horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
+      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+      distanceDisplayCondition: distanceDisplayCondition,
+      scaleByDistance: pointNearFarScalar
+    },
+    label: {
+      text: item.STNM || '未知点',
+      font: '25px 微软雅黑',
+      fillColor: Cesium.Color.WHITE,
+      backgroundColor: new Cesium.Color(0.1, 0.1, 0.1, 0.7),
+      backgroundPadding: new Cesium.Cartesian2(8, 4),
+      showBackground: true,
+      cornerRadius: 4,
+      outlineColor: Cesium.Color.BLACK,
+      outlineWidth: 1,
+      horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
+      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+      pixelOffset: new Cesium.Cartesian2(0, -32),
+      scale: 1.0,
+      disableDepthTestDistance: Number.POSITIVE_INFINITY,
+      distanceDisplayCondition: distanceDisplayCondition,
+      scaleByDistance: labelNearFarScalar
+    },
+    id: `point-${item.STCD || item.LGTD + '-' + item.LTTD}`,
+    properties: {
+      data: item
     }
   });
+  entityDataMap.set(entity.id, item);
+});
+
+// 天地图图层(保持不变)
+const tdtLayer = new Cesium.WebMapTileServiceImageryProvider({
+  url: `https://t0.tianditu.com/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
+  layer: "tdt",
+  style: "default",
+  format: "image/jpeg",
+  tileMatrixSetID: "w",
+  maximumLevel: 16,
+  show: true,
+});
+viewer.imageryLayers.addImageryProvider(tdtLayer);
+
+const tdtAnnotionLayer = new Cesium.WebMapTileServiceImageryProvider({
+  url: `http://t0.tianditu.com/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
+  layer: "tdtAnno",
+  style: "default",
+  format: "image/jpeg",
+  tileMatrixSetID: "w",
+  maximumLevel: 18,
+  show: false,
+});
+viewer.imageryLayers.addImageryProvider(tdtAnnotionLayer);
+
+// 初始化视图(保持不变)
+viewer.cesiumWidget.creditContainer.style.display = "none";
+viewer.camera.setView({
+  destination: Cesium.Cartesian3.fromDegrees(120.169103, 31.226174, 500000),
+  orientation: {
+    heading: Cesium.Math.toRadians(0),
+    pitch: Cesium.Math.toRadians(-90),
+  },
+});
+
+// 点击事件处理(核心修改)
+handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
+handler.setInputAction((click) => {
+  const scaleRatio = getScaleRatio();
+  const correctedX = click.position.x / scaleRatio;
+  const correctedY = click.position.y / scaleRatio;
+  const pickedObject = viewer.scene.pick(new Cesium.Cartesian2(correctedX, correctedY));
+
+  if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
+    const entityId = pickedObject.id.id;
+    const data = entityDataMap.get(entityId) || pickedObject.id.properties?.data?.getValue();
+
+    if (data) {
+      selectedPoint.value = data;
+      // 关键:计算图标屏幕坐标,固定显示在图标上方
+      const entityPosition = viewer.scene.cartesianToCanvasCoordinates(pickedObject.id.position._value);
+      if (entityPosition) {
+        popupPosition.value = {
+          // 水平居中对齐图标
+          x: (entityPosition.x / scaleRatio) - 100,
+          // 固定显示在图标上方(距离图标底部10px)
+          y: (entityPosition.y / scaleRatio) - 130  // 130 = 弹框高度 + 间距
+        };
+      }
+      viewer.flyTo(pickedObject.id, {
+        offset: new Cesium.HeadingPitchRange(0, -0.5, 1500)
+      });
+    }
+  } else {
+    selectedPoint.value = null;
+  }
+}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
+
+// 清理函数(移除鼠标移动监听)
+onUnmounted(() => {
+  if (handler) {
+    handler.destroy();
+    handler = null;
+  }
+  if (viewer && !viewer.isDestroyed()) {
+    viewer.destroy();
+  }
+});
 });
 </script>
 
@@ -185,7 +273,8 @@ onMounted(async () => {
 .custom-popup {
   position: absolute;
   z-index: 1000;
-  display: block; /* 始终显示(由v-if控制显隐) */
+  display: block;
+  /* 始终显示(由v-if控制显隐) */
   pointer-events: none;
 }
 
@@ -200,7 +289,8 @@ onMounted(async () => {
 
 .popup-arrow {
   position: absolute;
-  bottom: -10px; /* 指向图标 */
+  bottom: -10px;
+  /* 指向图标 */
   left: 50%;
   transform: translateX(-50%);
   width: 0;
@@ -222,4 +312,4 @@ onMounted(async () => {
   color: #666;
   font-size: 14px;
 }
-</style> 
+</style>