Преглед изворни кода

中图三亚20250312更新

lkk пре 2 месеци
родитељ
комит
8aa3431ed2

+ 44 - 3
src/utils/MapHelper/MapHelper.js

@@ -1,5 +1,4 @@
 import proj4 from "proj4";
-import axios from "axios";
 import { Notification, MessageBox, Message, Loading } from "element-ui";
 import { tansParams, blobValidate } from "@/utils/ruoyi";
 const CTservice = axios.create({
@@ -49,7 +48,7 @@ export const mapQuery = async (url, queryObj) => {
 };
 export const mapanalyzePost = async (url, queryObj) => {
   let response = await CTservice.post(url, queryObj);
-  debugger;
+
   if (response && response.data) {
     return response.data;
   } else {
@@ -187,7 +186,6 @@ export const undergroundMode = (state) => {
 export const getGroundPoint = async (lng, lat, completed) => {
   if (!lng || !lat) return null;
   try {
-    debugger;
     let positions = [Cesium.Cartographic.fromDegrees(lng, lat)];
     //如果有dem高程,则取dem高程,如果没有,则地图面高度为0
     if (viewer.terrainProvider) {
@@ -212,3 +210,46 @@ export const getGroundPoint = async (lng, lat, completed) => {
   let myP = Cesium.Cartesian3.fromDegrees(lng, lat, 0);
   return myP;
 };
+/**
+ * @namespace   名称:getGroundPoint
+ * @description 作用:根据经纬度(或者墨卡托)获取地面三维坐标
+ * @param {Array} Points 经纬度,
+ * @returns {Cartesian3} 返回经纬度
+ */
+export const getXYZPoint = async (Points) => {
+  if (!Points && Points.length > 0) return [];
+  try {
+    var positions = [];
+    for (var index = 0; index < Points.length; index++) {
+      var position = Points[index];
+      positions.push(Cesium.Cartographic.fromDegrees(position[0], position[1]));
+    }
+    //如果有dem高程,则取dem高程,如果没有,则地图面高度为0
+    if (viewer.terrainProvider) {
+      var promise = Cesium.sampleTerrainMostDetailed(
+        viewer.terrainProvider,
+        positions
+      );
+      var resultPs = await Promise.resolve(promise);
+      if (resultPs && resultPs.length > 0) {
+        var xyzs = [];
+        for (var index = 0; index < resultPs.length; index++) {
+          var resultP = resultPs[index];
+          var longitude = Cesium.Math.toDegrees(resultP.longitude);
+          var latitude = Cesium.Math.toDegrees(resultP.latitude);
+
+          xyzs.push({ x: longitude, y: latitude, z: resultP.height });
+        }
+        return xyzs;
+      }
+    } else {
+      for (var index = 0; index < Points.length; index++) {
+        var Point = Points[index];
+        Point = { x: Point[0], y: Point[1], z: 0 };
+      }
+      return Points;
+    }
+  } catch (error) {
+    return [];
+  }
+};

+ 6 - 2
src/views/ConstructionApplication3D/RSAnalysis/RSAnalysis.vue

@@ -720,7 +720,7 @@ export default {
       });
 
       //初始化飞行管理
-      that.flyHOld = that.flyH;
+      // that.flyHOld = that.flyH;
       //注册站点到达事件
       flyManager.stopArrived.addEventListener(function (routeStop) {
         routeStop.waitTime = 1; // 在每个站点处停留1s
@@ -754,20 +754,24 @@ export default {
         return;
       }
       var that = this;
+
       flyManager.currentRoute.speed = that.flySpeed / 3.6;
       flyManager && flyManager.stop();
       if (that.flySpeed == 0) {
         return;
       }
+
       debugger;
       flyManager.currentRoute.stopCollection.forEach((stop, index) => {
+        stop.altitude = that.lineFylPoints[index][2] + that.flyH;
         stop.point = new Cesium.Cartesian3.fromDegrees(
           that.lineFylPoints[index][0],
           that.lineFylPoints[index][1],
           that.lineFylPoints[index][2] + that.flyH
         );
       });
-      that.flyHOld = that.flyH;
+      // that.flyHOld = that.flyH;
+
       flyManager && flyManager.play();
     },
     /**

Разлика између датотеке није приказан због своје велике величине
+ 544 - 260
src/views/ConstructionApplication3D/SunlightAnalysis/SunlightAnalysis.vue


+ 499 - 0
src/views/ConstructionApplication3D/SunlightAnalysis/SunshineAnalysis.js

@@ -0,0 +1,499 @@
+const SunshineAnalysisByJS = {
+  /**
+   *
+   * @param {*} postions 经纬度   要分析的点的位置(是世界坐标)
+   * @param {*} selDate 日期
+   * @param {*} startTime 开始时间
+   * @param {*} endTime 结束时间
+   * @returns
+   */
+  PointSunshineAnalysis(
+    postions,
+    selDate,
+    startTime,
+    endTime,
+    HourSegmentation = 1
+  ) {
+    let framebufferCopy = viewer.scene._view.globeDepth._copyDepthFramebuffer;
+    let context = viewer.scene.context;
+    let width = viewer.scene.drawingBufferWidth;
+    let height = viewer.scene.drawingBufferHeight;
+    let pixels = context.readPixels({
+      x: 0,
+      y: 0,
+      width: width,
+      height: height,
+      framebuffer: framebufferCopy,
+    });
+    //根据传入时间计算实际日照时间(传入时间可能存在日落之前或之后的时间,应该去除)
+    var rcrlTime = SunshineAnalysisByJS.calculateTime(
+      selDate,
+      startTime,
+      endTime - 1
+    );
+    for (
+      var Timenumber = rcrlTime.jssunriseHours;
+      Timenumber <= rcrlTime.jssunsetHours;
+      Timenumber++
+    ) {
+      // var HourIsLineOfSightClear = false;
+      //增加精度,每小时分多时段采集
+      for (var fzs = 1; fzs <= HourSegmentation; fzs++) {
+        var date = new Date(
+          new Date(selDate).setHours(
+            Timenumber,
+            fzs * (60 / HourSegmentation),
+            0
+          )
+        );
+        //获取太阳的世界坐标,
+        let transforMatrix = Cesium.Transforms.computeTemeToPseudoFixedMatrix(
+          Cesium.JulianDate.fromDate(date)
+        );
+        let sunposition2 =
+          Cesium.Simon1994PlanetaryPositions.computeSunPositionInEarthInertialFrame(
+            Cesium.JulianDate.fromDate(date)
+          );
+        Cesium.Matrix3.multiplyByVector(
+          transforMatrix,
+          sunposition2,
+          sunposition2
+        );
+
+        for (let index = 0; index < postions.length; index++) {
+          const postion = postions[index];
+          var fx = new Cesium.Cartesian3(
+            sunposition2.x - postion.x,
+            sunposition2.y - postion.y,
+            sunposition2.z - postion.z
+          );
+          var dec = Math.sqrt(fx.x * fx.x + fx.y * fx.y + fx.z * fx.z);
+          var fxxl = new Cesium.Cartesian3(fx.x / dec, fx.y / dec, fx.z / dec); //方向向量
+          var changdu = 200;
+          var zd = new Cesium.Cartesian3(
+            postion.x + changdu * fxxl.x,
+            postion.y + changdu * fxxl.y,
+            postion.z + changdu * fxxl.z
+          );
+          //如果线之间被隔断,就认为该点被阻挡了
+          var isLineOfSightClear = SunshineAnalysisByJS.jiance(
+            scene,
+            context,
+            pixels,
+            postion,
+            zd
+          );
+          // true 不在阴影中   false 在阴影中
+          if (isLineOfSightClear) {
+            // HourIsLineOfSightClear = true;
+            postion.rzsc += 60 / HourSegmentation / 60;
+            if (postion.rzsc > 5) {
+              postion.rzsc = 5;
+            }
+          }
+        }
+      }
+    }
+
+    return postions;
+  },
+
+  jiance(scene, context, pixels, start, end) {
+    var num = 100;
+    var isshowders = false;
+    var rad1 = Cesium.Cartographic.fromCartesian(start);
+    var rad2 = Cesium.Cartographic.fromCartesian(end); //开始节点和结束节点转换为以弧度计算的经纬度
+    var points = [];
+    //这里表示插值函数,start和end是起始点,然后进行插值,检测高程,如果获取的地面点比差值点的高程高的话就代表有焦点
+    //坐标转经纬度
+    let startpoint = {};
+    startpoint.longitude = (rad1.longitude / Math.PI) * 180;
+    startpoint.latitude = (rad1.latitude / Math.PI) * 180;
+    startpoint.czheight = rad1.height; //将开始节点转换为角度的点
+    let endpoint = {};
+    endpoint.longitude = (rad2.longitude / Math.PI) * 180;
+    endpoint.latitude = (rad2.latitude / Math.PI) * 180;
+    endpoint.czheight = rad2.height; //将结束节点节点转换为角度的点
+    for (var i = 0; i < num; i++) {
+      let point = {};
+      point.longitude = Cesium.Math.lerp(
+        startpoint.longitude,
+        endpoint.longitude,
+        0.01 * (i + 1)
+      );
+      point.latitude = Cesium.Math.lerp(
+        startpoint.latitude,
+        endpoint.latitude,
+        0.01 * (i + 1)
+      );
+      point.czheight =
+        startpoint.czheight -
+        (startpoint.czheight - endpoint.czheight) * 0.01 * (i + 1);
+      points.push(point);
+    }
+
+    var pointDepths = SunshineAnalysisByJS.getHighPrecisionGeoDepths(
+      context,
+      scene,
+      points,
+      pixels
+    );
+    for (let index = 0; index < pointDepths.length; index++) {
+      const element = pointDepths[index];
+      if (element) {
+        // var cartographic = Cesium.Cartesian3.fromDegrees(
+        //   Cesium.Math.toDegrees(element.longitude),
+        //   Cesium.Math.toDegrees(element.latitude),
+        //   element.height
+        // ); //经纬度转世界坐标
+        // viewer.entities.add({
+        //   position: cartographic,
+        //   point: {
+        //     pixelSize: 4,
+        //     color: Cesium.Color.RED,
+        //     outlineColor: Cesium.Color.BLACK,
+        //     outlineWidth: 2,
+        //   },
+        // });
+        points[index].zsheight = element.height; //真实点的高程
+        if (points[index].zsheight > points[index].czheight) {
+          isshowders = true;
+        }
+      }
+    }
+
+    if (isshowders) {
+      return false;
+      // console.log("在阴影中");
+    } else {
+      return true;
+      // console.log("不在阴影中");
+    }
+    // console.log(points);
+  },
+
+  getHighPrecisionGeoDepths(context, scene, positions, pixels, options = {}) {
+    const { enableSubPixel = true } = options;
+
+    const packedDepthScale = new Cesium.Cartesian4(
+      1.0,
+      1 / 255,
+      1 / 65025,
+      1 / 16581375
+    );
+
+    // if (!Cesium.defined(framebuffer)) return undefined;
+    if (!positions || positions.length == 0) return [];
+
+    // 高精度坐标转换
+    const preciseCoords = positions.map((pos) => {
+      const cartesian = Cesium.Cartesian3.fromDegrees(
+        pos.longitude,
+        pos.latitude,
+        pos.height || 20,
+        scene.globe.ellipsoid
+      );
+      // 转换为屏幕像素坐标
+      const screenPos = scene.cartesianToCanvasCoordinates(cartesian);
+      //屏幕坐标转深度图坐标
+      screenPos.y = scene.canvas.height - 1 - screenPos.y;
+      if (
+        !screenPos ||
+        screenPos.x < 0 ||
+        screenPos.x >= scene.canvas.width ||
+        screenPos.y < 0 ||
+        screenPos.y >= scene.canvas.height
+      ) {
+        return null;
+      }
+
+      return {
+        x: screenPos.x, // 保留浮点精度
+        y: screenPos.y,
+        dx: screenPos.x - Math.floor(screenPos.x), // 小数部分
+        dy: screenPos.y - Math.floor(screenPos.y),
+      };
+    });
+
+    // 构建采样点集合
+    const samples = [];
+    preciseCoords.forEach((coord, index) => {
+      if (!coord) return;
+
+      const baseX = Math.floor(coord.x);
+      const baseY = Math.floor(coord.y);
+
+      // 根据插值模式收集采样点
+      const points = enableSubPixel
+        ? [
+            { x: baseX, y: baseY, weight: (1 - coord.dx) * (1 - coord.dy) },
+            { x: baseX + 1, y: baseY, weight: coord.dx * (1 - coord.dy) },
+            { x: baseX, y: baseY + 1, weight: (1 - coord.dx) * coord.dy },
+            { x: baseX + 1, y: baseY + 1, weight: coord.dx * coord.dy },
+          ]
+        : [{ x: Math.round(coord.x), y: Math.round(coord.y), weight: 1 }];
+
+      points.forEach((point) => {
+        samples.push({
+          sourceIndex: index,
+          x: point.x,
+          y: point.y,
+          weight: point.weight,
+        });
+      });
+    });
+
+    // 计算采样区域
+
+    let minX = 0,
+      minY = 0;
+    let maxX = scene.canvas.width,
+      maxY = scene.canvas.height;
+    // let minX = Infinity,
+    //   minY = Infinity;
+    // let maxX = -Infinity,
+    //   maxY = -Infinity;
+    // samples.forEach((s) => {
+    //   minX = Math.min(minX, s.x);
+    //   minY = Math.min(minY, s.y);
+    //   maxX = Math.max(maxX, s.x);
+    //   maxY = Math.max(maxY, s.y);
+    // });
+
+    // const width = maxX - minX + 1;
+    // const height = maxY - minY + 1;
+    const width = maxX - minX;
+    const height = maxY - minY;
+
+    // // 批量读取像素数据
+    // let framebufferCopy = viewer.scene._view.globeDepth._copyDepthFramebuffer;
+    // let context = viewer.scene.context;
+    // const pixels = context.readPixels({
+    //   x: minX,
+    //   y: minY,
+    //   width,
+    //   height,
+    //   framebufferCopy,
+    // });
+
+    // 初始化结果容器
+    const results = new Array(positions.length).fill(undefined);
+    if (!pixels || pixels.length < width * height * 4) return results;
+
+    // 创建深度缓存
+    const depthCache = new Map();
+    samples.forEach((sample) => {
+      const key = `${sample.x},${sample.y}`;
+      if (!depthCache.has(key)) {
+        const dx = sample.x - minX;
+        const dy = sample.y - minY;
+        if (dx < 0 || dx >= width || dy < 0 || dy >= height) return;
+
+        const pixelIndex = (dy * width + dx) * 4;
+        const packed = new Cesium.Cartesian4(
+          pixels[pixelIndex],
+          pixels[pixelIndex + 1],
+          pixels[pixelIndex + 2],
+          pixels[pixelIndex + 3]
+        );
+        Cesium.Cartesian4.divideByScalar(packed, 255, packed);
+        depthCache.set(key, Cesium.Cartesian4.dot(packed, packedDepthScale));
+      }
+    });
+
+    // 计算加权深度值
+    const depthAccumulator = new Map();
+    samples.forEach((sample) => {
+      const key = `${sample.x},${sample.y}`;
+      const depth = depthCache.get(key);
+      if (depth === undefined) return;
+
+      const current = depthAccumulator.get(sample.sourceIndex) || {
+        sum: 0,
+        weight: 0,
+      };
+      current.sum += depth * sample.weight;
+      current.weight += sample.weight;
+      depthAccumulator.set(sample.sourceIndex, current);
+    });
+
+    // 生成最终结果
+    depthAccumulator.forEach((value, index) => {
+      var v = value.weight > 0 ? value.sum / value.weight : 0;
+      //这里直接用深度图坐标转世界坐标
+      let res = Cesium.SceneTransforms.drawingBufferToWgs84Coordinates(
+        scene,
+        new Cesium.Cartesian2(preciseCoords[index].x, preciseCoords[index].y),
+        v,
+        new Cesium.Cartesian3()
+      );
+      let carp = Cesium.Cartographic.fromCartesian(res);
+      results[index] = carp; //value.weight > 0 ? value.sum / value.weight : undefined;
+    });
+
+    return results;
+  },
+  //计算日照时间范围
+  calculateTime(selDate, startTime, endTime) {
+    var sunriseDate = SunriseSunsetJS.getSunrise(
+      18.31723463241332,
+      109.5112252162011,
+      selDate
+    );
+    var sunsetdate = SunriseSunsetJS.getSunset(
+      18.31723463241332,
+      109.5112252162011,
+      selDate
+    );
+    //参与计算的日出日落时间
+    var jssunriseHours = 0;
+    var jssunsetHours = 0;
+    //日出时间
+    var sunriseHours = sunriseDate.getHours() + sunriseDate.getMinutes() / 60;
+    //日落时间
+    var sunsetHours = sunsetdate.getHours() + sunsetdate.getMinutes() / 60;
+
+    if (startTime > sunriseHours) {
+      jssunriseHours = startTime;
+    } else jssunriseHours = sunriseHours;
+
+    if (endTime > sunsetHours) jssunsetHours = sunsetHours;
+    else jssunsetHours = endTime;
+    return { jssunriseHours: jssunriseHours, jssunsetHours: jssunsetHours };
+  },
+
+  //以下为测试例子
+  Pointxyz() {
+    let framebufferCopy = viewer.scene._view.globeDepth._copyDepthFramebuffer;
+    let context = viewer.scene.context;
+    let scene = viewer.scene;
+
+    let depth = SunshineAnalysisByJS.getDepth(context, 0, 0, framebufferCopy);
+    let res = Cesium.SceneTransforms.drawingBufferToWgs84Coordinates(
+      scene,
+      new Cesium.Cartesian2(0, 0),
+      depth,
+      new Cesium.Cartesian3()
+    );
+    let carp = Cesium.Cartographic.fromCartesian(res);
+
+    var cartographic = Cesium.Cartesian3.fromDegrees(
+      Cesium.Math.toDegrees(carp.longitude),
+      Cesium.Math.toDegrees(carp.latitude),
+      20
+    ); //经纬度转世界坐标
+    var labelentity = viewer.entities.add({
+      position: cartographic,
+      point: {
+        pixelSize: 4,
+        color: Cesium.Color.RED,
+        outlineColor: Cesium.Color.BLACK,
+        outlineWidth: 2,
+      },
+    });
+    // viewer.flyTo(labelentity);
+    console.log(depth, res, carp.height);
+    console.log(
+      Cesium.Math.toDegrees(carp.longitude),
+      Cesium.Math.toDegrees(carp.latitude),
+      carp.height
+    );
+
+    var terCartographic = new Cesium.Cartographic(
+      carp.longitude,
+      carp.latitude,
+      0
+    ); //转经纬度对像
+    var cartographichight = viewer.scene.sampleHeight(terCartographic); //坐标点获取建筑物高程
+
+    var cartographic1 = Cesium.Cartesian3.fromDegrees(
+      Cesium.Math.toDegrees(carp.longitude),
+      Cesium.Math.toDegrees(carp.latitude),
+      cartographichight
+    ); //经纬度转世界坐标
+
+    console.log(cartographichight);
+
+    let res11 = SunshineAnalysisByJS.getDepthArray(context, framebufferCopy);
+    console.log(res11);
+  },
+  getDepth(context, x, y, framebuffer) {
+    const scratchPackedDepth = new Cesium.Cartesian4();
+    const packedDepthScale = new Cesium.Cartesian4(
+      1.0,
+      1.0 / 255.0,
+      1.0 / 65025.0,
+      1.0 / 16581375.0
+    );
+    // If this function is called before the framebuffer is created, the depth is undefined.
+    if (!Cesium.defined(framebuffer)) {
+      return undefined;
+    }
+    const pixels = context.readPixels({
+      x: x,
+      y: y,
+      width: 1,
+      height: 1,
+      framebuffer: framebuffer,
+    });
+    const packedDepth = Cesium.Cartesian4.unpack(pixels, 0, scratchPackedDepth);
+    Cesium.Cartesian4.divideByScalar(packedDepth, 255.0, packedDepth);
+    return Cesium.Cartesian4.dot(packedDepth, packedDepthScale);
+  },
+  getDepthArray(context, framebuffer) {
+    // If this function is called before the framebuffer is created, the depth is undefined
+    if (!Cesium.defined(framebuffer)) {
+      return undefined;
+    }
+    let width = viewer.scene.drawingBufferWidth;
+    let height = viewer.scene.drawingBufferHeight;
+    const pixels = context.readPixels({
+      x: 0,
+      y: 0,
+      width: width,
+      height: height,
+      framebuffer: framebuffer,
+    });
+    let k = 0;
+    let rest = [];
+    const packedDepthScale = new Cesium.Cartesian4(
+      1.0,
+      1.0 / 255.0,
+      1.0 / 65025.0,
+      1.0 / 16581375.0
+    );
+    for (let index = 0; index < width; index += 100) {
+      for (let j = 0; j < height; j += 100) {
+        const scratchPackedDepth = new Cesium.Cartesian4();
+
+        let arr = [
+          pixels[4 * k],
+          pixels[4 * k + 1],
+          pixels[4 * k + 2],
+          pixels[4 * k + 3],
+        ];
+        const packedDepth = Cesium.Cartesian4.unpack(
+          arr,
+          0,
+          scratchPackedDepth
+        );
+        Cesium.Cartesian4.divideByScalar(packedDepth, 255.0, packedDepth);
+        let dp = Cesium.Cartesian4.dot(packedDepth, packedDepthScale);
+
+        let res = Cesium.SceneTransforms.drawingBufferToWgs84Coordinates(
+          scene,
+          new Cesium.Cartesian2(index, j),
+          dp,
+          new Cesium.Cartesian3()
+        );
+        let carp = Cesium.Cartographic.fromCartesian(res);
+        carp.longitude = Cesium.Math.toDegrees(carp.longitude);
+        carp.latitude = Cesium.Math.toDegrees(carp.latitude);
+        rest.push(carp);
+        k++;
+      }
+    }
+    return rest;
+  },
+};
+export default SunshineAnalysisByJS;

Неке датотеке нису приказане због велике количине промена