Browse Source

格网、分别绘制

zhiyuan-007 3 months ago
parent
commit
cbb3f4141c
4 changed files with 222 additions and 175 deletions
  1. 120 126
      src/components/mapJK.vue
  2. 24 0
      src/config/basicTool.json
  3. 13 5
      src/units/map/AddThreeCubeEvent.js
  4. 65 44
      src/units/threejs/threeCube.js

+ 120 - 126
src/components/mapJK.vue

@@ -164,6 +164,12 @@ export default {
           case "ThreeGrid":
             threeGrid(params);
             break;
+          case "ShowThreeCube":
+            showThreeCube(params);
+            break;
+          case "ShowThreeNet":
+            showThreeNet(params);
+            break;
           case "RealPositionGrid":
             realPositionGrid(params);
             break;
@@ -449,131 +455,58 @@ export default {
           m_handles.add(addScaleEvent.scaleHandle,scale_handle_id);
         }
       }
-      function getEyeExtent() {
-        const screenWidth = m_view.width;
-        const screenHeight = m_view.height;
-
-        // 四个角的像素坐标
-        const screenCorners = [
-          { x: 0, y: 0 }, // 左上角
-          { x: screenWidth, y: 0 }, // 右上角
-          { x: screenWidth, y: screenHeight }, // 右下角
-          { x: 0, y: screenHeight }, // 左下角
-        ];
-
-        // 将屏幕角坐标转为地图坐标
-        const mapPoints = screenCorners.map((screenPoint) => m_view.toMap(screenPoint)).filter(p => p);
-
-        // 添加 camera.position 到 mapPoints
-        const cameraPoint = m_view.camera.position;
-
-        if (mapPoints.length < 4) {
-          if (cameraPoint) {
-            const bufferDistance = 2000; // 2公里
-            const spatialReference = m_view.spatialReference;
-
-            const screenExtent = {
-              xmin: cameraPoint.x - bufferDistance,
-              ymin: cameraPoint.y - bufferDistance,
-              xmax: cameraPoint.x + bufferDistance,
-              ymax: cameraPoint.y + bufferDistance,
-              spatialReference: spatialReference,
-            };
-            console.warn("视图范围不足4个有效点,使用摄像机位置生成的2公里范围。");
-            console.log(screenExtent);
-            return screenExtent;
-          } else {
-            console.warn("无法获取摄像机位置,请检查视图状态。");
-            return null;
-          }
-        } else {
-          try {
-            // 获取最小和最大坐标值
-            const xmin = Math.min(...mapPoints.map((p) => p.x));
-            const ymin = Math.min(...mapPoints.map((p) => p.y));
-            const xmax = Math.max(...mapPoints.map((p) => p.x));
-            const ymax = Math.max(...mapPoints.map((p) => p.y));
 
-            const screenExtent = {
-              xmin: xmin,
-              ymin: ymin,
-              xmax: xmax,
-              ymax: ymax,
-              spatialReference: m_view.spatialReference,
-            };
-            console.log(screenExtent);
-            return screenExtent;
-          } catch (e) {
-            console.error("获取地图范围时出错:", e);
-            return null;
+      function showThreeCube(params){
+        let status = params.status;
+        if(status == "hide"){
+          if(addThreeCubeEvent){
+            addThreeCubeEvent.clear();
+            addThreeCubeEvent = null;
           }
+          return
         }
+        // 初始化 AddThreeCubeEvent,暂时不启动
+        addThreeCubeEvent = new AddThreeCubeEvent({
+          view: m_view,
+        });
+        addThreeCubeEvent.start();
+        // 获取所有建筑点数据
+        getAllBuildingPoints();
       }
 
-
-      async function showLayersWithScaleEventsReturn(scaleValue) {
-        try {
-          // 初始化 AddThreeCubeEvent,暂时不启动
-          const addThreeCubeEvent = new AddThreeCubeEvent({
-            view: m_view,
-          });
-
-          // 获取所有建筑点数据
-          const allPoints = await getAllBuildingPoints();
-
-          // 将获取到的点数据赋值给 addThreeCubeEvent 的 points 属性
-          addThreeCubeEvent.points = allPoints;
-
-          // 确保所有点数据已加载后再启动事件
-          addThreeCubeEvent.start();
-
-          console.log('AddThreeCubeEvent started with points:', allPoints);
-        } catch (error) {
-          console.error('Error in showLayersWithScaleEventsReturn:', error);
+      function showThreeNet(params){
+        let status = params.status;
+        if(status == "hide"){
+          if(addThreeNetEvent){
+            addThreeNetEvent.clear();
+            addThreeNetEvent = null;
+          }
+          return
         }
+        //另一类是网加载(网只根据范围变化)
+        addThreeNetEvent = new AddThreeNetEvent({
+          view: m_view,
+          center: {x:8086.699067146538,y:2421.512992248397,z:20},
+          radius:1000,
+        });
+        addThreeNetEvent.start();
       }
 
       // 递归获取所有建筑点的辅助函数
-      async function getAllBuildingPoints(initialScrollId = null) {
-        let allPoints = [];        // 用于存储所有点的数组
-        let currentScrollId = initialScrollId; // 当前的 scrollId
-
-        while (true) {
-          try {
-            // 发起获取建筑点的请求
-            const res = await getBuildingPoint({
-              x: m_view.camera.position.x,
-              y: m_view.camera.position.y,
-              scrollId: currentScrollId,
-            });
-
-            // 检查响应码
-            if (res.data.code !== 200) {
-              throw new Error(`API返回错误代码: ${res.data.code}`);
-            }
-
-            const data = res.data.data;
-
-            // 假设 data.list 是当前请求返回的点数组
-            if (Array.isArray(data.list)) {
-              allPoints = allPoints.concat(data.list);
-            } else {
-              console.warn('data.list 不是数组:', data.list);
-            }
-
-            // 判断是否还有更多数据需要获取
-            if (data.list?.length >= 10000 && data.scrollId) {
-              currentScrollId = data.scrollId; // 更新 scrollId 以获取下一批数据
-            } else {
-              break; // 没有更多数据,退出循环
-            }
-          } catch (error) {
-            console.error('Error in getAllBuildingPoints:', error);
-            throw error; // 将错误抛出,以便上层捕获
+      function getAllBuildingPoints(scrollId = null) {
+        getBuildingPoint({
+          x: m_view.camera.position.x,
+          y: m_view.camera.position.y,
+          scrollId: scrollId,
+        }).then(res =>{
+          debugger
+          if(res.data.data.list?.length >= 10000 && res.data.data.scrollId){
+            addThreeCubeEvent.addPoints(res.data.data.list);
+            getAllBuildingPoints(res.data.data.scrollId);
+          }else{
+            addThreeCubeEvent.addPoints(res.data.data.list);
           }
-        }
-
-        return allPoints; // 返回累积的所有点
+        })
       }
 
 
@@ -670,21 +603,82 @@ export default {
       //     console.log("params",params)
       //   }
       // }
-
-
-      //不同比例尺加载白膜
-      // function showLayersWithScaleEventsReturn(scaleValue){
-      //   let layer = m_map.layers.find(item => item.id === "WhiteMold");
-      //   if(scaleValue > 50000){
-      //     if(layer){
-      //       layer.visible = false;
+      // function getEyeExtent() {
+      //   const screenWidth = m_view.width;
+      //   const screenHeight = m_view.height;
+      //
+      //   // 四个角的像素坐标
+      //   const screenCorners = [
+      //     { x: 0, y: 0 }, // 左上角
+      //     { x: screenWidth, y: 0 }, // 右上角
+      //     { x: screenWidth, y: screenHeight }, // 右下角
+      //     { x: 0, y: screenHeight }, // 左下角
+      //   ];
+      //
+      //   // 将屏幕角坐标转为地图坐标
+      //   const mapPoints = screenCorners.map((screenPoint) => m_view.toMap(screenPoint)).filter(p => p);
+      //
+      //   // 添加 camera.position 到 mapPoints
+      //   const cameraPoint = m_view.camera.position;
+      //
+      //   if (mapPoints.length < 4) {
+      //     if (cameraPoint) {
+      //       const bufferDistance = 2000; // 2公里
+      //       const spatialReference = m_view.spatialReference;
+      //
+      //       const screenExtent = {
+      //         xmin: cameraPoint.x - bufferDistance,
+      //         ymin: cameraPoint.y - bufferDistance,
+      //         xmax: cameraPoint.x + bufferDistance,
+      //         ymax: cameraPoint.y + bufferDistance,
+      //         spatialReference: spatialReference,
+      //       };
+      //       console.warn("视图范围不足4个有效点,使用摄像机位置生成的2公里范围。");
+      //       console.log(screenExtent);
+      //       return screenExtent;
+      //     } else {
+      //       console.warn("无法获取摄像机位置,请检查视图状态。");
+      //       return null;
       //     }
-      //   }else{
-      //     if(layer){
-      //       layer.visible = true;
+      //   } else {
+      //     try {
+      //       // 获取最小和最大坐标值
+      //       const xmin = Math.min(...mapPoints.map((p) => p.x));
+      //       const ymin = Math.min(...mapPoints.map((p) => p.y));
+      //       const xmax = Math.max(...mapPoints.map((p) => p.x));
+      //       const ymax = Math.max(...mapPoints.map((p) => p.y));
+      //
+      //       const screenExtent = {
+      //         xmin: xmin,
+      //         ymin: ymin,
+      //         xmax: xmax,
+      //         ymax: ymax,
+      //         spatialReference: m_view.spatialReference,
+      //       };
+      //       console.log(screenExtent);
+      //       return screenExtent;
+      //     } catch (e) {
+      //       console.error("获取地图范围时出错:", e);
+      //       return null;
       //     }
       //   }
       // }
+
+
+
+      //不同比例尺加载白膜
+      function showLayersWithScaleEventsReturn(scaleValue){
+        let layer = m_map.layers.find(item => item.id === "WhiteMold");
+        if(scaleValue > 50000){
+          if(layer){
+            layer.visible = false;
+          }
+        }else{
+          if(layer){
+            layer.visible = true;
+          }
+        }
+      }
       function viewshedAnalysis(params){
         let status = params.status;
         if(status === "hide"){

+ 24 - 0
src/config/basicTool.json

@@ -191,6 +191,30 @@
           }
         }
       },
+      {
+        "code": "1-25",
+        "title": "三维格子",
+        "data": {
+          "ActionName": "ShowThreeCube",
+          "Parameters": {
+            "status": "show",
+            "size": 50,
+            "token": ""
+          }
+        }
+      },
+      {
+        "code": "1-26",
+        "title": "三维网",
+        "data": {
+          "ActionName": "ShowThreeNet",
+          "Parameters": {
+            "status": "show",
+            "token": ""
+          }
+        }
+      },
+
       {
         "code": "1-19",
         "title": "指定位置格子加载渲染",

+ 13 - 5
src/units/map/AddThreeCubeEvent.js

@@ -6,7 +6,7 @@ import {ThreeCubeClass} from "../threejs/threeCube.js";
 class AddThreeCubeEvent{
     constructor(options){
         this.view = options.view;
-        this.points = options.points;
+        this.points = options.points || []; // 初始点位(可为空)
         this.addThreeCubeEvent = null;
     }
     start() {
@@ -18,15 +18,23 @@ class AddThreeCubeEvent{
         this.view.when(()=>{
             this.addThreeCubeEvent = new subRenderClass({
                 view:that.view,
-                points:that.points,
+                points: [], // 初始为空,等待后续增量加载
                 webgl,
             })
         })
     }
-    update(){
-        this.addThreeCubeEvent.points = this.points;
-    }
 
+    /**
+     * 增量加载点位
+     * @param {Array} newPoints - 新的点位数组
+     */
+    addPoints(newPoints) {
+        if (this.addThreeCubeEvent) {
+            this.addThreeCubeEvent.addPoints(newPoints); // 调用内部类的增量加载方法
+        } else {
+            console.warn("addThreeCubeEvent 未初始化,无法添加新点位!");
+        }
+    }
     clear(){
         if(this.addThreeCubeEvent){
             this.addThreeCubeEvent.destroy();

+ 65 - 44
src/units/threejs/threeCube.js

@@ -7,9 +7,11 @@ export const ThreeCubeClass = {
         this.points = options.points;
         this.mesh = null;
         this._camera = null;
+        this.dummy = null; // 用于批量操作的临时对象
     },
 
     initialize(){
+        this.dummy = new THREE.Object3D(); // 用于批量操作的临时对象
         this.renderer = new THREE.WebGLRenderer({
             context:this.gl,
             premultipliedAlpha:false
@@ -88,58 +90,77 @@ export const ThreeCubeClass = {
             );
         };
 
-        this.mesh = new THREE.InstancedMesh(geometry, material, this.points.length);
-        // 为实例添加颜色属性
-        const instanceColors = new Float32Array(this.points.length * 3);
-        const dummy = new THREE.Object3D();
-        const color = new THREE.Color();
-        let index = 0;
-        // debugger
-        // let dataX_CJ = points.map(point => point.x);
-        // let dataY_CJ = points.map(point => point.y);
-        //
-        // let dataX_84 = points.map(point => point.locationPoint.lat);
-        // let dataY_84 = points.map(point => point.locationPoint.lon);
-        //
-        // console.log("dataX_CJ",dataX_CJ)
-        // console.log("dataY_CJ",dataY_CJ)
-        // console.log("dataX_84",dataX_84)
-        // console.log("dataY_84",dataY_84)
-        // debugger
-        for(let i = 0; i < this.points.length; i++){
-            let worldX = this.points[i].x;
-            let worldY = this.points[i].y;
-            let worldZ = this.points[i].z;
-            let renderPos = [];
-            this.webgl.toRenderCoordinates(this.view, [worldX, worldY, worldZ], 0, this.view.spatialReference, renderPos, 0, 1);
-            dummy.position.set(renderPos[0], renderPos[1], renderPos[2]);
-            dummy.updateMatrix();
-            this.mesh.setMatrixAt(index, dummy.matrix);
-
-            instanceColors[index * 3] = 255;
-            instanceColors[index * 3 + 1] = 0;
-            instanceColors[index * 3 + 2] = 0;
-            index++;
+        this.mesh = new THREE.InstancedMesh(geometry, material, 0);
+        this.mesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
+    },
 
+    addPoints(newPoints) {
+        const totalPoints = this.points.length + newPoints.length;
+
+        // 创建新的颜色数组,并复制现有点位颜色信息
+        const instanceColors = new Float32Array(totalPoints * 3);
+        if (this.mesh.geometry.attributes.instanceColor) {
+            const oldColors = this.mesh.geometry.attributes.instanceColor.array;
+            instanceColors.set(oldColors, 0); // 复制旧颜色到新颜色数组
         }
 
-        // 为实例化的网格设置颜色
-        geometry.setAttribute('instanceColor', new THREE.InstancedBufferAttribute(instanceColors, 3));
-        geometry.attributes.instanceColor.needsUpdate = true;
-        this.mesh.instanceMatrix.needsUpdate = true;
+        // 创建新的 InstancedMesh
+        const newMesh = new THREE.InstancedMesh(
+            this.mesh.geometry,
+            this.mesh.material,
+            totalPoints
+        );
+        newMesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
+
+        // 复制旧点位矩阵
+        for (let i = 0; i < this.points.length; i++) {
+            this.mesh.getMatrixAt(i, this.dummy.matrix);
+            newMesh.setMatrixAt(i, this.dummy.matrix);
+        }
 
+        // 添加新点位矩阵和颜色
+        let index = this.points.length;
+        newPoints.forEach((point) => {
+            let renderPos = [];
+            this.webgl.toRenderCoordinates(
+                this.view,
+                [point.x, point.y, point.z],
+                0,
+                this.view.spatialReference,
+                renderPos,
+                0,
+                1
+            );
+            this.dummy.position.set(renderPos[0], renderPos[1], renderPos[2]);
+            this.dummy.updateMatrix();
+            newMesh.setMatrixAt(index, this.dummy.matrix);
+
+            // 设置新点位为红色
+            instanceColors[index * 3] = 1; // 红色通道
+            instanceColors[index * 3 + 1] = 0; // 绿色通道
+            instanceColors[index * 3 + 2] = 0; // 蓝色通道
+            index++;
+        });
 
-        // 将网格和边框分别添加到场景中
+        // 更新颜色属性
+        newMesh.geometry.setAttribute(
+            "instanceColor",
+            new THREE.InstancedBufferAttribute(instanceColors, 3)
+        );
+        newMesh.geometry.attributes.instanceColor.needsUpdate = true;
+        newMesh.instanceMatrix.needsUpdate = true;
+
+        // 替换场景中的 mesh
+        this.scene.remove(this.mesh);
+        this.mesh = newMesh;
         this.scene.add(this.mesh);
-        // 网格的光照
-        const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
-        this.scene.add(ambientLight);
-
-        const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
-        directionalLight.position.set(10, 10, 10);
-        this.scene.add(directionalLight);
 
+        // 更新点位数据
+        this.points = this.points.concat(newPoints);
     },
+
+
+
     render(){
         let cam = this.camera;
         //需要调整相机的视角