<template>
  <div
    class="ZTGlobal"
    style="width: 100%; padding: 1rem 1.1rem 0rem; color: white"
    v-loading.fullscreen.lock="loading"
    element-loading-text="正在分析中...."
    element-loading-spinner="el-icon-loading"
    element-loading-background="rgba(0, 0, 0, 0.8)"
  >
    <el-row :gutter="10">
      <el-col :span="24">
        <div class="titleHeader">
          <h3>参数设置</h3>
        </div>
      </el-col>
    </el-row>
    <el-row :gutter="10">
      <el-col :span="24">
        <el-row :gutter="10" style="display: flex; align-items: center">
          <el-col :span="24">
            日 期：
            <el-date-picker
              size="mini"
              v-model="form.selDate"
              type="date"
              placeholder="选择日期"
            >
            </el-date-picker>
          </el-col>
        </el-row>
        <el-row :gutter="10" style="display: flex; align-items: center">
          <el-col :span="6"> 日照时间范围: </el-col>
          <el-col :span="18">
            <el-slider
              size="mini"
              v-model="datavalue"
              range
              :marks="marks"
              :max="24"
              @change="datavalueChange"
            >
            </el-slider>
          </el-col>
        </el-row>
        <el-row :gutter="10" style="display: flex; align-items: center">
          <el-col :span="6"> 日照播放速度: </el-col>
          <el-col :span="18">
            <el-input-number
              size="mini"
              v-model="Intervalshijian"
              :min="1"
              :max="100"
            ></el-input-number>
          </el-col>
        </el-row>
        <el-row :gutter="10">
          <el-col :span="24">
            <div class="SaveCenter" style="padding: 0">
              <el-button size="mini" type="primary" @click="statrSunlight"
                >执行日照效果</el-button
              >
              <el-button size="mini" type="primary" @click="dqSunlight"
                >当前日照</el-button
              >
            </div>
          </el-col>
        </el-row>
        <el-divider></el-divider>
        <!-- <el-row :gutter="10">
          <el-col :span="12">
            时间间隔:
            <el-input-number
              style="width: 50%"
              size="mini"
              v-model="form.timeInterval"
            ></el-input-number>
          </el-col>
          <el-col :span="12">
            间距(米):
            <el-input-number
              style="width: 50%"
              size="mini"
              v-model="form.spacing"
            ></el-input-number>
          </el-col>
        </el-row> -->
        <!-- <el-row :gutter="10">
          <el-col :span="12" style="text-align: center">
            X坐标(度):
            <el-input-number
              size="mini"
              step="0.000001"
              v-model="form.x"
              @change="XYChange"
            ></el-input-number>
          </el-col>
          <el-col :span="12" style="text-align: center">
            Y坐标(度):
            <el-input-number
              size="mini"
              step="0.000001"
              v-model="form.y"
              @change="XYChange"
            ></el-input-number>
          </el-col>
        </el-row> -->

        <!-- <el-row :gutter="10">
          <el-col :span="12">
            底部高程(米):
            <el-input-number
              style="width: 50%"
              size="mini"
              v-model="form.bottomHeight"
            ></el-input-number>
          </el-col>
          <el-col :span="12">
            拉伸高度(米):
            <el-input-number
              style="width: 50%"
              size="mini"
              v-model="form.extrudeHeight"
            ></el-input-number>
          </el-col>
        </el-row> -->
        <el-row :gutter="5">
          <el-col :span="13">
            <!-- 阴影分析时日照时间案范围重合时为时刻阴影，不重合时计算为时间范围内阴影率 -->
            分析高度：
            <el-tooltip
              class="item"
              effect="dark"
              content="当分析高度为0时，自动读取绘制范围范围时第一个点的高度值。后续不为0时按设置高度分析。"
              placement="top"
            >
              <el-input-number
                size="mini"
                v-model="gd"
                :min="0"
                :max="100"
              ></el-input-number>
            </el-tooltip>
          </el-col>
          <el-col :span="11">
            <input @change="handleUpload" type="file" style="display:none" id="fileInput" accept=".geojson"></input> 
            <el-button size="mini" type="primary" @click="inputGeometry"
              >导入范围</el-button
            >
            <el-button size="mini" type="primary" @click="outGeometry"
              >导出范围</el-button
            >
          </el-col>
        </el-row>
      </el-col>
    </el-row>
    <!-- <el-row :gutter="10" v-if="multiViewportMode > 1">
      <el-col :span="24">
        选择分析视口：<el-radio-group
          v-model="radio"
          v-for="item in multiViewportMode"
          :key="item"
        >
          <el-radio :label="item - 1">窗口{{ item }}</el-radio>
        </el-radio-group>
      </el-col>
    </el-row> -->
    <div class="SaveCenter">
      <el-row :gutter="10">
        <el-col :span="24">
          <el-button size="mini" type="primary" @click="onSubmit"
            >自定义日照分析</el-button
          >
          <el-button size="mini" type="primary" @click="onDHSubmit"
            >大寒日</el-button
          >
          <el-button size="mini" type="primary" @click="onDZSubmit"
            >冬至日</el-button
          >
        </el-col>
      </el-row>
      <el-row :gutter="10">
        <el-col :span="24">
          <el-tooltip
            effect="dark"
            content="日照时长结果生成后,调整地图到合适位置，然后导出"
            placement="bottom"
          >
            <el-button
              size="mini"
              type="primary"
              :disabled="sdh.length == 0 ? true : false"
              @click="ExportResult"
              >导出结果</el-button
            >
          </el-tooltip>

          <el-button size="mini" @click="resetForm">清除</el-button>
        </el-col>
      </el-row>
    </div>
    <el-row :gutter="10">
      <el-col :span="24">
        <el-descriptions border size="mini" :column="2">
          <el-descriptions-item
            v-for="item in sdh"
            :key="item"
            :label="item.scS + ' 小时'"
            ><div
              style="width: 4.5rem; height: 100%"
              :style="{ 'background-color': item.fill }"
            >
              &nbsp;
            </div>
          </el-descriptions-item>
        </el-descriptions>
      </el-col>
    </el-row>
    <!-- <el-row :gutter="10">
      <el-col :span="24">
        <el-table
          size="mini"
          :data="tableData"
          style="width: 100%"
          :highlight-current-row="true"
          @row-click="rowClick"
        >
          <el-table-column prop="heightText" label="高程"> </el-table-column>
          <el-table-column prop="sunDate" label="日照时间"> </el-table-column>
          <el-table-column
            prop="shadowRadioText"
            label="日照率"
          ></el-table-column> 
        </el-table>
      </el-col>
    </el-row> -->
  </div>
</template>

<script>
var handlerPolygon = null,
  layers = null,
  shadowQuery = null,
  markedPoints = [];
var sdfff = null;
var czsj = { points1: null, dd1: null };
import {
  intersect,
  flatten,
  envelope,
  point,
  buffer,
  bboxPolygon,
  bbox,
  square,
  destination,
  polygon,
  featureCollection,
  interpolate,
  isobands,
  area,
  isolines,
  pointGrid,
  invariant
} from "@turf/turf";
// # 引入kriging-contour
import {
  getVectorContour,
  drawCanvasContour,
} from "kriging-contour/dist/kriging-contour.js";
// import { getSunrise, getSunset } from "sunrise-sunset-js";
import {
  cartesian3ToWGS84,
  mapQuery,
  mercator2lonLat,
  undergroundMode,
} from "@/utils/MapHelper/MapHelper.js";
import { v4 as uuidv4 } from "uuid";
import moment from "moment";
export default {
  data() {
    return {
      tooltip: createTooltip(document.body),
      form: {
        timeInterval: 60,
        spacing: 8,
        selDate: new Date(),
        startTime: 10,
        endTime: 14,
        bottomHeight: 0,
        extrudeHeight: 100,
        x: 0,
        y: 0,
      },
      sdh: [
        { scS: "0-1", fill: "#313695" },
        { scS: "1-2", fill: "#1E90A8" },
        { scS: "2-3", fill: "#00B457" },
        { scS: "3-4", fill: "#B7FF01" },
        { scS: "4-5", fill: "#F2A705" },
        { scS: ">=5", fill: "#FF0000" },
      ],
      loading: false,
      datavalue: [10, 14],
      positions: [],
      points: [],
      // layers: null,
      // shadowQuery: null,
      marks: {
        8: "8点",
        12: {
          style: {
            color: "#1989FA",
          },
          label: this.$createElement("strong", "12点"),
        },
        20: "20点",
      },
      tableData: [],
      multiViewportMode: 0,
      radio: 0,
      eids: [],
      //记录进入页面时的场景参数
      RecordInitializationScene: {},
      nIntervId: null,
      Intervalshijian: 10,
      gd: 0,
      geopolygon:null,
      ProjectScope:{positions:[]}
    };
  },
  props: {
    info: {
      type: Object,
      default: () => {
        return {};
      },
    },
    layerid: {
      type: String,
      default: "",
    },
    lydata: {
      type: Object,
      default: () => {
        return {};
      },
    },
    lyoption: {
      type: Object,
      default: () => {
        return {};
      },
    },
  },
  computed: {},
  mounted() {
    this.multiViewportMode = scene.multiViewportMode + 1;
    document.oncontextmenu = function (e) {
      e.preventDefault();
    };
    this.init();
  },
  methods: {
    init() {
      let scene = viewer.scene;
      layers = scene.layers.layerQueue;

      this.RecordInitializationScene.shadows = viewer.shadows;
      this.RecordInitializationScene.layersshadowType = [];
      for (let i = 0; i < layers.length; i++) {
        this.RecordInitializationScene.layersshadowType.push({
          name: layers[i].name,
          shadowType: layers[i].shadowType,
        });
      }

      if (viewer.shadows == false) {
        viewer.shadows = true; //开启场景阴影
      }

      //图层模型设置阴影
      for (let i = 0; i < layers.length; i++) {
        // if (layers[i].shadowType !== 2) {
        layers[i].shadowType = 2;
        // layers[i].refresh();
        // }
      }

      this.dqSunlight();
    },

    /**
     * 导出范围
     */
    outGeometry(){
      if(this.geopolygon){
        this.exportRaw("绘制范围.geojson",JSON.stringify(this.geopolygon));
      }else{
        this.$message.warning("请先执行分析后再保存绘制的区域！！！");
      }
    },
    /**
    * 点击导入范围
    */
    inputGeometry() {
      var element = document.getElementById('fileInput');
      if (element)
        element.click();
    },
    handleUpload(e) {
      const file = e.target.files[0];
      if (!file) {
        return;
      }
      var that = this;
      const reader = new FileReader();
      reader.onload = function(e) {
        var geojson =JSON.parse(e.target.result);
        e.target.files=[];
        document.getElementById('fileInput').value = '';
        
      if (!geojson || typeof geojson !== 'object' || geojson.geometry.type!="Polygon") {
        that.$message.warning("导入的范围格式错误！！！");
          return false;
      }
        that.addGeometry(geojson);
      };
      reader.onerror = function(error) {
        e.target.files=[];
        document.getElementById('fileInput').value = '';
        console.error('Error: ', error);
      };

      reader.readAsText(file);
    },

   /**
   * 导入范围添加图形
   */
    addGeometry(geojson) {
      var that = this;
      that.clear();
      debugger
      var coordinates = geojson.geometry.coordinates;
      var positions = [];
      that.ProjectScope.positions = [];
      for (var i = 0; i < coordinates.length; i++) {
        var coor = coordinates[i];
        if (coor && coor.length > 0) {
          for (var j = 0; j < coor.length; j++) {
            var Cartesian3Posit=Cesium.Cartesian3.fromDegrees(
              coor[j][0],
              coor[j][1],
              coor[j][2]
          )
            that.ProjectScope.positions.push(Cartesian3Posit)
            positions.push(coor[j][0])
            positions.push(coor[j][1])
          }
        }
      }
      viewer.entities.removeById('polygon');
      var polygonEntity = new Cesium.Entity({
        id: 'polygon',
        polygon: {
          hierarchy: new Cesium.PolygonHierarchy(
            new Cesium.Cartesian3.fromDegreesArray(positions)
          ),
          // positions: new Cesium.Cartesian3.fromDegreesArray(positions),
          material: Cesium.Color.WHITE.withAlpha(0.3),
          outline: true,
          outlineColor: Cesium.Color.RED,
          outlineWidth: 2.0,
        },
      });

      viewer.entities.add(polygonEntity);
      viewer.flyTo(polygonEntity,{
            offset: {
              heading: Cesium.Math.toRadians(0),
              pitch: Cesium.Math.toRadians(-90),
              range: 220,
            },
          })
    },

    fakeClick(obj) {
      var ev = document.createEvent("MouseEvents");
      ev.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
      obj.dispatchEvent(ev);
    },

    exportRaw(name, data) {
      var urlObject = window.URL || window.webkitURL || window;
      var export_blob = new Blob([data]);
      var save_link = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
      save_link.href = urlObject.createObjectURL(export_blob);
      save_link.download = name;
      this.fakeClick(save_link);
    } ,

    //自定义日照
    onSubmit() {
      this.analysis();
    },
    //大寒日
    onDHSubmit() {
      this.form.selDate = new Date(new Date().getFullYear() + "-01-20");
      this.datavalue = [9, 15];
      this.analysis();
    },
    //冬至日
    onDZSubmit() {
      //       冬至日期(东八区)的计算公式：(y×d+c)-l
      // 　　公式解读：Y=年数后2位，D=0.2422，L=闰年数，21世纪C=21.94，20世纪=22.60。
      // 　　举例说明：2088年冬至日期=[88×0.2422+21.94]-[88/4]=43-22=21，12月21日冬至。
      // 　　例外：1918年和2021年的计算结果减1日。
      let lastTwoDigitsOfYear = moment().format("YY");
      let rns = lastTwoDigitsOfYear / 4;
      let sjs = 21.94;
      let dzr = Math.floor(lastTwoDigitsOfYear * 0.2422 + sjs - rns);
      this.form.selDate = new Date(new Date().getFullYear() + "-12-" + dzr);

      this.datavalue = [9, 15];
      this.analysis();
    },
    //清空from
    resetForm() {
      this.ProjectScope.positions=[];
      this.clear();
      // this.clearmarkedPoints();
    },
    /**
     * 开始分析
     */
    analysis1() {
      let that = this;
      that.tableData = [];
      if (!handlerPolygon) {
        handlerPolygon = new Cesium.DrawHandler(
          viewer,
          Cesium.DrawMode.Point,
          Cesium.ClampMode.Space
        );
      }

      handlerPolygon.activate();
      handlerPolygon.activeEvt.addEventListener(function (isActive) {
        // if (isActive == true) {
        //   viewer.enableCursorStyle = false;
        //   viewer._element.style.cursor = "";
        //   document.body.classList.add("drawCur");
        // } else {
        //   viewer.enableCursorStyle = true;
        //   document.body.classList.remove("drawCur");
        // }
        that.tooltip.setVisible(false);
      });
      handlerPolygon.movingEvt.addEventListener((windowPosition) => {
        that.tooltip.showAt(
          windowPosition,
          "<p>点击鼠标左键开始选择分析区域</p>"
        );
      });
      handlerPolygon.drawEvt.addEventListener((result) => {
        that.resetForm();
        // that.clickSunDate();
        that.loading = true;
        let scene = viewer.scene;

        //创建阴影查询对象
        if (!shadowQuery) {
          shadowQuery = new Cesium.ShadowQueryPoints(scene);
          shadowQuery.setVisibleInViewport(that.radio);
          shadowQuery.queryPointsEvent.addEventListener(function (e) {
            that.tableData = [];
            that.loading = false;
            e.forEach(function (a) {
              var e_cartographic = Cesium.Cartographic.fromCartesian(
                a.position
              );
              var e_shadowRadio = shadowQuery.getShadowRadio(e_cartographic);
              var e_longitude = Cesium.Math.toDegrees(e_cartographic.longitude);
              var e_latitude = Cesium.Math.toDegrees(e_cartographic.latitude);
              var e_height = e_cartographic.height;
              let sunForm = {};
              sunForm.shadowRadioText =
                (Number(e_shadowRadio.toFixed(2)) * 100).toFixed(2) + "%";
              sunForm.longitudeText = Number(e_longitude.toFixed(6));
              sunForm.latitudeText = Number(e_latitude.toFixed(6));
              sunForm.heightText = Number(e_height.toFixed(2));
              sunForm.dateScope =
                that.datavalue[0] + "时--" + that.datavalue[1] + "时";
              if (that.datavalue[0] != that.datavalue[1]) {
                sunForm.sunDate =
                  (
                    (that.datavalue[1] + 1 - that.datavalue[0]) *
                    e_shadowRadio
                  ).toFixed(2) + "小时";
              } else {
                sunForm.sunDate = "";
              }
              that.tableData.push(sunForm);
            });
          });
        }
        that.tooltip.setVisible(false);
        var position = result.object.position;
        var cartographic = Cesium.Cartographic.fromCartesian(position);
        var longitude = Cesium.Math.toDegrees(cartographic.longitude);
        var latitude = Cesium.Math.toDegrees(cartographic.latitude);
        var clickPoint = point([longitude, latitude]); //
        var buffered = buffer(clickPoint, (that.form.spacing / 2 + 1) / 1000, {
          units: "kilometers",
        });

        that.form.x = longitude;
        that.form.y = latitude;
        that.points = buffered.geometry.coordinates[0].flat();
        //设置分析对象的开始结束时间
        var dateValue = that.form.selDate;
        var st = new Date(dateValue);
        st.setHours(Number(that.form.startTime));
        shadowQuery.startTime = Cesium.JulianDate.fromDate(st);

        var et = new Date(dateValue);
        et.setHours(Number(that.form.endTime));
        shadowQuery.endTime = Cesium.JulianDate.fromDate(et);

        //设置当前时间
        that.setCurrentTime();

        shadowQuery.spacing = that.form.spacing;
        shadowQuery.timeInterval = that.form.timeInterval;

        //设置分析区域、底部高程和拉伸高度
        var bh = Number(that.form.bottomHeight);
        var eh = Number(that.form.extrudeHeight);
        shadowQuery.qureyRegion({
          position: that.points,
          bottom: bh,
          extend: eh,
        });
        shadowQuery.build();
      });
    },
    analysis() {
      let that = this;
      that.clear();
      that.tableData = [];

      if (that.form.startTime == that.form.endTime) {
        this.$message.warning("请选择一个日照时间范围区间！！！");
        return;
      }
      if (!handlerPolygon) {
        handlerPolygon = new Cesium.DrawHandler(
          viewer,
          Cesium.DrawMode.Polygon,
          0
        );
      }
      if(that.ProjectScope.positions.length>0){
        that.imptAnalysis(that.ProjectScope);
      }else{
        handlerPolygon.activate();
        handlerPolygon.activeEvt.addEventListener(function (isActive) {
          // if (isActive == true) {
          //   // viewer.enableCursorStyle = false;
          //   // viewer._element.style.cursor = "";
          //   document.body.classList.add("drawCur");
          // } else {
          //   // viewer.enableCursorStyle = true;
          //   document.body.classList.remove("drawCur");
          // }
          that.tooltip.setVisible(false);
        });
        handlerPolygon.movingEvt.addEventListener((windowPosition) => {
          that.tooltip.showAt(
            windowPosition,
            "<p>点击鼠标左键开始绘制分析区域</p>"
          );
        });
        handlerPolygon.drawEvt.addEventListener((result) => {

          // if (sdfff == null) {
          //   sdfff = result;
          // } else {
          //   result = sdfff;
          // }

          that.tooltip.setVisible(false);
          that.resetForm();
          result.object.show = false;
          that.imptAnalysis(result.object);
        });
      }

    },

    imptAnalysis(polygons){
      var that=this;
      var polygonsCopy=polygons;
      that.loading = true;
        let scene = viewer.scene;
        // that.gd = 0;
        //创建阴影查询对象
        if (!shadowQuery) {
          shadowQuery = new Cesium.ShadowQueryPoints(scene);
          shadowQuery.setVisibleInViewport(that.radio);
          shadowQuery.queryPointsEvent.addEventListener(function (e) {
            console.log(new Date().getSeconds());
            that.tableData = [];
            that.loading = false;
            let sdsd = [];

            for (var index = 0; index < e.length; index++) {
              const a = e[index];
              var e_cartographic = Cesium.Cartographic.fromCartesian(
                a.position
              );
              var e_shadowRadio = shadowQuery.getShadowRadio(e_cartographic);
              var e_longitude = Cesium.Math.toDegrees(e_cartographic.longitude);
              var e_latitude = Cesium.Math.toDegrees(e_cartographic.latitude);
              var e_height = e_cartographic.height;

              let sd = point([e_longitude, e_latitude]);
              sd.properties.value = e_shadowRadio;
              sdsd.push(sd);
            }
            console.log(new Date().getSeconds());

            let gsd = that.setIsoline(sdsd, polygonsCopy);
            var sssssd = [];
            // that.sdh = [];
            console.log(new Date().getSeconds());
            for (
              let featuresindex = 0;
              featuresindex < gsd.features.length;
              featuresindex++
            ) {
              var element = gsd.features[featuresindex];
              if (element.geometry.type == "MultiPolygon") {
                // continue;
                var polygons =
                  that.geoJSONMultiPolygonToCesiumPolygons(element);
                sssssd.push(polygons);
                polygons.forEach((polygonItem) => {
                  let id = uuidv4();
                  that.eids.push(id);
                  viewer.entities.add({
                    id: id,
                    polygon: {
                      hierarchy: polygonItem,
                      material: new Cesium.Color.fromCssColorString(
                        element.properties.fill
                      ).withAlpha(1),
                      height: that.gd + 3 + featuresindex * 0.1,
                      outline: false,
                      // outlineColor: Cesium.Color.BLACK,
                      // outlineWidth: 2.0,
                      // classificationType: Cesium.ClassificationType.TERRAIN,
                    },
                  });
                });
              } else {
                // continue;
                for (
                  var index = 0;
                  index < element.geometry.coordinates.length;
                  index++
                ) {
                  var polygon = element.geometry.coordinates[index];
                  let ps = polygon.flat();
                  sssssd.push(ps);
                  let id = uuidv4();
                  that.eids.push(id);
                  viewer.entities.add({
                    id: id,
                    polygon: {
                      hierarchy: Cesium.Cartesian3.fromDegreesArray(ps),
                      material: new Cesium.Color.fromCssColorString(
                        element.properties.fill
                      ).withAlpha(1),
                      height: that.gd + 3 + featuresindex * 0.1,
                      outline: false,
                      // outlineColor: Cesium.Color.BLACK,
                      // outlineWidth: 2.0,
                      // classificationType: Cesium.ClassificationType.TERRAIN,
                    },
                  });
                }
              }
            }
            // var sdfsdfasf = sssssd;
  
            console.log(new Date().getSeconds());
            setTimeout(function () {
              if (shadowQuery) {
                shadowQuery.clear();
                shadowQuery.destroy();
                shadowQuery = null;

                // shadowQuery.qureyRegion({
                //   position: [0, 0],
                //   bottom: 0,
                //   extend: 0,
                // });
              }
            }, 1000);
          });
        }
        let positions = that.positions;
        let points = that.points;
        // var polygons = result.object;
        if (!polygons) {
          return;
        }

        //保存当前范围，为导出准备
        var geoposts=[];
        polygons.positions.forEach((position) => {
          let xy = cartesian3ToWGS84(position);
          geoposts.push([xy.lng, xy.lat,xy.alt]);
        });
        geoposts.push(geoposts[0]);
        that.geopolygon=polygon([geoposts]);

        
        // handlerPolygon.polyline.show = false;
        positions = [].concat(polygons.positions);
        positions = Cesium.arrayRemoveDuplicates(
          positions,
          Cesium.Cartesian3.equalsEpsilon
        );
        //遍历多边形，取出所有点
        for (var i = 0, len = positions.length; i < len; i++) {
          //转化为经纬度，并加入至临时数组
          var cartographic = Cesium.Cartographic.fromCartesian(
            polygons.positions[i]
          );
          var longitude = Cesium.Math.toDegrees(cartographic.longitude);
          var latitude = Cesium.Math.toDegrees(cartographic.latitude);
          if (i == 0) {
            if (that.gd == 0) {
              that.gd = Math.ceil(cartographic.height);
            }
          }
          points.push(longitude);
          points.push(latitude);
        }
        //设置分析对象的开始结束时间
        var dateValue = that.form.selDate;
        var st = new Date(dateValue);
        st.setHours(Number(that.form.startTime));
        shadowQuery.startTime = Cesium.JulianDate.fromDate(st);

        var et = new Date(dateValue);
        let endTime = 0;
        if (that.form.startTime != that.form.endTime) {
          endTime = that.form.endTime;
        } else {
          endTime = that.form.endTime;
        }
        et.setHours(Number(endTime));
        shadowQuery.endTime = Cesium.JulianDate.fromDate(et);

        //设置当前时间
        that.setCurrentTime();

        //设置根据面积计算间隔
        var trufpolygons = [];
        for (let pindex = 0; pindex < polygons.positions.length; pindex++) {
          var pposition = polygons.positions[pindex];
          var e_cartographic = Cesium.Cartographic.fromCartesian(pposition);
          var e_longitude = Cesium.Math.toDegrees(e_cartographic.longitude);
          var e_latitude = Cesium.Math.toDegrees(e_cartographic.latitude);
          trufpolygons.push([e_longitude, e_latitude]);
        }

        if (trufpolygons[0] != trufpolygons[trufpolygons.length - 1]) {
          trufpolygons.push(trufpolygons[0]);
        }
        var polygonPs = polygon([trufpolygons]);
        let areaPs = area(polygonPs);
        if (areaPs <= 20000) {
          that.form.spacing = 10;
        } else if (areaPs <= 60000) {
          that.form.spacing = 10;
        } else if (areaPs <= 100000) {
          that.form.spacing = 10;
        } else {
          that.form.spacing = 10;
        }

        shadowQuery.spacing = that.form.spacing;
        shadowQuery.timeInterval = that.form.timeInterval;

        //设置分析区域、底部高程和拉伸高度
        var bh = Number(that.gd + 1);
        var eh = Number(2);
        if (areaPs < 250000) {
          shadowQuery.qureyRegion({
            position: that.points,
            bottom: bh,
            extend: eh,
          });
          shadowQuery.build();
          // that.resetForm();
        } else {
          that.loading = false;
          this.$message({
            dangerouslyUseHTMLString: true,
            message:
              "框选范围过大，为确保分析精度，建议以小区为单位<br />请选取小于250000平方米的区域！！！",
            type: "warning",
          });
          if (shadowQuery) {
            shadowQuery.clear();
            shadowQuery.destroy();
            shadowQuery = null;
            // shadowQuery.qureyRegion({
            //   position: [0, 0],
            //   bottom: 0,
            //   extend: 0,
            // });
          }
        }
    },
    ExportResult() {
      let that = this;
      let entitys = [];
      that.eids.forEach((id) => {
        let entity = viewer.entities.getById(id);
        if (entity) {
          entitys.push(entity);
        }
      });

      let box = that.squarePolygon(entitys);
      viewer.camera.flyTo({
        destination: Cesium.Rectangle.fromDegrees(
          box[0][0] + 0.0002,
          box[0][1] - 0.0002,
          box[2][0] - 0.0002,
          box[2][1] + 0.0002
        ),
      });

      setTimeout(function () {
        var promise = scene.outputSceneToFile();
        Cesium.when(promise, function (base64data) {
          that.download(base64data);
        });
      }, 4000);
    },
    /**
     * 根据图片生成画布
     */
    convertImageToCanvas(image) {
      var canvas = document.createElement("canvas");
      canvas.width = image.width;
      canvas.height = image.height;
      var ctx = canvas.getContext("2d");
      ctx.drawImage(image, 0, 0);
      this.drawLegends(canvas, ctx);
      return canvas;
    },
    // 绘制图例
    drawLegends(canvas, ctx) {
      var legends = this.sdh;
      var padding = 10; // 图例与边缘的间距
      var lineHeight = 30; // 每行图例的高度
      var labW = 120;
      var x = canvas.width - padding - labW; // 图例的起始X坐标
      var y = canvas.height - legends.length * lineHeight - padding; // 图例的起始Y坐标
      // 绘制颜色块
      ctx.fillStyle = "#ffffff";
      ctx.fillRect(
        x - padding,
        y - padding,
        canvas.width - x + padding,
        canvas.height - y + padding
      );
      legends.forEach(function (legend, index) {
        // 绘制文本
        ctx.fillStyle = "black";
        ctx.fillText(
          legend.scS + "小时",
          x,
          y + index * lineHeight + lineHeight / 2
        );
        // 绘制颜色块
        ctx.fillStyle = legend.fill;
        ctx.fillRect(
          x + (labW / 3) * 2,
          y + index * lineHeight,
          30,
          lineHeight
        );
      });
    },
    /**
     * 下载图片
     */
    download(base64data) {
      let that = this;
      var image = new Image();
      image.src = base64data;
      image.onload = function () {
        var canvas = that.convertImageToCanvas(image);
        var url = canvas.toDataURL("image/jpeg");
        var a = document.createElement("a");
        var event = new MouseEvent("click");
        a.download = new Date().getTime() + ".jpg"; // 指定下载图片的名称
        a.href = url;
        a.dispatchEvent(event); // 触发超链接的点击事件
      };
    },
    clear() {
      viewer.entities.removeById('polygon');
      this.geopolygon=null;
      // viewer.entities.removeAll();
      // this.form.x = 0;
      // this.form.y = 0;
      this.tableData = [];
      if (handlerPolygon) {
        handlerPolygon.clear();
        handlerPolygon.deactivate();
        handlerPolygon = null;
      }
      this.tooltip.setVisible(false);
      if (shadowQuery) {
        shadowQuery.clear();
        shadowQuery.destroy();
        shadowQuery = null;
        // shadowQuery.qureyRegion({
        //   position: [0, 0],
        //   bottom: 0,
        //   extend: 0,
        // });
      }

      this.positions = [];
      this.points = [];
      for (let i = 0; i < this.eids.length; i++) {
        viewer.entities.removeById(this.eids[i]);
      }
      // this.sdh = [];
      this.eids = [];
    },
    //结束时日照阴影
    setCurrentTime() {
      var et = this.form.selDate;
      et.setHours(Number(this.form.endTime));
      viewer.clock.currentTime = Cesium.JulianDate.fromDate(et);
      viewer.clock.multiplier = 1;
      viewer.clock.shouldAnimate = false;
    },
    /**
     * 执行日照动画
     */
    statrSunlight() {
      var dateVal = this.form.selDate;
      var startTime = new Date(dateVal);
      var shour = Number(this.form.startTime);
      var ehour = Number(this.form.endTime);

      if (shour > ehour) {
        return;
      }

      var nTimer = 0.0;
      if (this.nIntervId) {
        clearInterval(this.nIntervId);
      }
      debugger;
      this.nIntervId = setInterval(function () {
        if (shour < ehour) {
          startTime.setHours(shour);
          startTime.setMinutes(nTimer);
          viewer.clock.currentTime = Cesium.JulianDate.fromDate(startTime);
          nTimer += 10.0;
          if (nTimer > 60.0) {
            shour += 1.0;
            nTimer = 0.0;
          }
        } else {
          clearInterval(this.nIntervId);
        }
      }, this.Intervalshijian * 10);
    },
    //当前日照效果
    dqSunlight() {
      viewer.clock.currentTime = Cesium.JulianDate.fromDate(new Date());
      viewer.clock.multiplier = 1;
      viewer.clock.shouldAnimate = true;
    },
    //日照列表行被点击
    rowClick(row, column, event) {
      this.clearmarkedPoints();
      var markedPoint = viewer.entities.add(
        new Cesium.Entity({
          point: new Cesium.PointGraphics({
            color: new Cesium.Color(1, 1, 0, 0.5),
            pixelSize: 15,
          }),
          position: Cesium.Cartesian3.fromDegrees(
            row.longitudeText,
            row.latitudeText,
            row.heightText
          ),
        })
      );
      markedPoints.push(markedPoint);
    },
    //清除点击的黄色圆圈
    clearmarkedPoints() {
      for (let i = 0; i < markedPoints.length; i++) {
        viewer.entities.remove(markedPoints[i]);
      }
      markedPoints = [];
    },
    // x或y变化触发
    XYChange() {
      if (!shadowQuery) {
        return;
      }
      this.loading = true;
      let that = this;

      var clickPoint = point([that.form.x, that.form.y]); //
      var buffered = buffer(clickPoint, (that.form.spacing / 2 + 1) / 1000, {
        units: "kilometers",
      });
      that.points = buffered.geometry.coordinates[0].flat();

      //设置分析区域、底部高程和拉伸高度
      var bh = Number(that.form.bottomHeight);
      var eh = Number(that.form.extrudeHeight);
      shadowQuery.qureyRegion({
        position: that.points,
        bottom: bh,
        extend: eh,
      });
      shadowQuery.build();
    },

    // 时间范围变化触发
    datavalueChange(val) {
      if (val[0] == val[1]) {
        this.form.timeInterval = 1;
      } else {
        this.form.timeInterval = 60;
      }
      this.form.startTime = val[0];
      this.form.endTime = val[1];
    },

    setIsoline(turfPoints, polygons) {
      //转换面
      var trufpolygons = [];
      for (var pindex = 0; pindex < polygons.positions.length; pindex++) {
        var pposition = polygons.positions[pindex];
        var e_cartographic = Cesium.Cartographic.fromCartesian(pposition);
        var e_longitude = Cesium.Math.toDegrees(e_cartographic.longitude);
        var e_latitude = Cesium.Math.toDegrees(e_cartographic.latitude);
        trufpolygons.push([e_longitude, e_latitude]);
      }

      if (trufpolygons[0] != trufpolygons[trufpolygons.length - 1]) {
        trufpolygons.push(trufpolygons[0]);
      }
      var polygonPs = polygon([trufpolygons]);

      var sunriseDate = SunriseSunsetJS.getSunrise(
        18.31723463241332,
        109.5112252162011,
        this.form.selDate
      );
      var sunsetdate = SunriseSunsetJS.getSunset(
        18.31723463241332,
        109.5112252162011,
        this.form.selDate
      );
      //参与计算的日出日落时间
      var jssunriseHours = 0;
      var jssunsetHours = 0;
      //日出时间
      var sunriseHours = sunriseDate.getHours() + sunriseDate.getMinutes() / 60;
      //日落时间
      var sunsetHours = sunsetdate.getHours() + sunsetdate.getMinutes() / 60;

      if (this.datavalue[0] > sunriseHours) jssunriseHours = this.datavalue[0];
      else jssunriseHours = sunriseHours;

      if (this.datavalue[1] > sunsetHours) jssunsetHours = sunsetHours;
      else jssunsetHours = this.datavalue[1];

      //赋值+计算小时数
      for (var index = 0; index < turfPoints.length; index++) {
        var element = turfPoints[index];
        console.log(
          jssunsetHours -
            jssunriseHours +
            "*" +
            element.properties.value +
            "==" +
            (jssunsetHours - jssunriseHours) * element.properties.value
        );

        var time = (jssunsetHours - jssunriseHours) * element.properties.value;
        // if (time > 5) {
        //   element["value"] = 5;
        //   element.properties.value = 5;
        // } else {
        element["value"] = time;
        element.properties.value = time;
        // }
      }

      // 使用turf.envelope计算包含所有点的最小矩形多边形
      var envelopeP = envelope(featureCollection(turfPoints));
      // var minX,max
      // turfPoints.forEach()

      // 从envelope多边形中提取bbox坐标
      let dd1 = envelopeP.bbox;
      // let dd1 = [107, 36, 180, 38];
      // let dd1 = bbox(sdsd);
      let points1 = {
        type: "FeatureCollection",
        features: turfPoints,
      };

      let levelv = [0, 1, 2, 3, 4, 5];
      let colors = [
        { fill: "#313695" },
        { fill: "#1E90A8" },
        { fill: "#00B457" },
        { fill: "#B7FF01" },
        { fill: "#F2A705" },
        { fill: "#FF0000" },
        { fill: "#FF0000" },
      ];
      // if (czsj.points1 == null) {
      //   czsj.points1 = points1;
      //   czsj.dd1 = dd1;
      // } else {
      //   points1 = czsj.points1;
      //   dd1 = czsj.dd1;
      // }

      let kriging_contours = getVectorContour(
        points1,
        "value",
        { model: "spherical", sigma2: 0, alpha: 50 },
        levelv,
        dd1
      );

      function hotcolor(d) {
        let index = levelv.findIndex((item) => item >= d);
        if (index > -1 && index < 6) {
          return colors[index].fill;
        } else {
          return colors[colors.length - 1].fill;
        }
      }
      function sortArea(a, b) {
        return area(b) - area(a);
      }
      //按照面积对图层进行排序，规避turf的一个bug
      kriging_contours.features.sort(sortArea);
      //后面使用要求输入的参数为Feature<Polygon>，而turf.isobands的是 MultiPolygon，需
      var boundaries = flatten(envelopeP); //行政边界

      kriging_contours = flatten(kriging_contours); //等值面边界
      //console.log('kriging_contours:'+JSON.stringify(kriging_contours));
      //根据行政边界裁剪图形,
      //现在放大一些区域边界还是没有充满  后面可以封装成一个插件，在源码里面进行canvas  clip 剪辑只显示的geojson区域，其余的栅格部分不显示
      let features = []; //裁剪后的结果集
      // kriging_contours.features.forEach(function (feature1) {
      //   boundaries.features.forEach(function (feature2) {
      //     let intersection = null;
      //     try {
      //       intersection = intersect(feature1, feature2);
      //     } catch (e) {
      //       try {
      //         //色斑图绘制之后，可能会生成一些非法 Polygon
      //         //解决的方法通常就是做一次 turf.buffer() 操作，这样可以把一些小的碎片 Polygon 清理掉。
      //         feature1 = buffer(feature1, 0);
      //         intersection = intersect(feature1, feature2);
      //       } catch (e) {
      //         intersection = feature1; //实在裁剪不了就不裁剪了,根据业务需求自行决定
      //       }
      //     }
      //     if (intersection != null) {
      //       intersection.properties = feature1.properties;
      //       // intersection.properties.fill = hotcolor(feature1.properties.value);
      //       intersection.id = (Math.random() * 100000).toFixed(0);
      //       features.push(intersection);
      //     }
      //   });
      // });
      var polygonPs = polygon([trufpolygons]);
      kriging_contours.features.forEach(function (feature1) {
        // polygonPs.features.forEach(function (feature2) {
        let inFeature = null;
        try {
          inFeature = intersect(feature1, polygonPs);
        } catch (e) {
          try {
            //色斑图绘制之后，可能会生成一些非法 Polygon
            //解决的方法通常就是做一次 turf.buffer() 操作，这样可以把一些小的碎片 Polygon 清理掉。
            feature1 = buffer(feature1, 0);
            inFeature = intersect(feature1, polygonPs);
          } catch (e) {
            inFeature = feature1; //实在裁剪不了就不裁剪了,根据业务需求自行决定
          }
        }
        if (inFeature != null) {
          inFeature.properties = feature1.properties;
          // intersection.properties.fill = hotcolor(feature1.properties.value);
          inFeature.id = (Math.random() * 100000).toFixed(0);
          features.push(inFeature);
        }
        // });
      });

      let intersection = featureCollection(features);
      intersection.features.forEach((element) => {
        element.properties.fill = hotcolor(element.properties.contour_value);
      });
      // function zdx(a, b) {
      //   return a.properties.contour_value - b.properties.contour_value;
      // }
      // intersection.features.sort(zdx);

      // let features = []; //裁剪后的结果集

      // intersection.features = features;
      return intersection;
    },

    /**
     * @property {Array} features  关键点集合
     */
    setIsoline1111(features) {
      // 准备工作，创建 options
      // const breaks = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1];
      const breaks = [0];
      for (
        var index = 1;
        index < this.datavalue[1] - this.datavalue[0] + 1;
        index++
      ) {
        breaks.push(index * (1 / (this.datavalue[1] - this.datavalue[0])));
      }
      // breaks.push(2);
      let breaksProperties = [];
      for (var index = 0; index < breaks.length; index++) {
        // let time1 = Math.ceil(
        //   (this.datavalue[1] - this.datavalue[0]) * breaks[index]
        // );

        let time1 = (this.datavalue[1] - this.datavalue[0]) * breaks[index];
        switch (time1) {
          case 0:
            breaksProperties.push(this.sdh[0]);
            break;
          case 1:
            breaksProperties.push(this.sdh[1]);
            break;
          case 2:
            breaksProperties.push(this.sdh[2]);
            break;
          case 3:
            breaksProperties.push(this.sdh[3]);
            break;
          case 4:
            breaksProperties.push(this.sdh[4]);
            break;
          default:
            breaksProperties.push(this.sdh[5]);
            break;
        }
      }

      const interpolateOptions = {
        gridType: "points",
        property: "value",
        units: "degrees",
        weight: 50,
      };
      const isobandsOptions = {
        zProperty: "value",
        // commonProperties: {
        //   "fill-opacity": 0.5,
        // },
        breaksProperties: breaksProperties,
      };
      // 准备工作结束

      // 将散点合并成要素集
      const points = featureCollection(features);
      // 使用反向距离加权(IDW)方法进行运算
      const grid = interpolate(
        points,
        this.form.spacing * 0.00001,
        interpolateOptions
      );
      // 根据参与分级的属性和分级的数组计算出等值面
      const isobandsData = isobands(grid, breaks, isobandsOptions);
      const intersection = featureCollection(isobandsData.features);

      return intersection;
    },
    /**
     * 计算边界
     */
    squarePolygon(entitys) {
      const polygons = [
        /* ... 多边形数组 ... */
      ];
      entitys.forEach((entity) => {
        let positions = entity.polygon.hierarchy.getValue().positions;
        let posts = [];
        positions.forEach((position) => {
          let xy = cartesian3ToWGS84(position);
          posts.push([xy.lng, xy.lat]);
        });
        let thispolygon = polygon([posts]);
        polygons.push(thispolygon);
      });

      // 初始化边界框变量
      let minX = Infinity,
        minY = Infinity,
        maxX = -Infinity,
        maxY = -Infinity;

      // 遍历每个多边形，计算其边界框，并更新最小/最大坐标
      polygons.forEach((polygon) => {
        const thisbbox = bbox(polygon);
        minX = Math.min(minX, thisbbox[0]);
        minY = Math.min(minY, thisbbox[1]);
        maxX = Math.max(maxX, thisbbox[2]);
        maxY = Math.max(maxY, thisbbox[3]);
      });

      // 计算正方形的边长
      const sideLength = Math.max(maxX - minX, maxY - minY);

      // 创建正方形的四个角点
      const squareCoords = [
        [minX, minY],
        [minX + sideLength, minY],
        [minX + sideLength, minY + sideLength],
        [minX, minY + sideLength],
        [minX, minY], // 闭合多边形
      ];

      // // 使用Turf.js创建正方形多边形
      // const squarePolygon = polygon([squareCoords]);
      return squareCoords;
    },
    geoJSONMultiPolygonToCesiumPolygons11(multiPolygon) {
      let polygonsHierarchy = [];

      multiPolygon.geometry.coordinates.forEach((polygon) => {
        let rings = [];

        polygon.forEach((ring) => {
          let cartesianPoints = ring.map((coordinates) => {
            return Cesium.Cartesian3.fromDegrees(
              coordinates[0],
              coordinates[1]
            );
          });

          rings.push(cartesianPoints);
        });

        polygonsHierarchy.push(rings);
      });

      return polygonsHierarchy;
    },
    geoJSONMultiPolygonToCesiumPolygons(multiPolygon) {
      // 假设multiPolygon是一个有效的多边形数组
      let polygonsHierarchy = [];
      // {
      //             // Cesium.PolygonHierarchy
      //             positions: point3ds[0],
      //             holes: holes, // Cesium.PolygonHierarchy 数组
      //           }
      multiPolygon.geometry.coordinates.forEach((polygon) => {
        var polygons = { positions: [] };
        if (polygon.length > 1) {
          polygons.holes = [];
        }
        polygon.forEach((element, i) => {
          if (i == 0) {
            polygons.positions = Cesium.Cartesian3.fromDegreesArray(
              element.flat()
            );
          } else {
            polygons.holes.push({
              positions: Cesium.Cartesian3.fromDegreesArray(element.flat()),
            });
          }
        });

        // 创建PolygonHierarchy结构
        polygonsHierarchy.push(polygons);
      });

      return polygonsHierarchy;
    },
  },
  watch: {
    "form.selDate": function (newValue) {
      if (!shadowQuery) {
        return;
      }
      this.loading = true;
      let st = new Date(newValue);
      st.setHours(this.form.startTime);
      let et = new Date(newValue);
      et.setHours(this.form.endTime);
      shadowQuery.startTime = Cesium.JulianDate.fromDate(st);
      shadowQuery.endTime = Cesium.JulianDate.fromDate(et);
    },
    "form.startTime": function (newValue) {
      if (!shadowQuery) {
        return;
      }
      this.loading = true;
      let thisdate = new Date(this.form.selDate);
      var st = thisdate;
      st.setHours(Number(newValue));
      shadowQuery.startTime = Cesium.JulianDate.fromDate(st);
    },
    "form.endTime": function (newValue) {
      if (!shadowQuery) {
        return;
      }
      this.loading = true;
      let thisdate = new Date(this.form.selDate);
      var et = thisdate;
      et.setHours(Number(newValue));
      shadowQuery.endTime = Cesium.JulianDate.fromDate(et);
    },
    "form.timeInterval": function (newValue) {
      if (!shadowQuery) {
        return;
      }
      this.loading = true;
      shadowQuery.timeInterval = Number(newValue);

      shadowQuery.build();
    },
    "form.spacing": function (newValue) {
      if (!shadowQuery) {
        return;
      }
      this.loading = true;
      shadowQuery.spacing = Number(newValue);

      shadowQuery.build();
    },
    "form.bottomHeight": function (newValue) {
      if (!shadowQuery) {
        return;
      }
      this.loading = true;
      var bh = Number(newValue);
      var eh = Number(this.form.extrudeHeight);
      shadowQuery.qureyRegion({
        position: this.points,
        bottom: bh,
        extend: eh,
      });
      shadowQuery.build();
    },
    "form.extrudeHeight": function (newValue) {
      if (!shadowQuery) {
        return;
      }
      this.loading = true;
      var bh = Number(this.form.bottomHeight);
      var eh = Number(newValue);
      shadowQuery.qureyRegion({
        position: this.points,
        bottom: bh,
        extend: eh,
      });
      shadowQuery.build();
    },
  },
  beforeDestroy() {
    document.oncontextmenu = null;
    this.clear();
    this.clearmarkedPoints();
    if (shadowQuery) {
      shadowQuery.clear();
      shadowQuery.destroy();
      shadowQuery = null;
    }
    if (handlerPolygon) {
      handlerPolygon.deactivate();
    }
    handlerPolygon = undefined;
    this.dqSunlight();

    let scene = viewer.scene;
    layers = scene.layers.layerQueue;
    viewer.shadows = this.RecordInitializationScene.shadows;
    //图层模型还原阴影
    for (let i = 0; i < layers.length; i++) {
      var shadowType = this.RecordInitializationScene.layersshadowType.find(
        (c) => c.name == layers[i].name
      );
      if (shadowType) {
        if (layers[i].shadowType != shadowType.shadowType) {
          layers[i].shadowType = shadowType.shadowType;
          layers[i].refresh();
        }
      }
    }
  },
};
</script>
<style lang="scss">
@import "@/../../zt.scss";
</style>
<style lang="scss" scoped>
.el-card {
  border: 0px solid #02a7f0;
}
.el-form-item {
  margin-bottom: 0;
}
.slider_padding {
  padding: 0rem 0.5rem;
}
</style>
