<template>
  <div id="cesiumContainer">
    <!-- <div class="get_now_camera_view">
      <van-button @click="consoleCameraPosition"> 当前视角 </van-button>
      <van-button @click="setViewDefaultlocation"> 复位 </van-button>
    </div>
    <van-popup
      v-model:show="dialogVisible"
      :style="{ height: '50%', width: '80%' }"
      :closed="hideInfoDailog"
    >
      <div>
        <div style="font-size: 16px">{{ dialogInfoStr }}</div>
        <van-button @click="hideInfoDailog">关 闭</van-button>
        <van-button :class="'copy_info_dialog'" type="primary">
          复 制
        </van-button>
      </div>
    </van-popup> -->
  </div>
  <Tool></Tool>
</template>

<script>
// import Clipboard from "clipboard";
import { defineAsyncComponent } from "vue";
import Water from "@/utils/Water";

export default {
  data() {
    return {
      dialogVisible: false,
      dialogInfoStr: "",
      clipboard: null,
      correctCamera: false,
      waterObj: null, // 水面实例
      flylineObj: [], // 飞线数组
      topK: [
        {
          lon: 121.12265818599361,
          lat: 31.153907327111906,
          h: 12.178229477117695,
        },
        {
          lon: 121.12264787421734,
          lat: 31.15395149031556,
          h: 12.178192986180326,
        },
        {
          lon: 121.12278546708409,
          lat: 31.153975342725264,
          h: 12.178415363887282,
        },
        {
          lon: 121.12281310059657,
          lat: 31.15385762853425,
          h: 12.178399877503464,
        },
        {
          lon: 121.1228576094918,
          lat: 31.15386519051712,
          h: 12.178394232107442,
        },
        {
          lon: 121.1228909000206,
          lat: 31.153723309251856,
          h: 12.17857353611858,
        },
        {
          lon: 121.12294578609598,
          lat: 31.153732796983615,
          h: 12.178675754028028,
        },
        {
          lon: 121.12298033312791,
          lat: 31.153585333373417,
          h: 12.17876227737616,
        },
        {
          lon: 121.1228480316718,
          lat: 31.15356239349922,
          h: 12.178326652099466,
        },
        {
          lon: 121.12283863696666,
          lat: 31.153602052352188,
          h: 12.178301731797035,
        },
        {
          lon: 121.12279132401528,
          lat: 31.153593731079162,
          h: 12.17821160134978,
        },
        {
          lon: 121.12280904366847,
          lat: 31.153517944755357,
          h: 12.178387628978598,
        },
        {
          lon: 121.12256003807408,
          lat: 31.15347475524662,
          h: 12.178108003497535,
        },
        {
          lon: 121.12255140331416,
          lat: 31.153510889388823,
          h: 12.178086221333002,
        },
        {
          lon: 121.12251427275822,
          lat: 31.153504509859477,
          h: 12.17756730102783,
        },
        { lon: 121.1224291079002, lat: 31.15386748647, h: 12.177529555001517 },
      ],
    };
  },
  components: {
    Tool: defineAsyncComponent(() => import("@/components/Tool.vue")),
  },
  created() {},
  mounted() {
    let that = this;
    // this.clipboard = new Clipboard(".copy_info_dialog", {
    //   // 点击copy按钮，直接通过text直接返回复印的内容
    //   text: function () {
    //     return that.dialogInfoStr;
    //   },
    // });
    this.waterObj = new Water();
    window.controlCZ = this.controlCZ;
    this.$root.$.appContext.config.globalProperties.$flyTo = this.flyTo;
    // this.setfixGltf();
    this.initViewer().then(() => {
      this.mapConfig();
      // 默认视角
      this.setViewDefaultlocation().then(() => {
        that.mainFunc();
      });
    });
    window.getNowCameraPosition1 = this.getNowCameraPosition;
    window.getNowCameraPosition = function () {
      this.getNowCameraPosition().then((result) => {
        this.showInfoDailog(result.info);
      });
    };
    return;
  },

  methods: {
    setfixGltf() {
      var fixGltf = function (gltf) {
        if (!gltf.extensionsUsed) {
          return;
        }

        var v = gltf.extensionsUsed.indexOf("KHR_technique_webgl");
        var t = gltf.extensionsRequired.indexOf("KHR_technique_webgl");
        // 中招了。。
        if (v !== -1) {
          gltf.extensionsRequired.splice(t, 1, "KHR_techniques_webgl");
          gltf.extensionsUsed.splice(v, 1, "KHR_techniques_webgl");
          gltf.extensions = gltf.extensions || {};
          gltf.extensions["KHR_techniques_webgl"] = {};
          gltf.extensions["KHR_techniques_webgl"].programs = gltf.programs;
          gltf.extensions["KHR_techniques_webgl"].shaders = gltf.shaders;
          gltf.extensions["KHR_techniques_webgl"].techniques = gltf.techniques;
          var techniques = gltf.extensions["KHR_techniques_webgl"].techniques;

          gltf.materials.forEach(function (mat, index) {
            gltf.materials[index].extensions["KHR_technique_webgl"].values =
              gltf.materials[index].values;
            gltf.materials[index].extensions["KHR_techniques_webgl"] =
              gltf.materials[index].extensions["KHR_technique_webgl"];

            var vtxfMaterialExtension =
              gltf.materials[index].extensions["KHR_techniques_webgl"];

            for (var value in vtxfMaterialExtension.values) {
              var us = techniques[vtxfMaterialExtension.technique].uniforms;
              for (var key in us) {
                if (us[key] === value) {
                  vtxfMaterialExtension.values[key] =
                    vtxfMaterialExtension.values[value];
                  delete vtxfMaterialExtension.values[value];
                  break;
                }
              }
            }
          });

          techniques.forEach(function (t) {
            for (var attribute in t.attributes) {
              var name = t.attributes[attribute];
              t.attributes[attribute] = t.parameters[name];
            }

            for (var uniform in t.uniforms) {
              var name = t.uniforms[uniform];
              t.uniforms[uniform] = t.parameters[name];
            }
          });
        }
      };

      Object.defineProperties(Cesium.Model.prototype, {
        _cachedGltf: {
          set: function (value) {
            this._vtxf_cachedGltf = value;
            if (this._vtxf_cachedGltf && this._vtxf_cachedGltf._gltf) {
              fixGltf(this._vtxf_cachedGltf._gltf);
            }
          },
          get: function () {
            return this._vtxf_cachedGltf;
          },
        },
      });
    },

    consoleCameraPosition() {
      this.getNowCameraPosition().then((result) => {
        this.showInfoDailog(
          JSON.stringify(result.result).replaceAll("{", "").replaceAll("}", "")
        );
      });
    },

    initViewer() {
      return new Promise((resolve, reject) => {
        // globalVariable.viewer = new Cesium.Viewer("cesiumContainer", {
        //   // useDefaultRenderLoop: false,  //关闭自动渲染
        //   animation: false, //动画控制不显示
        //   timeline: false, //时间线不显示
        //   fullscreenButton: false, //全屏按钮不显示
        //   infoBox: false,
        //   baseLayerPicker: false, //地图切换不显示
        //   // terrainProvider: Cesium.createWorldTerrain(), // 地形
        //   imageryProvider: new Cesium.SingleTileImageryProvider({
        //     url: (function createColorCanvas(color) {
        //       var width = 1,
        //         height = 1;
        //       var canvas = document.createElement("canvas");
        //       canvas.width = width;
        //       canvas.height = height;
        //       var ctx = canvas.getContext("2d");
        //       ctx.fillStyle = color;
        //       ctx.fillRect(0, 0, width, height);
        //       return canvas.toDataURL();
        //     })("#ffffff00"),
        //     rectangle: Cesium.Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0),
        //   }),
        //   geocoder: false,
        //   homeButton: false,
        //   selectionIndicator: false, // 去除绿色选择框
        //   sceneModePicker: false,
        //   navigationHelpButton: false,
        //   scene3DOnly: true, // 仅以3D渲染以节省GPU内存
        //   useBrowserRecommendedResolution:
        //     systemConfig.useBrowserRecommendedResolution, // 以浏览器建议的分辨率渲染
        //   //  设置为了去掉天空盒子
        //   orderIndependentTranslucency: true,
        //   // maximumRenderTimeChange: Infinity, // 无操作时自动渲染帧率，设为数字会消耗性能，Infinity为无操作不渲染
        //   // // 开启 webgl 2.0
        //   // contextOptions: {
        //   //   requestWebgl2: true,
        //   // },
        //   // resolutionScale: 1, //清晰度 0-1
        //   // targetFrameRate: 165, //设置最大频率数
        //   // maximumScreenSpaceError: 8, //屏幕空间最大误差
        // });
        globalVariable.viewer = new Cesium.Viewer("cesiumContainer", {
          animation: false, // 是否创建动画小器件，左下角仪表
          baseLayerPicker: false, // 是否显示图层选择器
          fullscreenButton: false, // 是否显示全屏按钮
          vrButton: false, // 是否创建VRButton小工具
          geocoder: false, // 是否显示geocoder小器件，右上角查询按钮
          homeButton: false, // 是否显示Home按钮
          infoBox: false, // 是否显示信息框
          sceneModePicker: false, // 是否显示3D/2D选择器
          selectionIndicator: false, // 是否显示选取指示器组件
          timeline: false, // 是否显示时间轴
          navigationHelpButton: false, // 是否显示右上角的帮助按钮
          navigationInstructionsInitiallyVisible: false, // 如果导航指示最初应可见，则为True；如果用户明确单击按钮后才显示，则为false。
          scene3DOnly: true, // 如果设置为true，则所有几何图形以3D模式绘制以节约GPU资源
          shouldAnimate: false, // 默认情况下，如果时钟应尝试提前模拟时间，则为true，否则为false。此选项优先于设置
          clock: new Cesium.Clock(), // 用于控制当前时间的时钟对象
          clockViewModel: new Cesium.ClockViewModel(
            new Cesium.Clock({
              startTime: Cesium.JulianDate.fromIso8601("2013-12-25"),
              currentTime: Cesium.JulianDate.fromIso8601("2013-12-25"),
              stopTime: Cesium.JulianDate.fromIso8601("2013-12-26"),
              clockRange: Cesium.ClockRange.LOOP_STOP,
              clockStep: Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER,
            })
          ), // 用于控制当前时间的时钟对象
          selectedImageryProviderViewModel: undefined, // 当前图像图层的显示模型，仅baseLayerPicker设为true有意义
          imageryProviderViewModels:
            Cesium.createDefaultImageryProviderViewModels(), // 可供BaseLayerPicker选择的图像图层ProviderViewModel数组
          selectedTerrainProviderViewModel: undefined, // 当前地形图层的显示模型，仅baseLayerPicker设为true有意义
          terrainProviderViewModels:
            Cesium.createDefaultTerrainProviderViewModels(), // 可供BaseLayerPicker选择的地形图层ProviderViewModel数组
          imageryProvider: new Cesium.SingleTileImageryProvider({
            url: (function createColorCanvas(color) {
              // 返回空白
              var width = 1,
                height = 1;
              var canvas = document.createElement("canvas");
              canvas.width = width;
              canvas.height = height;
              var ctx = canvas.getContext("2d");
              ctx.fillStyle = color;
              ctx.fillRect(0, 0, width, height);
              return canvas.toDataURL();
            })("#ffffff00"),
            rectangle: Cesium.Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0),
          }), // 图像图层提供者，仅baseLayerPicker设为false有意义
          // terrainProvider: new Cesium.EllipsoidTerrainProvider(), // 地形图层提供者，仅baseLayerPicker设为false有意义
          // skyBox: new Cesium.SkyBox({
          //   sources: {
          //     positiveX: "Cesium-1.7.1/Skybox/px.jpg",
          //     negativeX: "Cesium-1.7.1/Skybox/mx.jpg",
          //     positiveY: "Cesium-1.7.1/Skybox/py.jpg",
          //     negativeY: "Cesium-1.7.1/Skybox/my.jpg",
          //     positiveZ: "Cesium-1.7.1/Skybox/pz.jpg",
          //     negativeZ: "Cesium-1.7.1/Skybox/mz.jpg",
          //   },
          // }), // 用于渲染星空的SkyBox对象
          fullscreenElement: document.body, // 全屏时渲染的HTML元素,
          useDefaultRenderLoop: true, // 如果需要控制渲染循环，则设为true
          targetFrameRate: undefined, // 使用默认render loop时的帧率
          showRenderLoopErrors: false, // 如果设为true，将在一个HTML面板中显示错误信息
          automaticallyTrackDataSourceClocks: true, // 自动追踪最近添加的数据源的时钟设置
          sceneMode: Cesium.SceneMode.SCENE3D, // 初始场景模式
          mapProjection: new Cesium.WebMercatorProjection(), // 地图投影体系
          dataSources: new Cesium.DataSourceCollection(), // 需要进行可视化的数据源的集合
          // contextOptions: {
          //   // 传递给Scene对象的上下文参数（scene.options） 截图需要的
          //   // webgl: {
          //   //   alpha: true,
          //   //   depth: true,
          //   //   stencil: true,
          //   //   antialias: true,
          //   //   premultipliedAlpha: true,
          //   //   // 通过canvas.toDataURL()实现截图需要将该项设置为true
          //   //   preserveDrawingBuffer: true,
          //   //   failIfMajorPerformanceCaveat: true,
          //   // },
          //   webgl: {
          //     webgl: {
          //       alpha: false, // (boolean)值表明canvas包含一个alpha缓冲区。
          //       depth: true, // (boolean)值表明绘制缓冲区包含一个深度至少为16位的缓冲区。
          //       stencil: false, // 表明绘制缓冲区包含一个深度至少为8位的模版缓冲区boolean值。
          //       antialias: true, //  (boolean)值表明是否开启抗锯齿
          //       //指示浏览器在运行WebGL上下文时使用相应的GPU电源配置。 可能值如下:
          //       // "default":自动选择，默认值。
          //       // "high-performance": 高性能模式。
          //       // "low-power": 节能模式。
          //       powerPreference: "low-power",
          //       premultipliedAlpha: true, // 表明排版引擎讲假设绘制缓冲区包含预混合alpha通道的boolean值。
          //       preserveDrawingBuffer: false, // 如果这个值为true缓冲区将不会被清除，会保存下来，直到被清除或被使用者覆盖。
          //       failIfMajorPerformanceCaveat: false, // 表明在一个系统性能低的环境是否创建该上下文的boolean值。
          //     },
          //     allowTextureFilterAnisotropic: true,
          //   },
          // },
        });

        if (systemConfig.msaaSamples != 0) {
          globalVariable.viewer.scene.msaaSamples = systemConfig.msaaSamples;
        }
        //去除版权标记
        globalVariable.viewer._cesiumWidget._creditContainer.style.display =
          "none";
        resolve();
      });
    },

    mainFunc() {
      let that = this;
      // camera范围限制
      this.bindLimitCameraFunc();

      // 取消滑动事件
      this.controlCZ(systemConfig.mapControl);

      // 自定义滑动事件
      this.wetherScroll(this.changeCamera);

      // // 加载地图瓦片
      // this.addMapTiles("arcgis");

      window.bindLimitCameraFunc = this.bindLimitCameraFunc;
      window.unbindLimitCameraFunc = this.unbindLimitCameraFunc;

      // entity点击事件
      this.entityClickEvent();
      // 键盘/地图点击事件
      // this.singleClick(viewer); // 地图点击
      this.singleClick2(); // 模型点击
      keyboardMapRoamingInit(globalVariable.viewer);

      // this.addGltf("http://192.168.1.37/model_data/QPXZFUZX/20220921/obj/output/gltf/Image60/1C.gltf", 121.1225983493769, 31.153846152219288, 0);
      // this.addGltf("http://192.168.1.37/model_data/QPXZFUZX/20220921/obj/output/gltf/Image60/2C.gltf", 121.1225983493769, 31.153846152219288, 0);
      // this.addGltf("http://192.168.1.37/model_data/QPXZFUZX/20220921/obj/output/gltf/Image60/3C.gltf", 121.1225983493769, 31.153846152219288, 0);

      // return;

      let keyArr = Object.keys(systemConfig.tilesConfig);
      for (let i = 0; i < keyArr.length; i++) {
        const str = keyArr[i];
        globalVariable.tilesArr[str] = this.add3DTilesData(
          systemConfig.dataUrl + str + "/tileset.json", //
          {
            light: systemConfig.tilesConfig[str].light,
          }
        );
      }

      // // 飞线加载
      // this.addFlyLine();

      // 水面加载
      this.addWaterPanel();

      // // 树木加载
      // this.addTree();
    },

    // bindCameraNo() {
    //   globalVariable.viewer.scene.preUpdate.addEventListener(this.cameraddte);
    // },
    // unbindCamera() {
    //   globalVariable.viewer.scene.preUpdate.removeEventListener(
    //     this.cameraddte
    //   );
    // },
    // cameraddte() {
    //   // 获取当前位置，当前方向，强制禁止X轴、Y轴
    //   var heading = Cesium.Math.toDegrees(globalVariable.viewer.camera.heading);
    //   var pitch = Cesium.Math.toDegrees(globalVariable.viewer.camera.pitch); //Cesium.Math.toDegrees作用是把弧度转换成度数
    //   var roll = Cesium.Math.toDegrees(globalVariable.viewer.camera.roll);

    //   var positionCartesian = globalVariable.viewer.camera.position;
    //   // var position = Cesium.Cartographic.fromCartesian(positionCartesian);
    //   // var lon = Cesium.Math.toDegrees(position.longitude);
    //   // var lat = Cesium.Math.toDegrees(position.latitude);
    //   // var h = globalVariable.viewer.camera.positionCartographic.height;
    //   globalVariable.viewer.camera.setView({
    //     destination: positionCartesian, //赤道上空1000km高度
    //     orientation: {
    //       heading: Cesium.Math.toRadians(heading), // 相机方向指向当地东向
    //       pitch: 0.0, // 再将相机方向转向地心，此时Up方向指向当地东向
    //       roll: 0.0,
    //     },
    //   });
    // },

    // entity Click
    entityClickEvent() {
      let viewClickHandle = new Cesium.ScreenSpaceEventHandler(
        globalVariable.viewer.scene.canvas
      );
      viewClickHandle.setInputAction(function (evt) {
        var pickedObject = globalVariable.viewer.scene.pick(evt.position);
        if (pickedObject && pickedObject.id) {
          var clickMarkerId = pickedObject.id._id;
          if (globalVariable.point_positions[clickMarkerId]) {
            var data = globalVariable.point_positions[clickMarkerId];
            if (data.callback) {
              data.callback(data.infos);
            }
          }
        } else {
          return false;
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    },

    changeCamera(direction) {
      switch (direction) {
        case "left":
          globalVariable.viewer.camera.lookLeft((Math.PI / 180) * 2);
          break;

        case "right":
          globalVariable.viewer.camera.lookRight((Math.PI / 180) * 2);
          break;

        default:
          break;
      }
    },

    wetherScroll(func) {
      let startX = 0;
      let startY = 0;
      let endX = 0;
      let endY = 0;
      let distanceX = 0;
      let distanceY = 0;
      let body = document.getElementById("cesiumContainer");
      var clientHeight = document.documentElement.clientHeight;
      var clientWidth = document.documentElement.clientWidth;
      body.addEventListener("touchstart", function (event) {
        var touch = event.targetTouches[0];
        //滑动起点的坐标
        startX = touch.pageX;
        startY = touch.pageY;
        // console.log("startX:"+startX+","+"startY:"+startY);
      });
      body.addEventListener("touchmove", function (event) {
        var touch = event.targetTouches[0];
        //手势滑动时，手势坐标不断变化，取最后一点的坐标为最终的终点坐标
        endX = touch.pageX;
        endY = touch.pageY;
        distanceX = endX - startX;
        distanceY = endY - startY;
        if (startX != Math.abs(distanceX)) {
          //在滑动的距离超过屏幕高度的20%时，做某种操作
          if (Math.abs(distanceX) > clientWidth * 0.001) {
            //向下滑实行函数someAction1，向上滑实行函数someAction2
            //向左滑实行函数someAction1，向右滑实行函数someAction2
            distanceX < 0 ? func("left") : func("right");
            startX = endX;
            startY = endY;
          }
        }
        // console.log("endX:"+endX+","+"endY:"+endY);
      });
      body.addEventListener("touchend", function (event) {
        // distanceX = endX - startX;
        // distanceY = endY - startY;
        // // console.log("distanceX:"+distanceX+","+"distanceY:"+distanceY);
        // //移动端设备的屏幕宽度
        // var clientHeight = document.documentElement.clientHeight;
        // // console.log(clientHeight;*0.2);
        // //判断是否滑动了，而不是屏幕上单击了
        // if (startY != Math.abs(distanceY)) {
        //   //在滑动的距离超过屏幕高度的20%时，做某种操作
        //   if (Math.abs(distanceY) > clientHeight * 0.2) {
        //     //向下滑实行函数someAction1，向上滑实行函数someAction2
        //     distanceY < 0 ? someAction1() : someAction2();
        //   }
        // }
        startX = 0;
        startY = 0;
        endX = 0;
        endY = 0;
        distanceX = 0;
        distanceY = 0;
      });
    },

    // 禁用/开启 操作
    controlCZ(bool) {
      globalVariable.viewer.scene.screenSpaceCameraController.enableLook = bool;
      globalVariable.viewer.scene.screenSpaceCameraController.enableRotate =
        bool;
      globalVariable.viewer.scene.screenSpaceCameraController.enableTilt = bool;
      globalVariable.viewer.scene.screenSpaceCameraController.enableTranslate =
        bool;
      globalVariable.viewer.scene.screenSpaceCameraController.enableZoom = bool;
    },

    // 添加地图底图瓦片
    addMapTiles(key) {
      let viewer = globalVariable.viewer;
      switch (key) {
        case "tdt":
          // 加载天地图影像
          viewer.imageryLayers.addImageryProvider(
            new Cesium.WebMapTileServiceImageryProvider({
              url:
                "http://t{s}.tianditu.gov.cn/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=" +
                systemConfig.tdt_tk,
              // url: "/proxy_tdt/proxy{s}/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk="+systemConfig.tdt_tk,
              layer: "img",
              style: "default",
              tileMatrixSetID: "w",
              format: "image/jpeg",
              subdomains: ["0", "1", "2", "3", "4", "5", "6", "7"],
              tileMatrixSetID: "GoogleMapsCompatible",
              show: true,
              minimumLevel: 1,
              maximumLevel: 18,
              // rectangle: Cesium.Rectangle.fromDegrees(90, -90, 180, -180),
            })
          );
          //加载影像注记
          viewer.imageryLayers.addImageryProvider(
            new Cesium.WebMapTileServiceImageryProvider({
              url:
                "http://t{s}.tianditu.gov.cn/cia_w/wmts?tk=" +
                systemConfig.tdt_tk,
              layer: "cia",
              style: "default",
              tileMatrixSetID: "w",
              format: "tiles",
              subdomains: ["0", "1", "2", "3", "4", "5", "6", "7"],
              maximumLevel: 20,
            })
          );
          break;
        case "xq":
          viewer.imageryLayers.addImageryProvider(
            new Cesium.UrlTemplateImageryProvider({
              url: "http://119.3.233.75/tile/v1.0/gr?l={z}&x={x}&y={y}",
              minimumLevel: 1,
              maximumLevel: 19,
              format: "png",
            })
          );

          break;
        case "arcgis":
          // 加载ArcGIS在线地图
          viewer.imageryLayers.addImageryProvider(
            new Cesium.ArcGisMapServerImageryProvider({
              url: "https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer",
            })
          );
          break;

        default:
          break;
      }
      viewer = null;
    },

    // 默认定位
    setViewDefaultlocation() {
      return new Promise((resolve, reject) => {
        this.$flyTo({
          lon: systemConfig.mapDefault.center.lon,
          lat: systemConfig.mapDefault.center.lat,
          h: systemConfig.mapDefault.height,
          heading: systemConfig.mapDefault.heading,
          pitch: systemConfig.mapDefault.pitch,
          roll: systemConfig.mapDefault.roll,
          time: 1,
          pitchAdjustHeight: 1000,
          callback: null,
        }).then(() => {
          resolve();
        });
      });
    },
    flyTo(item) {
      return new Promise((resolve, reject) => {
        globalVariable.viewer.camera.flyTo({
          destination: Cesium.Cartesian3.fromDegrees(
            item.lon,
            item.lat,
            item.h
          ),
          orientation: {
            heading: Cesium.Math.toRadians(item.heading), // 方向
            pitch: Cesium.Math.toRadians(item.pitch), // 倾斜角度
            roll: Cesium.Math.toRadians(item.roll),
          },
          duration: isNaN(item.time) ? 2 : item.time,
          pitchAdjustHeight: item.pitchAdjustHeight || 1000,
          complete: function () {
            if (item) {
              if (item.callback) item.callback(item);
            }
            resolve();
          },
        });
      });
    },

    // cesium 球体配置
    mapConfig() {
      // 大气效果（发光）
      globalVariable.viewer.scene.globe.showGroundAtmosphere = false;
      // 是否将地球渲染为半透明的球体
      globalVariable.viewer.scene.globe.translucency.enabled = true;
      // 基础球体颜色
      globalVariable.viewer.scene.globe.baseColor = Cesium.Color.TRANSPARENT;
      // 地底颜色
      globalVariable.viewer.scene.globe.undergroundColor = undefined;

      // 开启场景光照
      // globalVariable.viewer.scene.globe.enableLighting = true;
      // 控制太阳光
      globalVariable.viewer.scene.sun.show = systemConfig.sunShow;
      // 控制阴影
      globalVariable.viewer.shadows = systemConfig.shadows;
      // 阴影强度
      globalVariable.viewer.shadowMap.darkness = systemConfig.shadowMapDarkness;

      // globalVariable.viewer.terrainShadows = Cesium.ShadowMode.RECEIVE_ONLY;
      // // globalVariable.viewer.shadowMap.softShadows  = truee
      // globalVariable.viewer.shadowMap.darkness = 0.7; //阴影透明度--越大越透明
      if (systemConfig.DirectionalLightShow) {
        globalVariable.viewer.scene.light = new Cesium.DirectionalLight({
          color: new Cesium.Color(
            systemConfig.DirectionalLightColor.r,
            systemConfig.DirectionalLightColor.g,
            systemConfig.DirectionalLightColor.b,
            systemConfig.DirectionalLightColor.a
          ),
          // //去除时间原因影响模型颜色
          // direction: Cesium.Cartesian3.fromDegrees(
          //   121.1217914833498,
          //   31.154385387088624,
          //   2000
          // ),
          direction: new Cesium.Cartesian3(
            systemConfig.DirectionalLightDirection.x,
            systemConfig.DirectionalLightDirection.y,
            systemConfig.DirectionalLightDirection.z
          ),
          intensity: systemConfig.DirectionalLightIntensity,
        });
      }

      // globalVariable.viewer._cesiumWidget._supportsImageRenderingPixelated =
      //   Cesium.FeatureDetection.supportsImageRenderingPixelated();
      // globalVariable.viewer._cesiumWidget._forceResize = true;

      // 解决抗锯齿问题
      // // 方法一
      // if (Cesium.FeatureDetection.supportsImageRenderingPixelated()) {
      //   //判断是否支持图像渲染像素化处理
      //   var vtxf_dpr = window.devicePixelRatio;
      //   // 适度降低分辨率
      //   while (vtxf_dpr >= 2.0) {
      //     vtxf_dpr /= 2.0;
      //   }
      //   //alert(dpr);
      //   globalVariable.viewer.resolutionScale = vtxf_dpr;
      // }
      // 方法二
      if (Cesium.FeatureDetection.supportsImageRenderingPixelated()) {
        //判断是否支持图像渲染像素化处理
        var vtxf_dpr = window.devicePixelRatio;
        globalVariable.viewer.resolutionScale = vtxf_dpr;
      }

      // //是否开启抗锯齿
      globalVariable.viewer.scene.fxaa = systemConfig.fxaa;
      globalVariable.viewer.scene.postProcessStages.fxaa.enabled =
        systemConfig.fxaaEnabled;

      // // 天空盒隐藏
      // globalVariable.viewer.scene.skyBox.show = false;
      // 配置天空盒子
      this.deploySkyBox();

      // // 地形遮盖
      // globe.depthTestAgainstTerrain = false;
      // let inter = setInterval(() => {
      //   // 改变时间设置光照效果
      //   // let date = new Date().getTime();
      //   let utc = Cesium.JulianDate.fromDate(new Date("2022-06-22"));
      //   //北京时间=UTC+8=GMT+8 不用加8
      //   viewer.clockViewModel.currentTime = Cesium.JulianDate.addHours(
      //     utc,
      //     0,
      //     new Cesium.JulianDate()
      //   );
      // }, 100);

      // globe.translucency.frontFaceAlpha = 1.0;
      // globe.translucency.rectangle = Cesium.Rectangle.fromDegrees(
      //   120.87373270003363,
      //   27.913116219448348,
      //   120.98856425530658,
      //   27.97741914289562
      // );

      // // 地下模式
      // viewer.scene.screenSpaceCameraController.enableCollisionDetection = true ;
      // viewer.scene.undergroundMode = true;
      // // 设置地表透明度
      // viewer.scene.globe.translucency.frontFaceAlpha = 0

      // viewer.scene.globe.depthTestAgainstTerrain = true;
      // viewer.scene.debugShowFramesPerSecond = true;
      // viewer.shadows = true;
      // // viewer.shadowMap.softShadows  = true
      // viewer.shadowMap.darkness = 0.7; //阴影透明度--越大越透明

      // // 改变时间设置光照效果
      // var utc = Cesium.JulianDate.fromDate(new Date("2021/07/04 08:00:00"));
      // //北京时间=UTC+8=GMT+8
      // viewer.clockViewModel.currentTime = Cesium.JulianDate.addHours(
      //   utc,
      //   8,
      //   new Cesium.JulianDate()
      // );
    },

    // 限制camera的移动范围
    bindLimitCameraFunc() {
      // globalVariable.viewer.scene.preRender.addEventListener(function () {});
      // viewer.scene.screenSpaceCameraController.maximumZoomDistance = 20000;
      // viewer.scene.screenSpaceCameraController.minimumZoomDistance = 10;
      globalVariable.viewer.camera.changed.addEventListener(
        this.limitCameraFunc
      );
    },
    unbindLimitCameraFunc() {
      globalVariable.viewer.camera.changed.removeEventListener(
        this.limitCameraFunc
      );
    },
    limitCameraFunc() {
      let that = this;
      if (!this.correctCamera) {
        this.getNowCameraPosition()
          .then((result) => {
            let cameraLon = result.result.lon;
            let cameraLat = result.result.lat;
            let cameraHeight = result.result.h;
            // systemConfig.mapDefault.bbox.west;
            // systemConfig.mapDefault.bbox.east;
            // systemConfig.mapDefault.bbox.north;
            // systemConfig.mapDefault.bbox.south;
            if (
              cameraLon > systemConfig.mapDefault.bbox.east ||
              cameraLon < systemConfig.mapDefault.bbox.west ||
              cameraLat > systemConfig.mapDefault.bbox.north ||
              cameraLat < systemConfig.mapDefault.bbox.south ||
              cameraHeight > systemConfig.mapDefault.defaultH
            ) {
              that.correctCamera = true;
              that.setViewDefaultlocation().then(() => {
                huifu();
              });
            }
            cameraLon = null;
            cameraLat = null;
            cameraHeight = null;
          })
          .catch((err) => {});
      }
      function huifu() {
        that.correctCamera = false;
      }
    },

    // 配置天空盒
    deploySkyBox() {
      // 自定义的近地天空盒
      let groundSkybox = new Cesium.GroundSkyBox({
        sources: {
          negativeX: "./static/images/skybox/Left.jpg",
          negativeY: "./static/images/skybox/Front.jpg",
          negativeZ: "./static/images/skybox/Down.jpg",

          positiveX: "./static/images/skybox/Right.jpg",
          positiveY: "./static/images/skybox/Back.jpg",
          positiveZ: "./static/images/skybox/Up.jpg",
        },
      });

      // // 自带的默认天空盒
      // let defaultSkybox = viewer.scene.skyBox;

      globalVariable.viewer.scene.skyBox = groundSkybox;
      globalVariable.viewer.scene.skyAtmosphere.show = false;

      // // 监听并判断相机位置，切换天空盒
      // globalVariable.viewer.scene.preUpdate.addEventListener(() => {
      //   let position = viewer.scene.camera.position;
      //   let cameraHeight = Cesium.Cartographic.fromCartesian(position).height;
      //   if (cameraHeight < 240000) {
      //     viewer.scene.skyBox = groundSkybox;
      //     viewer.scene.skyAtmosphere.show = false;
      //   } else {
      //     viewer.scene.skyBox = defaultSkybox;
      //     viewer.scene.skyAtmosphere.show = true;
      //   }
      // });
    },

    // 获取当前camera的详细位置
    getNowCameraPosition() {
      let that = this;
      return new Promise((resolve, reject) => {
        var camera = globalVariable.viewer.camera;
        var heading = Cesium.Math.toDegrees(
          globalVariable.viewer.camera.heading
        );
        var pitch = Cesium.Math.toDegrees(globalVariable.viewer.camera.pitch); //Cesium.Math.toDegrees作用是把弧度转换成度数
        var roll = Cesium.Math.toDegrees(globalVariable.viewer.camera.roll);
        var h = globalVariable.viewer.camera.positionCartographic.height;
        var camera = globalVariable.viewer.camera.position;
        var position = Cesium.Cartographic.fromCartesian(camera);
        var lon = Cesium.Math.toDegrees(position.longitude);
        var lat = Cesium.Math.toDegrees(position.latitude);
        console.log(heading)
        console.log(pitch)
        console.log(roll)
        console.log(lon)
        console.log(lat)
        console.log(h) 
        let str = `
      lon:${lon}
      lat:${lat}
      h:${h}
      heading:${heading}
      pitch:${pitch}
      roll:${roll}
      `;
        resolve({
          str: "",
          result: {
            lon: lon,
            lat: lat,
            h: h,
            heading: heading,
            pitch: pitch,
            roll: roll,
          },
        });
      });

      // that.showInfoDailog(str);
    },

    // 地图（地球表面，无地形）左击事件
    singleClick() {
      var handler = new Cesium.ScreenSpaceEventHandler(
        globalVariable.viewer.scene.canvas
      );
      handler.setInputAction(function (event) {
        var earthPosition = globalVariable.viewer.camera.pickEllipsoid(
          event.position,
          globalVariable.viewer.scene.globe.ellipsoid
        );
        var cartographic = Cesium.Cartographic.fromCartesian(
          earthPosition,
          globalVariable.viewer.scene.globe.ellipsoid,
          new Cesium.Cartographic()
        );
        var lat = Cesium.Math.toDegrees(cartographic.latitude);
        var lng = Cesium.Math.toDegrees(cartographic.longitude);
        var height = cartographic.height;
        console.log(lng + "," + lat);
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    },

    // 地图（模型上）左击事件
    singleClick2() {
      let that = this;
      var handler = new Cesium.ScreenSpaceEventHandler(
        globalVariable.viewer.scene.canvas
      );
      handler.setInputAction(function (event) {
        var pick = globalVariable.viewer.scene.pickPosition(event.position);
        var pickModel = globalVariable.viewer.scene.pick(event.position);
        if (pickModel && pick && !pickModel.id) {
          var height = Cesium.Cartographic.fromCartesian(pick).height;
          var lat = Cesium.Math.toDegrees(
            Cesium.Cartographic.fromCartesian(pick).latitude
          );
          var lon = Cesium.Math.toDegrees(
            Cesium.Cartographic.fromCartesian(pick).longitude
          );
          // cartesian = Cesium.Cartesian3.fromDegrees(lng, lat, height);
          // console.log("模型高度点", cartesian);
          let str = `
          lon:${lon}
          lat:${lat}
          height:${height}
          `;
          that.showInfoDailog(
            JSON.stringify({
              lon: lon,
              lat: lat,
              h: height,
            })
              .replaceAll("{", "")
              .replaceAll("}", "")
          );
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    },

    showInfoDailog(str) {
      this.dialogVisible = true;
      this.dialogInfoStr = str;
    },
    hideInfoDailog() {
      this.dialogVisible = false;
    },

    // 加载顶部东线动线特效
    addAnimatedLineToHousetop() {},
    // 加载飞线
    addFlyLine() {
      let that = this;
      this.topK.map(function (item) {
        let startPoint = item;
        let endPoint = Object.assign({}, startPoint);
        endPoint.h = getRandom(199, 200);
        let positions = [
          startPoint.lon,
          startPoint.lat,
          0,
          endPoint.lon,
          endPoint.lat,
          endPoint.h,
        ];
        addLine(positions);
      });

      // for (var j = 0; j < 50; ++j) {
      //   let startPoint = randomPoint();
      //   let endPoint = Object.assign({}, startPoint);
      //   endPoint.h = getRandom(199, 200);

      //   // this.addFlyingLineByEntity(
      //   //   Cesium.Cartesian3.fromDegreesArrayHeights([
      //   //     startPoint.lon,
      //   //     startPoint.lat,
      //   //     startPoint.h,
      //   //     endPoint.lon,
      //   //     endPoint.lat,
      //   //     endPoint.h,
      //   //   ])
      //   // );
      //   // continue;
      // }

      function addLine(positions) {
        // 创建长方体对象
        const PolylineGeometry = new Cesium.PolylineGeometry({
          positions: Cesium.Cartesian3.fromDegreesArrayHeights(positions),
          width: 2,
        });
        const instance = new Cesium.GeometryInstance({
          geometry: PolylineGeometry,
        });
        // this.flylineObj.push(
        globalVariable.viewer.scene.primitives.add(
          new Cesium.Primitive({
            geometryInstances: [instance],
            appearance: that.getFlylineMaterial(1),
            depthFailAppearance: that.getFlylineMaterial(1),
            releaseGeometryInstances: false,
            compressVertices: false,
          })
        );
        // );
      }

      function randomPoint() {
        var jingd = 1000000;
        var jd =
          getRandom(
            systemConfig.mapDefault.bbox.west * jingd,
            systemConfig.mapDefault.bbox.east * jingd
          ) / jingd;
        var wd =
          getRandom(
            systemConfig.mapDefault.bbox.south * jingd,
            systemConfig.mapDefault.bbox.north * jingd
          ) / jingd;
        return {
          lon: jd,
          lat: wd,
          h: 0,
        };
      }
      function getRandom(t, e) {
        return Math.floor(Math.random() * (e - t + 1) + t);
      }
    },
    // 创建飞线材质 1
    getFlylineMaterial(index) {
      // 创建材质，在MaterialAppearance中若不添加基础材质，模型将会透明
      let material = new Cesium.Material.fromType("Color");
      material.uniforms.color = Cesium.Color.ORANGE;
      let fragmentShaderSource;
      if (index === 1) {
        // 飞线效果-飞线间隔，宽度2
        fragmentShaderSource = `         
                  varying vec2 v_st;    
                  varying float v_width;    
                  varying float v_polylineAngle;
                  varying vec4 v_positionEC;
                  varying vec3 v_normalEC;
                  void main()
                  {
                      vec2 st = v_st;
                      float xx = fract(st.s*2.0 - czm_frameNumber/60.0);
                      float r = xx;
                      float g = 200.0;
                      float b = 200.0;
                      float a = xx;
                      gl_FragColor = vec4(r,g,b,a);
                  }
          `;
      } else if (index === 2) {
        fragmentShaderSource = `
  varying vec2 v_st;
  varying float v_width;
  varying float v_polylineAngle;
  varying vec4 v_positionEC;
  varying vec3 v_normalEC;
  void main()
  {
      vec2 st = v_st;
      float xx = fract(st.s*2.0 - czm_frameNumber/60.0);
      float r = xx;
      float g = sin(czm_frameNumber/30.0);
      float b = cos(czm_frameNumber/30.0);
      float a = xx;
      gl_FragColor = vec4(r,g,b,a);
  }
          `;
      } else if (index === 3) {
        fragmentShaderSource = `
  varying vec2 v_st;
  varying float v_width;
  varying float v_polylineAngle;
  varying vec4 v_positionEC;
  varying vec3 v_normalEC;
  void main()
  {
      vec2 st = v_st;
      float xx = sin(st.s*6.0 -czm_frameNumber/5.0) - cos(st.t*6.0);
      float r = 0.0;
      float g = xx;
      float b = xx;
      float a = xx;
      gl_FragColor = vec4(r,g,b,a);
  }
          `;
      } else if (index === 4) {
        fragmentShaderSource = `
  varying vec2 v_st;
  varying float v_width;
  varying float v_polylineAngle;
  varying vec4 v_positionEC;
  varying vec3 v_normalEC;
  void main()
  {
      vec2 st = v_st;
      float xx = fract(st.s*10.0 + st.t  - czm_frameNumber/60.0);
      if (st.t<0.5) {
          xx = fract(st.s*10.0 - st.t - czm_frameNumber/60.0);
      }
      float r = 0.0;
      float g = xx;
      float b = xx;
      float a = xx;
      if (st.t>0.8||st.t<0.2) {
          g = 1.0;
          b = 1.0;
          a = 0.4;
      }
      gl_FragColor = vec4(r,g,b,a);
  }
          `;
      }
      // 自定义材质
      const aper = new Cesium.PolylineMaterialAppearance({
        material: material,
        translucent: true,
        vertexShaderSource: `
                  #define CLIP_POLYLINE 
                  void clipLineSegmentToNearPlane(
                      vec3 p0,
                      vec3 p1,
                      out vec4 positionWC,
                      out bool clipped,
                      out bool culledByNearPlane,
                      out vec4 clippedPositionEC)
                  {
                      culledByNearPlane = false;
                      clipped = false;
                      vec3 p0ToP1 = p1 - p0;
                      float magnitude = length(p0ToP1);
                      vec3 direction = normalize(p0ToP1);
                      float endPoint0Distance =  czm_currentFrustum.x + p0.z;
                      float denominator = -direction.z;
                      if (endPoint0Distance > 0.0 && abs(denominator) < czm_epsilon7)
                      {
                          culledByNearPlane = true;
                      }
                      else if (endPoint0Distance > 0.0)
                      {
                          float t = endPoint0Distance / denominator;
                          if (t < 0.0 || t > magnitude)
                          {
                              culledByNearPlane = true;
                          }
                          else
                          {
                              p0 = p0 + t * direction;
                              p0.z = min(p0.z, -czm_currentFrustum.x);
                              clipped = true;
                          }
                      }
                      clippedPositionEC = vec4(p0, 1.0);
                      positionWC = czm_eyeToWindowCoordinates(clippedPositionEC);
                  }
                  vec4 getPolylineWindowCoordinatesEC(vec4 positionEC, vec4 prevEC, vec4 nextEC, float expandDirection, float width, bool usePrevious, out float angle)
                  {
                      #ifdef POLYLINE_DASH
                      vec4 positionWindow = czm_eyeToWindowCoordinates(positionEC);
                      vec4 previousWindow = czm_eyeToWindowCoordinates(prevEC);
                      vec4 nextWindow = czm_eyeToWindowCoordinates(nextEC);
                      vec2 lineDir;
                      if (usePrevious) {
                          lineDir = normalize(positionWindow.xy - previousWindow.xy);
                      }
                      else {
                          lineDir = normalize(nextWindow.xy - positionWindow.xy);
                      }
                      angle = atan(lineDir.x, lineDir.y) - 1.570796327;
                      angle = floor(angle / czm_piOverFour + 0.5) * czm_piOverFour;
                      #endif
                      vec4 clippedPrevWC, clippedPrevEC;
                      bool prevSegmentClipped, prevSegmentCulled;
                      clipLineSegmentToNearPlane(prevEC.xyz, positionEC.xyz, clippedPrevWC, prevSegmentClipped, prevSegmentCulled, clippedPrevEC);
                      vec4 clippedNextWC, clippedNextEC;
                      bool nextSegmentClipped, nextSegmentCulled;
                      clipLineSegmentToNearPlane(nextEC.xyz, positionEC.xyz, clippedNextWC, nextSegmentClipped, nextSegmentCulled, clippedNextEC);
                      bool segmentClipped, segmentCulled;
                      vec4 clippedPositionWC, clippedPositionEC;
                      clipLineSegmentToNearPlane(positionEC.xyz, usePrevious ? prevEC.xyz : nextEC.xyz, clippedPositionWC, segmentClipped, segmentCulled, clippedPositionEC);
                      if (segmentCulled)
                      {
                          return vec4(0.0, 0.0, 0.0, 1.0);
                      }
                      vec2 directionToPrevWC = normalize(clippedPrevWC.xy - clippedPositionWC.xy);
                      vec2 directionToNextWC = normalize(clippedNextWC.xy - clippedPositionWC.xy);
                      if (prevSegmentCulled)
                      {
                          directionToPrevWC = -directionToNextWC;
                      }
                      else if (nextSegmentCulled)
                      {
                          directionToNextWC = -directionToPrevWC;
                      }
                      vec2 thisSegmentForwardWC, otherSegmentForwardWC;
                      if (usePrevious)
                      {
                          thisSegmentForwardWC = -directionToPrevWC;
                          otherSegmentForwardWC = directionToNextWC;
                      }
                      else
                      {
                          thisSegmentForwardWC = directionToNextWC;
                          otherSegmentForwardWC =  -directionToPrevWC;
                      }
                      vec2 thisSegmentLeftWC = vec2(-thisSegmentForwardWC.y, thisSegmentForwardWC.x);
                      vec2 leftWC = thisSegmentLeftWC;
                      float expandWidth = width * 0.5;
                      if (!czm_equalsEpsilon(prevEC.xyz - positionEC.xyz, vec3(0.0), czm_epsilon1) && !czm_equalsEpsilon(nextEC.xyz - positionEC.xyz, vec3(0.0), czm_epsilon1))
                      {
                          vec2 otherSegmentLeftWC = vec2(-otherSegmentForwardWC.y, otherSegmentForwardWC.x);
                          vec2 leftSumWC = thisSegmentLeftWC + otherSegmentLeftWC;
                          float leftSumLength = length(leftSumWC);
                          leftWC = leftSumLength < czm_epsilon6 ? thisSegmentLeftWC : (leftSumWC / leftSumLength);
                          vec2 u = -thisSegmentForwardWC;
                          vec2 v = leftWC;
                          float sinAngle = abs(u.x * v.y - u.y * v.x);
                          expandWidth = clamp(expandWidth / sinAngle, 0.0, width * 2.0);
                      }
                      vec2 offset = leftWC * expandDirection * expandWidth * czm_pixelRatio;
                      return vec4(clippedPositionWC.xy + offset, -clippedPositionWC.z, 1.0) * (czm_projection * clippedPositionEC).w;
                  }
                  vec4 getPolylineWindowCoordinates(vec4 position, vec4 previous, vec4 next, float expandDirection, float width, bool usePrevious, out float angle)
                  {
                      vec4 positionEC = czm_modelViewRelativeToEye * position;
                      vec4 prevEC = czm_modelViewRelativeToEye * previous;
                      vec4 nextEC = czm_modelViewRelativeToEye * next;
                      return getPolylineWindowCoordinatesEC(positionEC, prevEC, nextEC, expandDirection, width, usePrevious, angle);
                  }
                  attribute vec3 position3DHigh;
                  attribute vec3 position3DLow;
                  attribute vec3 prevPosition3DHigh;
                  attribute vec3 prevPosition3DLow;
                  attribute vec3 nextPosition3DHigh;
                  attribute vec3 nextPosition3DLow;
                  attribute vec2 expandAndWidth;
                  attribute vec2 st;
                  attribute float batchId;
                  varying float v_width;
                  varying vec2 v_st;
                  varying float v_polylineAngle;
                  
                  varying vec4 v_positionEC;
                  varying vec3 v_normalEC;
                  void main()
                  {
                  float expandDir = expandAndWidth.x;
                  float width = abs(expandAndWidth.y) + 0.5;
                  bool usePrev = expandAndWidth.y < 0.0;
                  vec4 p = czm_computePosition();
                  vec4 prev = czm_computePrevPosition();
                  vec4 next = czm_computeNextPosition();
                  
                  float angle;
                  vec4 positionWC = getPolylineWindowCoordinates(p, prev, next, expandDir, width, usePrev, angle);
                  gl_Position = czm_viewportOrthographic * positionWC;
                  
                  v_width = width;
                  v_st.s = st.s;
                  v_st.t = st.t;
                  // v_st.t = czm_writeNonPerspective(st.t, gl_Position.w);
                  v_polylineAngle = angle;
                  
                  vec4 eyePosition = czm_modelViewRelativeToEye * p;
                  v_positionEC =  czm_inverseModelView * eyePosition;      // position in eye coordinates
                  //v_normalEC = czm_normal * normal;                         // normal in eye coordinates
                  }
              `,
        fragmentShaderSource: fragmentShaderSource,
      });
      return aper;
    },

    // 添加水面
    addWaterPanel() {
      let d = [];
      for (let i = 0; i < systemConfig.water.length; i += 2) {
        let x = systemConfig.water[i];
        let y = systemConfig.water[i + 1];
        d.push(x);
        d.push(y);
        d.push(1);
      }

      let geometry = new Cesium.PolygonGeometry({
        polygonHierarchy: new Cesium.PolygonHierarchy(
          Cesium.Cartesian3.fromRadiansArrayHeights(d)
        ),
        height: -2,
      });

      let waterFace = this.waterObj.create(geometry, {
        // normalMap: "img/textures/waterNormals.jpg", // 水正常扰动的法线图
        frequency: 8000.0, // 控制波数的数字。
        animationSpeed: 0.02, // 控制水的动画速度的数字。
        amplitude: 5.0, // 控制水波振幅的数字。
        specularIntensity: 0.8, // 控制镜面反射强度的数字。
        baseWaterColor: "#006ab4", // rgba颜色对象基础颜色的水。#00ffff,#00baff,#006ab4
        blendColor: "#006ab4", // 从水中混合到非水域时使用的rgba颜色对象。
        // height: 100, //水面高度
        clampToGround: true, //是否贴地
        opacity: 0.7, //透明度
      });
      globalVariable.viewer.scene.primitives.add(waterFace);
    },

    // 添加树木
    addTree() {
      let keys = Object.keys(systemConfig.tree);
      keys.map(function (key, index) {
        let treeObj = systemConfig.tree[key];
        for (let i = 0; i < treeObj.positions.length; i += 2) {
          const x = treeObj.positions[i];
          const y = treeObj.positions[i + 1];
          let position = Cesium.Cartesian3.fromRadians(x, y, 0);
          globalVariable.viewer.entities.add({
            // 设置方向
            //   orientation: orientation,
            position: position,
            model: {
              // 引入模型
              uri:
                systemConfig.dataUrl +
                systemConfig.gltfConfig +
                "/" +
                treeObj.name +
                ".gltf",
              // 模型的近似最小像素大小，而不考虑缩放。这可以用来确保即使观看者缩小也可以看到模型。如果为0.0，则不强制使用最小大小
              minimumPixelSize: 0,
              // // 模型的颜色（与模型的渲染颜色混合的属性）
              // color: Cesium.Color.WHITE.withAlpha(1),
              // 模型的最大比例大小
              maximumScale: 2000,
              // // 设置模型轮廓（边框）颜色
              // silhouetteColor: Cesium.Color.BLACK,
              // // 设置模型轮廓（边框）大小
              // silhouetteSize: 2,
              // // 是否执行模型动画
              // runAnimations: true,
              // 应用于图像的统一比例。比例大于会1.0放大标签，而比例小于会1.0缩小标签。
              scale: 1.0,
              // 是否显示
              show: true,
            },
          });
        }
      });
    },

    // 加载3DTiles数据
    add3DTilesData(url, options) {
      if (!options) {
        options = {
          show: true,
          light: 1,
          matrix: null,
        };
      } else {
        options.show = typeof options.show == "boolean" ? options.show : true;
        options.light = isNaN(options.light) ? 1 : options.light;
      }

      let that = this;
      // let pointLight = this.pointLight();
      let tileset = new Cesium.Cesium3DTileset({
        url: url,
        // skipLevelOfDetail: true, //开启跳级加载
        // preferLeaves: true,
        // shadows: Cesium.ShadowMode.DISABLED,
        // maximumScreenSpaceError: 256,
        // maximumNumberOfLoadedTiles: 500,
        // maximumMemoryUsage: 128, //tileset可以使用的最大内存
        show: options.show,
        // immediatelyLoadDesiredLevelOfDetail: true,
        // progressiveResolutionHeightFraction: 0.5, // 数值偏于0能够让初始加载变得模糊
        // dynamicScreenSpaceErrorDensity: 1, // 数值加大，能让周边加载变快
        // dynamicScreenSpaceErrorFactor: 1, // 不知道起了什么作用没，反正放着吧先
        // dynamicScreenSpaceError: true, // 根据测试，有了这个后，会在真正的全屏加载完之后才清晰化房屋
        // customShader: pointLight,
        // imageBasedLighting:,
        // lightColor: new Cesium.Cartesian3(
        //   options.light,
        //   options.light,
        //   options.light
        // ),
      });

      globalVariable.viewer.scene.primitives.add(tileset);

      tileset.readyPromise.then(function () {
        if (options.matrix)
          tileset.root.transform = that.createMatrix4(options.matrix);
        // globalVariable.viewer.zoomTo(tileset);
      });
      // tileset.tileLoad.addEventListener(function (tile) {
      //   let content = tile.content;
      //   let featuresLength = content.featuresLength;
      //   console.log("要素数量为：");
      //   console.log(featuresLength);
      //   console.log("第一个要素为：");
      //   let feature = content.getFeature(0);
      //   console.log(feature);
      // });
      return tileset;
    },

    // 创建偏移矩阵
    createMatrix4(matrixParam, defaultModelMatrix) {
      let tileModelTool = matrixParam;
      var mx = Cesium.Matrix3.fromRotationX(
        Cesium.Math.toRadians(tileModelTool.rx)
      );
      var my = Cesium.Matrix3.fromRotationY(
        Cesium.Math.toRadians(tileModelTool.ry)
      );
      var mz = Cesium.Matrix3.fromRotationZ(
        Cesium.Math.toRadians(tileModelTool.rz)
      );
      var rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
      var rotationY = Cesium.Matrix4.fromRotationTranslation(my);
      var rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);
      var m;
      if (defaultModelMatrix) {
        m = defaultModelMatrix;
      } else {
        //平移 修改经纬度
        var position = Cesium.Cartesian3.fromDegrees(
          tileModelTool.longitude,
          tileModelTool.latitude,
          tileModelTool.height
        );
        m = Cesium.Transforms.eastNorthUpToFixedFrame(position);
      }

      //旋转、平移矩阵相乘
      Cesium.Matrix4.multiply(m, rotationX, m);
      Cesium.Matrix4.multiply(m, rotationY, m);
      Cesium.Matrix4.multiply(m, rotationZ, m);
      //缩放 修改缩放比例
      var scale = Cesium.Matrix4.fromUniformScale(tileModelTool.scale);
      Cesium.Matrix4.multiply(m, scale, m);
      return m;
    },

    // 加载大批量gltf文件
    loadBigDataGltf() {
      let that = this;
      globalVariable.treeArr = [];
      return new Promise((resolve, reject) => {
        $.getJSON("./static/data/GLTF/tree_path.json", function (array) {
          //array.length

          let instances = [];
          for (let i = 0; i < array.length; i += 10) {
            const item = array[i];
            let lonlat = that.webMercator2lonlat(item.x, item.y);
            globalVariable.treeArr.push(lonlat);
            let modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(
              new Cesium.Cartesian3.fromDegrees(
                lonlat[0] + 116.2026998939312,
                lonlat[1] + 1.1932712598797461,
                10
              ),
              new Cesium.HeadingPitchRoll(0, 0, 0)
            );
            Cesium.Matrix4.multiplyByUniformScale(modelMatrix, 2, modelMatrix); // 缩放
            instances.push({
              modelMatrix: modelMatrix,
            });
          }
          // // for (let i = 0; i < newPositions.length; i++) {
          // for (let i = 0; i < 5000; i++) {
          //   let cartesian = newPositions[i];
          //   //批量加载
          //   let modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(
          //     cartesian,
          //     new Cesium.HeadingPitchRoll(0, 0, 0)
          //   ); // 旋转
          // }
          let primitive = new Cesium.ModelInstanceCollection({
            url: "./static/data/GLTF/SEWQ01.gltf",
            instances: instances,
          });
          globalVariable.viewer.scene.primitives.add(primitive);
          // globalVariable.viewer.camera.setView({
          //   // 4.730190106068796,26.731048740120254
          //   destination: newPositions[0], // 设置位置
          //   orientation: {
          //     heading: Cesium.Math.toRadians(0), // 方向
          //     pitch: Cesium.Math.toRadians(-90.0), // 倾斜角度
          //     roll: 0,
          //   },
          // });
          resolve(primitive);
        });
      });
    },

    // 点光源
    pointLight() {
      // 自定义光源
      return new Cesium.CustomShader({
        lightingModel: Cesium.LightingModel.UNLIT,
        uniforms: {
          u_cameraDirectionWC: {
            type: Cesium.UniformType.VEC3,
            value: globalVariable.viewer.scene.camera.positionWC,
          },
          u_lightColor1: {
            type: Cesium.UniformType.VEC4,
            value: new Cesium.Cartesian4(0.2, 0.2, 0.2, 0.05),
          },
          u_lightPos1: {
            type: Cesium.UniformType.VEC3,
            // 大门头顶
            value: Cesium.Cartesian3.fromRadians(
              2.113986007449123,
              0.5437488254764549,
              59
            ),
            // 一楼门厅
            // value: Cesium.Cartesian3.fromRadians(
            //         2.113987467160011,
            //         0.5437379383404595,
            //         2,
            // ),
            // 门口室外
            // value: Cesium.Cartesian3.fromDegrees(
            // 121.122485613095,
            // 31.1542436101541,
            // 10.649243861995
            // ),
          },
          // u_lightColor2: {
          //   type: Cesium.UniformType.VEC4,
          //   value: new Cesium.Cartesian4(0.2, 0.8, 0.2, 0.2),
          // },
          // u_lightPos2: {
          //   type: Cesium.UniformType.VEC3,
          //   value: Cesium.Cartesian3.fromRadians(
          //           3.1001573234522195,
          //           0.5437380338095784,
          //           2.1
          //   ),
          // },
          // u_lightColor3: {
          //   type: Cesium.UniformType.VEC4,
          //   value: lightPoint3.color,
          // },
          // u_lightPos3: {
          //   type: Cesium.UniformType.VEC3,
          //   value: lightPoint3.postion,
          // },
        },
        fragmentShaderText: `
    vec4 makeLight(vec4 lightColorHdr,vec3 lightPos,
      vec3 positionWC,vec3 positionEC,vec3 normalEC,czm_pbrParameters pbrParameters)
    {
      vec3 color = vec3(0.0);
      float mx1 = 1.0;
      vec3 light1Dir = positionWC - lightPos;
      float distance1 = length(light1Dir);
      if(distance1 < 60.0){
        vec4 l1 = czm_view * vec4(lightPos, 1.0);
        vec3 lightDirectionEC = l1.xyz - positionEC;
        mx1 = 1.0 - distance1 / 60.0;
        color = czm_pbrLighting(
          positionEC,
          normalEC,
          lightDirectionEC,
          lightColorHdr.xyz,
          pbrParameters
        ).xyz;
      }
      mx1 = max(color.r,max(color.g,color.b)) * pow(mx1,1.0) * 10.0;
      return vec4(color,mx1);
    }
    void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material)
    {
      // material.diffuse = vec3(1.0);
      vec3 positionWC = fsInput.attributes.positionWC;
      vec3 normalEC = fsInput.attributes.normalEC;
      vec3 positionEC = fsInput.attributes.positionEC;
      vec3 lightColorHdr = czm_lightColorHdr;
      vec3 lightDirectionEC = czm_lightDirectionEC;
      lightDirectionEC = (czm_view * vec4(u_cameraDirectionWC,1.0)).xyz - positionEC;

      czm_pbrParameters pbrParameters;
      pbrParameters.diffuseColor = material.diffuse;
      pbrParameters.f0 = vec3(0.5);
      pbrParameters.roughness = 1.0;

      vec3 ligth1Color0 = czm_pbrLighting(
        positionEC,
        normalEC,
        lightDirectionEC,
        lightColorHdr,
        pbrParameters
      );

      vec4 ligth1ColorR = makeLight(u_lightColor1,u_lightPos1,positionWC,positionEC,normalEC,pbrParameters);
      // vec4 ligth1ColorG = makeLight(u_lightColor2,u_lightPos2,positionWC,positionEC,normalEC,pbrParameters);

      vec3 finalColor = mix(material.diffuse.rgb, ligth1ColorR.rgb, ligth1ColorR.a);
      // finalColor = mix(finalColor, ligth1ColorG.rgb, ligth1ColorG.a);

      material.diffuse = finalColor;
      // material.ambient = finalColor;
    }
    `,
      });
    },

    wenzhou2000ToWGS84(coordinate) {
      return proj4("EPSG:0986", "EPSG:4326", coordinate);
    },

    // 经纬度转墨卡托
    lonlattoWebMercator(lon, lat) {
      var xy = [];
      var x = (lon * 20037508.34) / 180;
      var y =
        Math.log(Math.tan(((90 + lat) * Math.PI) / 360)) / (Math.PI / 180);
      y = (y * 20037508.34) / 180;
      xy[0] = x;
      xy[1] = y;
      return xy;
    },

    // 墨卡托转经纬度
    webMercator2lonlat(x, y) {
      var lonlat = [];
      var lon = (x / 20037508.34) * 180;
      var lat = (y / 20037508.34) * 180;
      lat =
        (180 / Math.PI) *
        (2 * Math.atan(Math.exp((lat * Math.PI) / 180)) - Math.PI / 2);
      lonlat[0] = lon;
      lonlat[1] = lat;
      return lonlat;
    },

    addGltf(url, x, y, z) {
      let origin = Cesium.Cartesian3.fromDegrees(x, y, z);
      // 创建一个本地的东北向上坐标系，其原点为经度-120度，纬度44.0度。
      // 可以随时更改模型的modelMatrix属性以移动或旋转模型。
      let modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);
      let model = globalVariable.viewer.scene.primitives.add(
        Cesium.Model.fromGltf({
          url: url,
          modelMatrix: modelMatrix,
          scale: 1,
        })
      );
    },
  },
};
</script>

<style lang="less" scoped>
#cesiumContainer {
  width: 100%;
  height: 100%;
  .get_now_camera_view {
    position: absolute;
    z-index: 1;
  }
}
</style>