UNPKG

gisthreemap

Version:

基于webGL的三维api

1,797 lines 60.9 kB
// import * as Cesium from 'cesium'
// import 'cesium/Widgets/widgets.css'
import CustomTilingScheme from './SubClass/CustomTilingScheme'
import MapEvent from './SubClass/MapEvent'
import Popup from './SubClass/Popup'
import Entitys from './SubClass/Entitys'
import EntitysEffect from './SubClass/EntitysEffect'
import CustomMaterial from './extendMaterial/CustomMaterial'
import CircleDiffusion from './SubClass/CircleDiffusion'
import HexagonSpread from './SubClass/HexagonSpread'
import Scanline from './SubClass/Scanline'
import CircleScan from './SubClass/CircleScan'
import Measure from './SubClass/Measure'
import draw from './SubClass/draw'
import DrawDynamicTool from './SubClass/DrawDynamicTool'
import Mentitys from './SubClass/Mentitys'
import commonTools from './SubClass/CommonTools'
import Handler from './SubClass/Handler'
import MouseManager from './SubClass/MouseManager'
import EntityFactory from './SubClass/EntityFactory'
import TrackedAnimate from './SubClass/TrackedAnimate'
import Criska_Plugin from './SubClass/Criska_Plugin'
//导入mars3d主库
import "mars3d/dist/mars3d.css";
import "../assets/css/camera.css";
import "../assets/css/divGraphic.css";
import * as mars3d from "mars3d";

//导入mars3d插件(按需使用,需要先npm install)
// import "mars3d-space";

// import XbsjEarth from 'XbsjEarth/dist/XbsjEarth/XbsjEarth.js'
// import MVTImageryProvider from 'mvt-imagery-provider';

import mapboxstyle from "./mapVecstyles/mapboxstyle";

// 引入 turf
import * as turf from "@turf/turf";
// 引入 axios
import axios from 'axios'



class Criska_Cesium {
  constructor(options) {
    this.options = options
    this.Events = [] //存储地图点击事件,绘制时,清空存储事件
    this.pointEntitiesLine = [] // 存放高度线的数组
    this.mars3d = mars3d
    this.mgraphicLayer = new mars3d.layer.GraphicLayer({ id: 'simplelayer' })
    this.heatMap = null
  }
  init(callback) {
    // 配置 cesium token
    Cesium.Ion.defaultAccessToken = this.options.CesiumToken
    const defaultOptions = {
      selectionIndicator: false, // 去掉点击的选中框
      baseLayerPicker: false, // 如果设置为false,将不会创建右上角图层按钮。
      imageryProvider: false, //必须为false

      geocoder: false, // 如果设置为false,将不会创建右上角查询(放大镜)按钮。
      navigationHelpButton: false, // 如果设置为false,则不会创建右上角帮助(问号)按钮。
      homeButton: false, // 如果设置为false,将不会创建右上角主页(房子)按钮。
      sceneModePicker: false, // 如果设置为false,将不会创建右上角投影方式控件(显示二三维切换按钮)。
      animation: false, // 如果设置为false,将不会创建左下角动画小部件。
      timeline: false, // 如果设置为false,则不会创建正下方时间轴小部件。
      fullscreenButton: false, // 如果设置为false,将不会创建右下角全屏按钮。
      scene3DOnly: true, // 为 true 时,每个几何实例将仅以3D渲染以节省GPU内存。
      shouldAnimate: true, // 默认true ,否则为 false 。此选项优先于设置 Viewer#clockViewModel 。
      // ps. Viewer#clockViewModel 是用于控制当前时间的时钟视图模型。我们这里用不到时钟,就把shouldAnimate设为false
      infoBox: false, // 是否显示点击要素之后显示的信息
      sceneMode: 3, // 初始场景模式 1 2D模式 2 2D循环模式 3 3D模式  Cesium.SceneMode
      requestRenderMode: false, // 启用请求渲染模式,不需要渲染,节约资源吧
      fullscreenElement: document.body, // 全屏时渲染的HTML元素 暂时没发现用处,虽然我关闭了全屏按钮,但是键盘按F11 浏览器也还是会进入全屏
      contextOptions: {
        requestWebgl2: true,
        msaa: true,
        multisampleNum: 8,
    }
    }
    const initOptions = this.options.initOptions || defaultOptions
    this.ThreeViewer = new Cesium.Viewer(this.options.el, initOptions)
    const canvas = document.querySelector('.cesium-widget canvas')
    let ctx = canvas.getContext("2d");
    console.log(ctx,'ctx')
    //this.earth = new XE.Earth(this.options.el);
    //this.ThreeViewer = this.earth.czm.viewer;

    this.marsmap = new mars3d.Map(this.ThreeViewer, {
      control: {
        contextmenu: { hasDefault: true } // 右键菜单
      }
    })
    // 挂载3D热力图
    this.heatMap = new HeatMap3D(this.ThreeViewer);

    let dom1 = document.querySelector('#Threemapview .mars3d-contextmenu')
    dom1.remove();
    let dom2 = document.querySelector('#Threemapview .mars3d-smallTooltip')
    dom2.remove();
    this.marsmap.addLayer(this.mgraphicLayer)

    const NODE_ENV = process.env.NODE_ENV;
    console.log(NODE_ENV);
    // 开发环境
    if (NODE_ENV === 'development') {
     //  console.clear()
      // 清除版权信息
      // let clearIntervalTime = setInterval(() => {
      //   console.clear()
      // }, 100)

      // let clearSetTime = setTimeout(() => {
      //   clearInterval(clearIntervalTime)
      //   clearTimeout(clearSetTime)
      // }, 10000)
      // window.requestAnimationFrame(animationVersion);
    } else {
      // 清除版权信息
      window.requestAnimationFrame(animationVersion);
    }


    // 回调
    if (callback) {
      callback(this.ThreeViewer)
    }
    // this.marsmap.unbindContextMenu()

    // this.earth.sceneTree.root = {
    //   "title": "当前场景",
    //   "isSelected": true,
    //   "children": [
    //   ]
    // };

    // 隐藏版权
    this.ThreeViewer._cesiumWidget._creditContainer.style.display = 'none'

    this.ThreeViewer.scene.light = new Cesium.DirectionalLight({ //去除时间原因影响模型颜色
      direction: new Cesium.Cartesian3(0.35492591601301104, -0.8909182691839401, -0.2833588392420772)
    })

    const criskapl = Criska_Plugin()
    // 挂载第三方插件
    this.criskaplugin = new criskapl(this.ThreeViewer)

    // console.log(mapboxgl, 'mapboxgl')



    // let terrainProvider = new Cesium.CesiumTerrainProvider({
    //   url : Cesium.IonResource.fromAssetId(3956),
    //   requestWaterMask: true, // 请求水体效果所需要的海岸线数据
    //   requestVertexNormals: true, // 请求地形照明数据
    // });

    // this.ThreeViewer.terrainProvider = terrainProvider;


    // 打开抗锯齿
    this.ThreeViewer.scene.fxaa = true
    this.ThreeViewer.scene.postProcessStages.fxaa.enabled = true;

    // 自动调整分辨率

    this.adjustmentPixel()

    // Primitive 管理
    this.Primitivemanager = new Cesium.PrimitiveCollection();
    this.Primitivemanager.destroyPrimitives = false;
    this.ThreeViewer.scene.primitives.add(this.Primitivemanager);




    // let supportsImageRenderingPixelated = this.ThreeViewer.cesiumWidget._supportsImageRenderingPixelated;
    // if (supportsImageRenderingPixelated) {
    //   let vtxf_dpr = window.devicePixelRatio;
    //   while (vtxf_dpr >= 2.0) { vtxf_dpr /= 2.0; }
    //   this.ThreeViewer.resolutionScale = vtxf_dpr;
    // }


    // 隐藏默认切片
    // imageryLayers.get(0).show = false;
    // 时间设置,调整光照
    let utc = Cesium.JulianDate.fromDate(new Date(this.options.currentTime)) // UTC
    this.ThreeViewer.clock.currentTime = Cesium.JulianDate.addHours(utc, 8, new Cesium.JulianDate()) // 北京时间=UTC+8=GMT+8
    // 点击事件监听
    // 获取BoundingSphere
    this.originboundingSphere = this.getBoundingSphere({
      r: this.options.mapOption.radius,
      ...this.options.mapOption.center
    })
    const { x: originx, y: originy, z: originz } = this.options.mapOption.center
    const { heading, pitch, roll, radius } = this.options.mapOption

    // camera视野的默认偏转角度
    // let heading = Cesium.Math.toRadians(360.0)
    // let pitch = Cesium.Math.toRadians(-45.0)
    // // 镜头距点位距离
    // let range = 500
    // 创建中心点
    this.centerEntity = new Cesium.Entity({
      eid: 'centerpoint',
      position: Cesium.Cartesian3.fromDegrees(originx, originy),
      point: {
        pixelSize: 0,
        color: Cesium.Color.WHITE.withAlpha(0),
        outlineColor: Cesium.Color.WHITE.withAlpha(0),
        outlineWidth: 0
      }
    });
    this.ThreeViewer.entities.add(this.centerEntity);
    // 加载底图
    this.initBaseLayers(this.options.baseLayer.Cesium)










    // 加载arcgis管线
    // this.ThreeViewer.imageryLayers.addImageryProvider(
    //   new Cesium.ArcGisMapServerImageryProvider({
    //    url : 'http://192.168.88.205:6080/arcgis/rest/services/jy/JYGS_pipe_BS/MapServer'
    //   })
    // )
    // 加载设备
    this.initBaseEquments(this.options.EqumentPoints)
    // 是否光照
    this.sunshine(this.options.senceOption.sunshine)
    // 是否自传
    if (this.options.senceOption.autoRotation) {
      // 自转动
      this.autoRotation(() => {
        if (this.options.Tile3DModels.length > 0) {

          // 遍历Tile3DModels,看是否有飞向模型,没有的话,飞向自定的范围
          let models = this.options.Tile3DModels.filter(item => item.gotomodel)
          if (!models.length) {
            this.CommonflyTo(this.centerEntity, { offset: new Cesium.HeadingPitchRange(heading, pitch, originz), duration: 5 })


          }
          setTimeout(() => {
            this.initBaseModels(this.options.Tile3DModels)
            // 加载水系
            this.initWaterLayers(this.options.waterpolygons)
            // 加载管线
            this.initBaseLayers(this.options.featureLayers)
          }, 5100)

        } else {
          this.CommonflyTo(this.centerEntity, { offset: new Cesium.HeadingPitchRange(heading, pitch, originz), duration: 5 })
          setTimeout(() => {
            // 加载水系
            this.initWaterLayers(this.options.waterpolygons)
            // 加载管线
            this.initBaseLayers(this.options.featureLayers)
          }, 5200)

        }

      })
    } else {
      if (this.options.Tile3DModels.length > 0) {
        this.initBaseModels(this.options.Tile3DModels)
        // 遍历Tile3DModels,看是否有飞向模型,没有的话,飞向自定的范围
        let models = this.options.Tile3DModels.filter(item => item.gotomodel)
        if (!models.length) {
          this.CommonflyTo(this.centerEntity, { offset: new Cesium.HeadingPitchRange(heading, pitch, originz), duration: 5 })


        }
        setTimeout(() => {
          // 加载水系
          this.initWaterLayers(this.options.waterpolygons)
          // 加载管线
          this.initBaseLayers(this.options.featureLayers)
        }, 5200)

      } else {
        this.CommonflyTo(this.centerEntity, { offset: new Cesium.HeadingPitchRange(heading, pitch, originz), duration: 5 })
        setTimeout(() => {
          // 加载水系
          this.initWaterLayers(this.options.waterpolygons)
          // 加载管线
          this.initBaseLayers(this.options.featureLayers)
        }, 5200)
      }
    }

 


    // 挂载子class
    this.bindSubClass()
    // 设置初始动画速度
    this.originspeed = this.ThreeViewer.clockViewModel.multiplier

    // //  清除版权信息
    // setTimeout(() => {
    //   console.clear()
    // }, 8000)



  }



  /**
   * 挂载子类
   */
  bindSubClass() {

    // 挂载自定义材质纹理
    this.CustomMaterial = new CustomMaterial()


    // 事件类
    this.mapevent = new MapEvent(this.ThreeViewer, this.options.mapEventOption)
    // 量测类
    this.measure = new Measure(this.ThreeViewer)
    // 动态绘制类
    this.drawDynamicTool = new DrawDynamicTool(this.ThreeViewer)
    // 绘制类
    this.draw = new draw(this.ThreeViewer)
    // 鼠标事件
    this.handlerAction = new Handler(this.ThreeViewer)
    // 基础实体事件
    this.mentitys = new Mentitys(this.ThreeViewer)
    // 鼠标管理
    this.mouseManager = new MouseManager(this.ThreeViewer)
    // 动态实体
    this.entityFactory = new EntityFactory(this.ThreeViewer)
    // 通用工具
    this.commonTools = new commonTools()
    // 弹窗类
    this.popup = new Popup(this.ThreeViewer)
    // 实体类自动初始化的
    this.defaultEntitys = new Entitys(this.ThreeViewer)
    // 自定义的Entitys
    this.CustomEntitys = Entitys
    // 特效实体类自动初始化
    this.defaultEntitysEffect = new EntitysEffect(this.ThreeViewer)
    // 自定义的EntitysEffect
    this.CustomEntitysEffect = EntitysEffect
    // 挂载扩散圆
    this.circleDiffusion = new CircleDiffusion(this.ThreeViewer)
    // 挂载六角星
    this.hexagonSpread = new HexagonSpread(this.ThreeViewer, 'hexagonSpread')
    // 挂载线圈发光
    this.scanline = new Scanline(this.ThreeViewer, 'scanlineSpread')
    // 挂载雷达平扫
    this.circleScan = new CircleScan(this.ThreeViewer)
    // 轨迹动画类
    this.trackEntity = new TrackedAnimate(this.ThreeViewer, 'trace_animate', () => {

    })


    // this.criska_base = new Criska_Base(this.ThreeViewer)


  }

  // 分辨率调整函数

  adjustmentPixel() {

    // 判断是否支持图像渲染像素化处理

    let supportsImageRenderingPixelated = this.ThreeViewer.cesiumWidget._supportsImageRenderingPixelated;

    if (supportsImageRenderingPixelated) {

      // 直接拿到设备的像素比例因子 - 如我设置的1.25

      let vtxf_dpr = window.devicePixelRatio;

      // 这个while我们在后面会做一个说明,但不是解决问题的说明

      while (vtxf_dpr >= 2.0) { vtxf_dpr /= 2.0; }

      // 设置渲染分辨率的比例因子

      this.ThreeViewer.resolutionScale = vtxf_dpr;

    }

  }

  initBaseLayers(layers) {
    if (!layers || !layers.length) return []
    layers.forEach(item => {
      switch (item.layerType) {
        case 'WebTileLayer':
          this.addWebTileLayer(item)
          break;
        case 'WMTS':
          this.addWmtsLayer(item)
          break;
        case 'ArcGIS':
          this.addArcgisLayer(item)
          break;
        case 'MapBox_Raster':
          this.addMapBoxRasterLayer(item)
          break;
        case 'WMS':
          this.addWMSLayer(item)
          break;
        default:
          break;
      }
      // 显隐控制
      this.setLayerVisable({ layerid: item.id }, item.visable)
    })
  }
  initBaseModels(models) {
    if (!models || !models.length) return []
    models.forEach(item => {
      if (item.add) {
        this.add3DTileModels(item)
      }

    })
  }
  initBaseEquments(points) {
    if (!points || !points.length) return []
    points.forEach(item => {
      this.addMakers(item.points, item.sourcename, item.visable)
    })
  }
  initWaterLayers(layers) {


    // jsp.features[0].geometry.coordinates.reduce(function (a, b) { return a.concat(b) });




    if (!layers || !layers.length) return []
    layers.forEach(item => {

      this.TestloadGeojson(item.url, '水体面')

    })
  }

  initWaterLayersWMS(layers) {


    // jsp.features[0].geometry.coordinates.reduce(function (a, b) { return a.concat(b) });




    if (!layers || !layers.length) return []
    layers.forEach(item => {
      axios.post(item.url, null, {
        params: {
          ...item.params
        }
      })
        .then((res) => {
          console.log(res, 'res')
          // 
          let features = res.data.features;
          features.forEach((sitem) => {

            let coordinates = sitem.geometry.coordinates

            coordinates.forEach((gitem) => {
              console.log(gitem, 'gitem')

              let c3polygon = gitem.reduce(function (a, b) { return a.concat(b) });
              // console.log(c3polygon, 'c3polygonc3polygon')
              // 生成水系
              this.setWaterEarth(c3polygon, {
                id: `water_${Math.random()}`,
                baseWaterColor: [207, 53, 46, 1], // 水面基本颜色
                blendColor: [127, 127, 127, 0.7], // 水面融合颜色
                height: 0.24, // 水面高度
                ground: false, // 是否贴底
                frequency: 5000, // 水面频率
                amplitude: 2, // 水面振幅
                animationSpeed: 0.05, // 水面速度
                specularIntensity: 0.5, // 水面强度
                horizontalSpeed: 10, // 水平方向速度
                verticalSpeed: 10, // 水平方向速度
                outline: false

              })
            })
          })
        })
        .catch(err => console.warn(err));

    })
  }
  TestloadGeojson(data, name, color) {

    // '@public/json/给水管-绿色.json'
    Cesium.GeoJsonDataSource.load(data, {
      fill: new Cesium.Color(0, 0.49, 1.0, 0.5), stroke: new Cesium.Color(0, 0.49, 1.0, 0.5),
    }).then((dataSource) => {
      dataSource.name = name
      this.ThreeViewer.dataSources.add(dataSource)
      console.log(dataSource, 'dataSource')
      const entities = dataSource.entities.values
      entities.forEach((item) => {
        console.log(item, 'item')
      })




    })
  }
  setWaterEarth(degrees, options = {
    id: `water_${Math.random()}`,
    baseWaterColor: [0, 127, 255, 1], // 水面基本颜色
    blendColor: [127, 127, 127, 0.7], // 水面融合颜色
    height: 0.24, // 水面高度
    ground: false, // 是否贴底
    frequency: 5000, // 水面频率
    amplitude: 2, // 水面振幅
    animationSpeed: 0.005, // 水面速度
    specularIntensity: 0.5, // 水面强度
    horizontalSpeed: 10, // 水平方向速度
    verticalSpeed: 10, // 水平方向速度
    outline: false

  }) {
    // const criskaplugin = this.earth
    // 处理坐标 转为弧度
    let positions = degrees.map((item) => {
      return Cesium.Math.toRadians(item)

    })
    // 处理颜色,归到0-1
    let baseColor = options.baseWaterColor.map((item) => {
      return item / 255
    })
    baseColor[3] = options.baseWaterColor[3];
    let blendColor = options.blendColor.map((item) => {
      return item / 255
    })
    blendColor[3] = options.blendColor[3];
    let wateroptions = {
      ...options,
      baseWaterColor: baseColor,
      blendColor: blendColor
    }


    // const objConfig = {
    //   "ref": options.id,
    //   "czmObject": {
    //     "xbsjType": "Water",
    //     "positions": positions,
    //     ...wateroptions
    //   }
    // };
    // const Water = new XE.Obj.Water(criskaplugin);
    // Water.xbsjFromJSON(objConfig);
    this.earth.sceneTree.root.children.push({
      "ref": options.id,
      "czmObject": {
        "xbsjType": "Water",
        "positions": positions,
        ...wateroptions
      }
    });


    // criskaplugin.sceneTree.root.children.push()

    console.log(this.earth.sceneTree.root, '水系已添加')
    // let water1 = criskaplugin.sceneTree.$refs.water1.czmObject;





  }
  /**
   * 添加geoserver wmts 图层
   * @param {Object} option
   */
  addWmtsLayer(option) {
    let CreateOption = null
    const matrixIds = ['EPSG:4326:0', 'EPSG:4326:1', 'EPSG:4326:2', 'EPSG:4326:3', 'EPSG:4326:4', 'EPSG:4326:5', 'EPSG:4326:6', 'EPSG:4326:7', 'EPSG:4326:8', 'EPSG:4326:9', 'EPSG:4326:10',
      'EPSG:4326:11', 'EPSG:4326:12', 'EPSG:4326:13', 'EPSG:4326:14', 'EPSG:4326:15', 'EPSG:4326:16', 'EPSG:4326:17', 'EPSG:4326:18', 'EPSG:4326:19', 'EPSG:4326:20', 'EPSG:4326:21']
    // const m =  ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21']
    // 仅支持3857和4326的数据
    if (option.SR === 'EPSG:4326') {
      CreateOption = {
        url: option.url,
        tileMatrixSetID: option.SR,
        tileMatrixLabels: matrixIds,
        style: option.style || '',
        tilingScheme: new Cesium.GeographicTilingScheme({
          // 此处很重要,很重要。。。
          numberOfLevelZeroTilesX: 2,
          numberOfLevelZeroTilesY: 1
        })
      }
    } else if (option.SR === 'EPSG:3857') {
      CreateOption = {
        style: option.style || '',
        url: `${option.url}/rest/${option.layername}/{style}/{TileMatrixSet}/{TileMatrixSet}:{TileMatrixSet}:{TileMatrix}/{TileRow}/{TileCol}?format=image/png`,
        tileMatrixSetID: 'EPSG:900913'
      }
    }

    const wmtsImageryProvider = new Cesium.WebMapTileServiceImageryProvider({
      format: 'image/png',
      layer: option.layername,
      ...CreateOption
    })
    wmtsImageryProvider._layerid = option.id || `layer_${Math.random()}`
    if (option.addViewer) {
      this.ThreeViewer.imageryLayers.addImageryProvider(wmtsImageryProvider)
    }
    return wmtsImageryProvider
  }
  addArcgisLayer(option) {
    const arcGisMapServerImageryProvider = new Cesium.ArcGisMapServerImageryProvider({
      url: option.url,
      show: option.visable
      //token: 'jrafdgyUFOu1YlyT90MAJ2WnsYFnR46esei0NIRbRPMoEDref4FEBIqdk2Pl1MZUAvpgmfbqO1Knfg1MRbXTiA..'
    })
    arcGisMapServerImageryProvider._layerid = option.id || `layer_${Math.random()}`
    if (option.addViewer) {
      this.ThreeViewer.imageryLayers.addImageryProvider(arcGisMapServerImageryProvider)
    }

    return arcGisMapServerImageryProvider
  }
  /**
   * 添加网络切片
   * @param {Object} option
   * @returns
   */
  addWebTileLayer(option) {
    let CreateOption = {
      url: option.url
    }
    // 是否纠偏
    if (option.Rectification) {
      CreateOption.tilingScheme = new CustomTilingScheme({
        fromSR: 'GCJ02',
        toSR: 'EPSG:4326'
      }) // 自定义切片片方案,用于纠偏
    }
    // 是否设置获取可以请求的最大详细级别,可实现无限缩放
    if (option.maximumLevel) CreateOption.maximumLevel = option.maximumLevel
    const WebTileProvider = new Cesium.UrlTemplateImageryProvider(CreateOption)
    WebTileProvider._layerid = option.id || `layer_${Math.random()}`
    if (option.addViewer) {
      let imga = this.ThreeViewer.imageryLayers.addImageryProvider(WebTileProvider)

      // console.log(imga, 'imga')
      if (imga._imageryProvider._layerid === 'baselayer_arcgis_blue') {
        console.log(imga, 'imga')
        // contrast 对比度
        // 
        imga.brightness = 2.0
        imga.gamma = 1.1
        imga.contrast = 1.1
        imga.hue = 0.050
        imga.saturation = 1.5
        //  imga.gamma = 1
      }
      // imga.brightness = 3.0

      // imga.contrast = 
    }
    return WebTileProvider
  }
  // 加载mapbox栅格瓦片
  addMapBoxRasterLayer(option) {
    let CreateOption = {
      //   url: option.url
    }
    // 是否纠偏
    if (option.Rectification) {
      CreateOption.tilingScheme = new CustomTilingScheme({
        fromSR: 'GCJ02',
        toSR: 'EPSG:4326'
      }) // 自定义切片片方案,用于纠偏
    }
    // // const GridProvider = new Cesium.GridImageryProvider(CreateOption)
    // // GridProvider._layerid = option.id || `layer_${Math.random()}`



    // // 添加mapbox自定义地图
    let MapboxRasterLayer = new Cesium.MapboxStyleImageryProvider({
      username: "wals001",
      styleId: option.styleId,
      scaleFactor: true,
      accessToken: 'pk.eyJ1Ijoid2FsczAwMSIsImEiOiJjbGE2N2M1Ym0wMDBlM3dvMmU0MmJpazZ3In0.eFa_DgNJBal3KUH5yvlZAg',
      ...CreateOption
    });
    // mapbox://styles/criska/cl9sfslxy002z15smj457t4jn
    this.ThreeViewer.imageryLayers.addImageryProvider(MapboxRasterLayer);

    return MapboxRasterLayer


  }
  // 加载wms服务

  addWMSLayer(option) {
    let wmsImageryProvider = new Cesium.WebMapServiceImageryProvider({

      parameters: {
        transparent: true,
        format: 'image/png',
        srs: option.SR,
        styles: ''
      },
      ...option
    });
    wmsImageryProvider._layerid = option.id || `layer_${Math.random()}`
    this.ThreeViewer.imageryLayers.addImageryProvider(wmsImageryProvider); //加载
  }
  // 添加3Dtile模型
  add3DTileModels(option) {
    const ModelsTileset = new Cesium.Cesium3DTileset({
      url: option.url,
      skipLevelOfDetail: true,
      baseScreenSpaceError: 1024,
      maximumScreenSpaceError: 160, // 数值加大,能让最终成像变模糊
      skipScreenSpaceErrorFactor: 16,
      skipLevels: 1,
      immediatelyLoadDesiredLevelOfDetail: false,
      loadSiblings: true, // 如果为true则不会在已加载完概况房屋后,自动从中心开始超清化房屋
      cullWithChildrenBounds: true,
      cullRequestsWhileMoving: true,
      cullRequestsWhileMovingMultiplier: 10, // 值越小能够更快的剔除
      preloadWhenHidden: true,
      preferLeaves: true,
      maximumMemoryUsage: 256, // 内存分配变小有利于倾斜摄影数据回收,提升性能体验
      progressiveResolutionHeightFraction: 0.5, // 数值偏于0能够让初始加载变得模糊
      // dynamicScreenSpaceErrorDensity: 0.1, // 数值加大,能让周边加载变快
      dynamicScreenSpaceErrorDensity: 1, // 数值加大,能让周边加载变快
      dynamicScreenSpaceErrorFactor: 1, // 不知道起了什么作用没,反正放着吧先
      dynamicScreenSpaceError: true // 根据测试,有了这个后,会在真正的全屏加载完之后才清晰化房屋
    })
    // Cesium.ExperimentalFeatures.enableModelExperimental = true
    if (option.rgba) {
      ModelsTileset.readyPromise.then(function (tileset) {
        tileset.style = new Cesium.Cesium3DTileStyle({
          color: {
            conditions: [
              // #9faabd // 'rgb(51, 153, 255)'
              //  "color('rgb(150, 179, 189)',1)"
              ["true", option.rgba]
            ]
          }
        });
        // viewer.flyTo(tileset)
      })
    }


    // 判断是否使用自定义片元着色器
    if (option.customShader) {
      let customShader = new Cesium.CustomShader({
        lightingModel: Cesium.LightingModel[option.customShader.lightingModel],
        fragmentShaderText: option.customShader.fragmentShaderText
      })
      ModelsTileset.enableModelExperimental = true;
      ModelsTileset.customShader = customShader;
    } else {
      ModelsTileset.enableModelExperimental = false;
    }


    ModelsTileset._modelid = option.id || `model_${Math.random()}`
    // this.ThreeViewer.scene.primitives.add(ModelsTileset)


    this.primitiveadd(ModelsTileset)
    // 是否要调整模型位置
    if (option.isreset) {
      ModelsTileset.readyPromise.then((newtileset) => {
        // this.tileSet(newtileset, 104.635759, 30.132481, 9)
        this.tileSetAll(newtileset,...option.isresetoption)
      });
    }

    // 是否定位到模型位置
    if (option.gotomodel) {
      this.ThreeViewer.flyTo(ModelsTileset)
    }
    return ModelsTileset
  }
  // 修改模型颜色
  change3DTileModelsColor(modelid, rgba) {
    const model = this.getModel(modelid)
    model.style = new Cesium.Cesium3DTileStyle({
      color: {
        conditions: [
          ["true", rgba]
        ]
      }
    })

  }
  primitiveadd(primitive) {
    this.Primitivemanager.add(primitive);
    if (this.ThreeViewer.scene.primitives.length <= 1) {
      this.ThreeViewer.scene.primitives.add(this.Primitivemanager);
    }
  }
  // 利用translation对模型的经度、纬度、高度进行修改
  tileSet(tileset, longitude, latitude, height = 0) {
    //3dtile模型的边界球体
    var boundingSphere = tileset.boundingSphere;
    //迪卡尔空间直角坐标=>地理坐标(弧度制)
    var cartographic_original = Cesium.Cartographic.fromCartesian(boundingSphere.center);
    //设置新的经度、纬度、高度
    var cartographic_offset = Cesium.Cartographic.fromDegrees(longitude, latitude, height)

    //地理坐标(弧度制)=>迪卡尔空间直角坐标
    var Cartesian3_original = Cesium.Cartesian3.fromRadians(cartographic_original.longitude, cartographic_original.latitude, cartographic_original.height);
    var Cartesian3_offset = Cesium.Cartesian3.fromRadians(cartographic_offset.longitude, cartographic_offset.latitude, cartographic_offset.height);
    //获得地面和offset的转换
    var translation = Cesium.Cartesian3.subtract(Cartesian3_offset, Cartesian3_original, new Cesium.Cartesian3());
    //修改模型矩阵
    tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
  }
  // 利用transform对模型的所有参数进行修改
  tileSetAll(tileset, longitude, latitude, height, rotateX, rotateY, rotateZ, scale) {
    //平移 修改经纬度
    // const cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center);
    // var position = Cesium.Cartesian3.fromDegrees(cartographic.longitude, cartographic.latitude, cartographic.height);
    var position = Cesium.Cartesian3.fromDegrees(longitude, latitude, height);
    var transform = Cesium.Transforms.eastNorthUpToFixedFrame(position);

    //旋转角度设置
    if (rotateX) {
      var mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(rotateX));
      var rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
      //旋转、平移矩阵相乘
      Cesium.Matrix4.multiply(transform, rotationX, transform);
    }
    if (rotateY) {
      var my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(rotateY));
      var rotationY = Cesium.Matrix4.fromRotationTranslation(my);
      //旋转、平移矩阵相乘
      Cesium.Matrix4.multiply(transform, rotationY, transform);
    }
    if (rotateZ) {
      var mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(rotateZ));
      var rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);
      //旋转、平移矩阵相乘
      Cesium.Matrix4.multiply(transform, rotationZ, transform);
    }

    //缩放 修改缩放比例
    if (scale) {
      var scale1 = Cesium.Matrix4.fromUniformScale(scale);
      Cesium.Matrix4.multiply(transform, scale1, transform);
    }
    //赋值给tileset
    tileset._root.transform = transform;
  }
  primitivedeletes(primitive) {
    this.Primitivemanager.remove(primitive);
  }
  primitiveRemoveall() {
    if (this.ThreeViewer.scene.primitives.length <= 1) {
      this.ThreeViewer.scene.primitives.removeAll()
    } else {
      this.Primitivemanager.removeAll()
    }
  }

  // 添加点位
  addMakers(points, sourcetype = `source_${Math.random()}`, visable = true) {
    let dataSource = null
    // 获取dataSource 存在的状态
    const indataSource = this.getDataSourceByName(sourcetype)
    // 如果存在 先清除所有实体
    if (indataSource) {
      indataSource.entities.removeAll()
      dataSource = indataSource
    } else {
      // 生成新的dataSource
      dataSource = new Cesium.CustomDataSource(sourcetype)
      // dataSource添加到viewer
      this.ThreeViewer.dataSources.add(dataSource)
    }
    // 默认显示或隐藏
    dataSource.show = visable
    // 自定义label颜色
    const textColor = 'rgb(11, 255, 244)'
    // 清除上一次加载的点位
    // this.ThreeViewer.entities.removeAll()
    //  添加点位
    points.forEach((pointObj) => {
      // 循环添加点位引线方法
      const labelEntityLine = this.addFloatPoint(pointObj, pointObj.longitude, pointObj.latitude, pointObj.height, dataSource)
      this.pointEntitiesLine.push(labelEntityLine)
      let pointentities = {
        name: pointObj.name || '',
        id: pointObj.id,
        eid: pointObj.id,
        content: pointObj.content || '',
        position: Cesium.Cartesian3.fromDegrees(
          pointObj.longitude,
          pointObj.latitude,
          pointObj.height || 0
        ),
        // 文字标签
        label: pointObj.orilabel || {
          show: pointObj.label.show || false,
          text: pointObj.label.text || '',
          font: pointObj.label.fontsize ? `${pointObj.label.fontsize} monospace` : `14px monospace`,
          style: pointObj.label.style ? Cesium['LabelStyle'][pointObj.label.style] : Cesium['LabelStyle']['FILL_AND_OUTLINE'],
          fillColor: pointObj.label.color ? Cesium.Color.fromCssColorString(pointObj.label.color) : Cesium.Color.fromCssColorString(textColor),
          outlineWidth: pointObj.label.outlineWidth || 4,
          verticalOrigin: pointObj.label.verticalOrigin ? Cesium['VerticalOrigin'][pointObj.label.verticalOrigin] : Cesium.VerticalOrigin.BOTTOM, // 垂直方向以底部来计算标签的位置
          pixelOffset: pointObj.label.offsetx && pointObj.label.offsety ? new Cesium.Cartesian2(pointObj.label.offsetx, pointObj.label.offsety) : new Cesium.Cartesian2(0, -60) // 偏移量
        },
        // 图标
        billboard: {
          image: pointObj.billboard.image || 'https://p26-passport.byteacctimg.com/img/user-avatar/a7ab372b32558ab9c8e130194a1a78d8~300x300.image',
          width: pointObj.billboard.width || 48,
          height: pointObj.billboard.height || 75,
          pixelOffset: pointObj.billboard.offsetx && pointObj.billboard.offsety ? new Cesium.Cartesian2(pointObj.billboard.offsetx, pointObj.billboard.offsety) : new Cesium.Cartesian2(0, 0), // 偏移量
          horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
          verticalOrigin: Cesium.VerticalOrigin.BOTTOM
        }
      }
      if (pointObj.hasOwnProperty('selfsymbol')) {
        pointentities = {
          name: pointObj.name,
          id: pointObj.id,
          eid: pointObj.id,
          position: Cesium.Cartesian3.fromDegrees(
            pointObj.longitude,
            pointObj.latitude,
            pointObj.height || 0
          ),
          ...pointObj.selfsymbol
        }
      }
      // 实体添加到dataSource
      dataSource.entities.add(pointentities)
    })
    return dataSource
  }
  // 加载高度线
  addFloatPoint(pointObj, long, lat, height, dataSource) {
    const lineColor = '#108de7'
    let floatlinesymbol = {
      positions: Cesium.Cartesian3.fromDegreesArrayHeights([
        long, lat, 0,
        long, lat, height
      ]),
      width: 1,
      // 材质设置
      // material: Cesium.Color.DODGERBLUE,
      // material: Cesium.Color.fromCssColorString(lineColor)
      material: new Cesium.PolylineGlowMaterialProperty({ //发光线
        glowPower: pointObj.floatline.glowPower || 0.25,
        color: pointObj.floatline.color ? Cesium.Color.fromCssColorString(pointObj.floatline.color) : Cesium.Color.DODGERBLUE
      })

    }
    if (pointObj.floatline.hasOwnProperty('selfsymbol')) {
      floatlinesymbol = {
        positions: Cesium.Cartesian3.fromDegreesArrayHeights([
          long, lat, 0,
          long, lat, height
        ]),
        ...pointObj.floatline.selfsymbol
      }
    }
    // 如果传了dataSource 加载到dataSource
    if (dataSource) {
      dataSource.entities.add({
        name: 'line_' + pointObj.pointName,
        code: 'line_' + pointObj.id,
        id: 'line_' + pointObj.id,
        eid: 'line_' + pointObj.id,
        // 经度维度必须是数字
        // position: Cesium.Cartesian3.fromDegrees(120.42602, 31.92423),
        polyline: floatlinesymbol
      })
      return dataSource.entities

    } else {
      // 否则加载到viewer的entities里
      const entityLine = this.ThreeViewer.entities.add({
        name: 'line_' + pointObj.pointName,
        code: 'line_' + pointObj.id,
        id: 'line_' + pointObj.id,
        eid: 'line_' + pointObj.id,
        // 经度维度必须是数字
        // position: Cesium.Cartesian3.fromDegrees(120.42602, 31.92423),
        polyline: floatlinesymbol
      })
      return entityLine
    }
  }

  // 加载信息框
  addPopPoint(pointObj, long, lat, height, dataSource) {

  }

  // 添加点位模型
  addGlbModels(points, sourcetype = `source_${Math.random()}`, visable = true) {
    let dataSource = null
    // 获取dataSource 存在的状态
    const indataSource = this.getDataSourceByName(sourcetype)
    // 如果存在 先清除所有实体
    if (indataSource) {
      indataSource.entities.removeAll()
      dataSource = indataSource
    } else {
      // 生成新的dataSource
      dataSource = new Cesium.CustomDataSource(sourcetype)
      // dataSource添加到viewer
      this.ThreeViewer.dataSources.add(dataSource)
    }
    // 默认显示或隐藏
    dataSource.show = visable
    // 自定义label颜色
    const textColor = 'rgb(11, 255, 244)'
    // 清除上一次加载的点位
    // this.ThreeViewer.entities.removeAll()
    //  添加点位
    points.forEach((pointObj) => {
      // 循环添加点位引线方法
      // const labelEntityLine = this.addFloatPoint(pointObj, pointObj.longitude, pointObj.latitude, 1000, dataSource)
      // this.pointEntitiesLine.push(labelEntityLine)
      let modelentities = {
        name: pointObj.name || '',
        id: pointObj.id,
        eid: pointObj.id,
        content: pointObj.content || '',
        position: Cesium.Cartesian3.fromDegrees(
          pointObj.longitude,
          pointObj.latitude,
          pointObj.height || 0
        ),
        orientation: Cesium.Transforms.headingPitchRollQuaternion(
          Cesium.Cartesian3.fromDegrees(
            pointObj.longitude,
            pointObj.latitude,
            pointObj.height || 0
          ),
          new Cesium.HeadingPitchRoll(
            Cesium.Math.toRadians(pointObj.head || 50),    // 设置这个属性即可(顺时针旋转的角度值)
            Cesium.Math.toRadians(pointObj.roll || 0),
            Cesium.Math.toRadians(pointObj.patch || 0)
          )
        ),
        // orientation: new Cesium.CallbackProperty(diaoyong, false),

        model: {
          show: true,
          uri: pointObj.modeluri,
          scale: pointObj.modelscale,
          color: pointObj.color ? Cesium.Color.fromCssColorString(pointObj.color) : null,
          minimumPixelSize: 60,
          maximumScale: 50000,
        },
        ...pointObj
      }
      // 实体添加到dataSource
      dataSource.entities.add(modelentities)
    })
    return dataSource
  }

  /**
   * 创建缓冲区
   * @param {*} lon 
   * @param {*} lat 
   * @param {*} radius 
   * @param {*} units 
   */
  createBuffer(lon, lat, radius, units = 'kilometer') {
    const point = turf.point([lon, lat])
    const buffered = turf.buffer(point, radius / 1000, { units })
    let coordinates = buffered.geometry.coordinates
    let points = coordinates[0]
    let degreesArray = this.pointsToDegreesArray(points)
    // this.ThreeViewer.entities.add({
    //   polygon: {
    //       hierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray(degreesArray)),
    //       material: Cesium.Color.RED.withAlpha(0.6),
    //       classificationType: Cesium.ClassificationType.BOTH
    //   },
    // })
    return {
      geojson: buffered,
      degreesArray
    }
  }
  // 点数组转为cesium格式
  pointsToDegreesArray(points, height) {
    let degreesArray = []
    points.map(item => {
      degreesArray.push(item[0])
      degreesArray.push(item[1])
      if (height) {
        degreesArray.push(height)
      }
    });
    return degreesArray
  }

  /**
   * 删除图层
   * @param {*} layer 
   * @param {*} hasDestroy  是否释放对象
   */
  removeLayer(layer, hasDestroy) {
    this.marsmap.removeLayer(layer, hasDestroy)
  }
  getLayerById() {

  }

  removeAllEntity(sourcetype) {
    // 清除dataSource的实体
    if (sourcetype) {
      const DataSource = this.getDataSourceByName(sourcetype)
      DataSource.entities.removeAll()
    } else {
      const DataSources = this.getDataSources()
      DataSources._dataSources.forEach((item) => {
        if (item.name) {
          if (!(item.name.includes('Equpoint'))) {
            item.entities.removeAll()
          }
        }
      })
      this.ThreeViewer.entities.removeAll()
    }
  }

  // 清除所有实体,关闭点选事件,关闭量测
  clearEntandCloseMe() {
    // 删除实体
    this.removeAllEntity()
    // 清除点选
    this.options.mapEventOption.openEntityEventMap = false
    this.options.mapEventOption.pipeEventMap = false
    // 关闭量测
    this.measure.remove()
  }
  /**
   * 清除实体通过Eid
   * @param {} eid
   * @param {*} sourcetype
   * @returns
   */
  removeEntityByEid(eid, sourcetype) {
    const { entities, Entity } = this.getEntityByEid(eid, sourcetype)
    entities.remove(Entity)
    return entities
  }
  /**
   * 清除实体通过id
   * @param {} id
   * @param {*} sourcetype
   * @returns
   */
  removeEntityById(id, sourcetype) {
    const { entities, Entity } = this.getEntityById(id, sourcetype)
    entities.remove(Entity)
    return entities
  }

  removeDataSource(name, destroy = true) {
    const dataSource = this.getDataSourceByName(name)
    // 获取单一设备
    this.ThreeViewer.dataSources.remove(dataSource, destroy)

  }

  getViewer() {
    return this.ThreeViewer
  }
  /**
   * 获取具有中心和半径的包围球。
   * @param {Object} option
   */
  getBoundingSphere(option) {
    // Cartesian3.fromDegrees 从以度为单位的经度和纬度值返回笛卡尔坐标位置。
    return new Cesium.BoundingSphere(
      Cesium.Cartesian3.fromDegrees(option.x, option.y, option.z),
      option.r
    )
  }

  /**
   * 从以度为单位的经度和纬度值返回Cartesian3位置。
   * @returns
   */
  getCartesian3fromDegrees(longitude, latitude, height = 0) {
    return Cesium.Cartesian3.fromDegrees(Number(longitude), Number(latitude), Number(height))
  }

  /**
   * 笛卡尔坐标转换为画布坐标
   * @param {} Cartesian3
   */
  getCanvasCoordfromcartesian(Cartesian3) {
    return this.ThreeViewer.scene.cartesianToCanvasCoordinates(Cartesian3, new Cesium.Cartesian2())
  }

  // 笛卡尔转为经纬度
  getWGS84FromCartesian3(coor) {
    let cartographic = Cesium.Cartographic.fromCartesian(coor);
    let x = Cesium.Math.toDegrees(cartographic.longitude);
    let y = Cesium.Math.toDegrees(cartographic.latitude);
    let wgs84 = {
      x: x,
      y: y,
    };
    return wgs84;
  }

  /**
   * 
   * @returns 获取当前范围
   */
  getCurrentExtent() {

    // 范围对象
    let extent = {}

    // 得到当前三维场景
    let scene = this.ThreeViewer.scene

    // 得到当前三维场景的椭球体
    let ellipsoid = scene.globe.ellipsoid
    let canvas = scene.canvas;

    // canvas左上角
    let car3_lt = this.ThreeViewer.camera.pickEllipsoid(new Cesium.Cartesian2(0, 0), ellipsoid)

    // canvas右下角
    let car3_rb = this.ThreeViewer.camera.pickEllipsoid(new Cesium.Cartesian2(canvas.width, canvas.height), ellipsoid)

    // 当canvas左上角和右下角全部在椭球体上
    if (car3_lt && car3_rb) {
      let carto_lt = ellipsoid.cartesianToCartographic(car3_lt)
      let carto_rb = ellipsoid.cartesianToCartographic(car3_rb)
      extent.xmin = Cesium.Math.toDegrees(carto_lt.longitude)
      extent.ymax = Cesium.Math.toDegrees(carto_lt.latitude)
      extent.xmax = Cesium.Math.toDegrees(carto_rb.longitude)
      extent.ymin = Cesium.Math.toDegrees(carto_rb.latitude)
    }

    // 当canvas左上角不在但右下角在椭球体上
    else if (!car3_lt && car3_rb) {
      let car3_lt2 = null;
      let yIndex = 0
      do {
        // 这里每次10像素递加,一是10像素相差不大,二是为了提高程序运行效率
        yIndex <= canvas.height ? yIndex += 10 : canvas.height
        car3_lt2 = this.ThreeViewer.camera.pickEllipsoid(new Cesium.Cartesian2(0, yIndex), ellipsoid)
      } while (!car3_lt2);
      let carto_lt2 = ellipsoid.cartesianToCartographic(car3_lt2)
      let carto_rb2 = ellipsoid.cartesianToCartographic(car3_rb)
      extent.xmin = Cesium.Math.toDegrees(carto_lt2.longitude)
      extent.ymax = Cesium.Math.toDegrees(carto_lt2.latitude)
      extent.xmax = Cesium.Math.toDegrees(carto_rb2.longitude)
      extent.ymin = Cesium.Math.toDegrees(carto_rb2.latitude)
    }

    // 获取高度
    extent.height = Math.ceil(this.ThreeViewer.camera.positionCartographic.height)
    return extent
  }


  getScale() {
    // 监听场景渲染事件

  }

  /**
   * 获取dataSources数据集
   * @returns
   */
  getDataSources() {
    return this.ThreeViewer.dataSources
  }
  /**
   * 根据name从DataSources 中 获取dataSource
   * @param {*} name
   * @returns
   */
  getDataSourceByName(name) {
    return this.ThreeViewer.dataSources.getByName(name)[0]
  }

  /**
   * 根据Eid获取实体
   * @param {*} eid
   * @param {*} sourcetype
   * @returns
   */
  getEntityByEid(eid, sourcetype) {
    // 根据sourcetype 查询到Source
    let entities = null
    if (sourcetype) {
      const DatsSource = this.getDataSourceByName(sourcetype)
      entities = DatsSource.entities
    } else {
      entities = this.ThreeViewer.entities
    }
    //根据Eid在dataSource中查找中Entity
    const ent = entities.values.filter((item) => {
      if (item.eid === eid) {
        return item
      }
    })

    return {
      entities,
      Entity: ent[0]
    }
  }

  /**
   * 获取实体通过ID
   * @param {} id
   * @param {*} sourcetype
   * @returns
   */
  getEntityById(id, sourcetype) {
    // 根据sourcetype 查询到Source
    let entities = null
    if (sourcetype) {
      const DatsSource = this.getDataSourceByName(sourcetype)
      entities = DatsSource.entities
    } else {
      entities = this.ThreeViewer.entities
    }
    //根据Eid在dataSource中查找中Entity
    const ent = entities.getById(id)

    return {
      entities,
      Entity: ent
    }
  }

  getModel(modelid) {
    const model = this.Primitivemanager._primitives.filter((item) => {
      if (item._modelid === modelid) {
        return item
      }
    })
    return model[0]
  }

  /* 获取camera高度  */
  getHeight() {
    if (this.ThreeViewer) {
      let height = this.ThreeViewer.camera.positionCartographic.height
      return height
    }
  }

  /* 获取camera中心点坐标 */
  getCenterPosition() {
    const result = this.ThreeViewer.camera.pickEllipsoid(new Cesium.Cartesian2(this.ThreeViewer.canvas.clientWidth / 2, this.ThreeViewer.canvas
      .clientHeight / 2))
    const curPosition = Cesium.Ellipsoid.WGS84.cartesianToCartographic(result)
    const lon = curPosition.longitude * 180 / Math.PI
    const lat = curPosition.latitude * 180 / Math.PI
    const height = this.getHeight()
    return {
      lon: lon,
      lat: lat,
      height: height
    }
  }
  /**
   * 获取相机姿态位置
   * @returns 
   */
  getcameraPosInfo() {
    // 获取 相机姿态信息
    let head = this.ThreeViewer.scene.camera.heading
    let pitch = this.ThreeViewer.scene.camera.pitch
    let roll = this.ThreeViewer.scene.camera.roll
    let info = { 'head': head, 'pitch': pitch, 'roll': roll };
    // 获取位置 wgs84的地心坐标系,x,y坐标值以弧度来表示
    let position = this.ThreeViewer.scene.camera.positionCartographic //with longitude and latitude expressed in radians and height in meters.
    //以下方式也可以获取相机位置只是返回的坐标系不一样
    // let position = viewer.scene.camera.position //cartesian3 空间直角坐标系
    // let ellipsoid = scene.globe.ellipsoid;
    // let position =ellipsoid.cartesianToCartographic(viewer.scene.camera.position)//
    // 弧度转经纬度
    let longitude = Cesium.Math.toDegrees(position.longitude).toFixed(6)
    let latitude = Cesium.Math.toDegrees(position.latitude).toFixed(6)
    let height = position.height
    return { lng: longitude, lat: latitude, h: height, mat: info }
  }

  /* 地图放大 */
  setMapbig() {
    // 镜头拉进
    this.ThreeViewer.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(this.getCenterPosition().lon, this.getCenterPosition().lat, this.getCenterPosition().height / 1.8),
      duration: 1.0,
      // orientation : {
      //   direction:  this.ThreeViewer.camera.direction,
      //   right:  this.ThreeViewer.camera.right,
      //   up:  this.ThreeViewer.camera.up,
      // }
    })
  }
  /* 地图缩小 */
  setMapsmall() {
    // 镜头远离
    this.ThreeViewer.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(this.getCenterPosition().lon, this.getCenterPosition().lat, this.getCenterPosition().height * 1.2),
      duration: 1.0
    })
  }
  /**
   * 设置图层显示和隐藏
   * @param {*} layerid
   * @param {*} layer
   * @param {*} layer
   */
  setLayerVisable({ layerid, layer = null }, visable) {
    if (layer) {
      console.log('我选择了layer,可直接隐藏')
    } else {
      // 从所有图层中进行遍历查询
      if (this.ThreeViewer.imageryLayers.length > 0) {
        this.ThreeViewer.imageryLayers._layers.forEach((item) => {
          if (item.imageryProvider._layerid === layerid) {
            item.show = visable
          }
        })
      }
    }
  }

  CreateDataSource(sourcetype) {
    return new Cesium.CustomDataSource(sourcetype)
  }


  switchBaseLayer(layerid) {
    // 高德影像
    if (layerid.includes('amap_img')) {
      this.options.baseLayer.Cesium.forEach((item) => {
        if (item.id === layerid || item.id.includes('amap_label')) {
          // 设置为显示
          this.setLayerVisable({ layerid: item.id }, true)
        } else {
          // 其他的设置为隐藏
          this.setLayerVisable({ layerid: item.id }, false)
        }
      })
    }
    // 高德普通 和 深色
    else {
      this.options.baseLayer.Cesium.forEach((item) => {
        if (item.id === layerid) {
          // 设置为显示
          this.setLayerVisable({ layerid: item.id }, true)
        } else {
          // 其他的设置为隐藏
          this.setLayerVisable({ layerid: item.id }, false)
        }
      })

    }
  }
  /**
   *
   * @param {*} boundingSphere
   * @param {*} option  包含callback
   */
  flyToBoundingSphere(boundingSphere, option = {
    duration: 1
  }) {
    this.ThreeViewer.camera.flyToBoundingSphere(boundingSphere, option)
  }
  /**
   *  相机视角移动
   * @param {*} lon
   * @param {*} lat
   * @param {*} height
   * @param {*} additional
   */
  flyTo(lon, lat, height = 1500, additional = {
    orientation: {
      heading: 0,
      pitch: -45,
      roll: 0
    }
  }) {
    let SetOption = additional
    if (additional.hasOwnProperty('orientation')) {
      SetOption.orientation.heading = Cesium.Math.toRadians(additional.orientation.heading)
      SetOption.orientation.pitch = Cesium.Math.toRadians(additional.orientation.pitch)
      SetOption.orientation.roll = Cesium.Math.toRadians(additional.orientation.roll)
    }
    this.ThreeViewer.camera.flyTo({
      destination: this.getCartesian3fromDegrees(lon, lat, height),
      ...SetOption
    })
  }

  /**
   *
   * @param {*} target
   * @param {*} options
   * @returns 飞行成功返回一个为true的promise
   */
  CommonflyTo(target, options) {
    return this.ThreeViewer.flyTo(target, options)
  }

  /**
   * 相机恢复初始状态
   */
  gotoOriginBoundingSphere() {
    let centerpoint = this.getEntityByEid('centerpoint');
    if (!centerpoint.Entity) {
      this.ThreeViewer.entities.add(this.centerEntity);
    }
    const { z: originz } = this.options.mapOption.center
    const { heading, pitch } = this.options.mapOption
    this.CommonflyTo(this.centerEntity, { offset: new Cesium.HeadingPitchRange(heading, pitch, originz), duration: 5 })
  }
  // 地球自转
  autoRotation(callback) {
    let i = Date.now()
    let rotate = () => {
      const a = 0.8;
      const t = Date.now();
      const n = (t - i) / 1e3
      i = t;
      this.ThreeViewer.scene.camera.rotate(Cesium.Cartesian3.UNIT_Z, -a * n)
    }
    // 只要时间变化就执行
    this.ThreeViewer.clock.onTick.addEventListener(rotate);
    // 4.2s后 北美洲转动至亚洲,停止转动,进入回调
    setTimeout(() => {
      this.ThreeViewer.clock.onTick.removeEventListener(rotate)
      callback()
    }, 4200);
  }
  // 日照管理
  sunshine(sun) {
    this.ThreeViewer.scene.globe.enableLighting = sun
    this.ThreeViewer.shadows = sun
  }

  changeEarthColor(color) {
    this.ThreeViewer.scene.globe.baseColor = new Cesium.Color.fromCssColorString(color)
  }

  /**
   * 时间轴操作
  */

  // 动画暂停
  clockPause() {
    this.ThreeViewer.clock.shouldAnimate = false
  }

  // 动画开始
  clockRestar() {
    this.ThreeViewer.clock.shouldAnimate = true
  }

  // 动画倍速
  clockhastenMultiplier(v) {
    this.ThreeViewer.clockViewModel.multiplier = this.originspeed * v
  }

  // 动画减倍速
  clockdecelerateMultiplier(v) {
    this.ThreeViewer.clockViewModel.multiplier = this.originspeed / v
  }
  // 重置时间轴
  clockReset() {
    this.ThreeViewer.clock.currentTime = this.ThreeViewer.clock.startTime;
  }

  // 循环/不循环
  // 时间轴执行完后停止(LOOP_STOP为循环,UNBOUNDED为继续读秒)
  clockClockRange(type = 'CLAMPED') {
    this.ThreeViewer.clock.clockRange = Cesium.ClockRange[type];
  }

  // 水面流动特效
  /**
 *  绘制水面
 * @param boundary 边界点位 [112.23, 22.25, 112.24, 22.24]
 * @param waterImg 水面贴图
 * @param extrudedHeight 水面高度
 * @returns 水面实例
 */
  useDrawRiver(
    boundary,
    waterImg,
    extrudedHeight = 0
  ) {
    const _this = this
    let riverHeight = extrudedHeight
    console.log(this.useCreatePolygonGeometry, 'this.useCreatePolygonGeometry')
    const polygon = this.useCreatePolygonGeometry(boundary, riverHeight)
    let river = null
    river = new Cesium.Primitive({
      geometryInstances: new Cesium.GeometryInstance({
        geometry: polygon,
      }),
      appearance: new Cesium.EllipsoidSurfaceAppearance({
        aboveGround: true,
      }),
      show: true,
      asynchronous: false,
      releaseGeometryInstances: false,
    })

    const riverMaterial = new Cesium.Material({
      fabric: {
        type: 'Water',
        uniforms: {
          baseWaterColor: new Cesium.Color(64 / 255.0, 157 / 255.0, 253 / 255.0, 0.5), // 水的基本颜色
          normalMap: waterImg, // 水的法线贴图
          frequency: 5000.0, // 水波纹的数量
          animationSpeed: 0.005, // 水的流速
          amplitude: 2, // 水波纹振幅
          specularIntensity: 1, // 镜面反射强度
        },
      },
    })
    const scene = this.ThreeViewer.scene
    river.appearance.material = riverMaterial
    scene.primitives.add(river) //添加到场景
    river.appearance.material = riverMaterial
    Object.defineProperty(river, 'extrudedHeight', {
      get() {
        return riverHeight
      },
      set(newVal) {
        if (typeof newVal !== 'number') {
          return
        }
        riverHeight = newVal
        river._state = 3 // 重置primitive状态触发cesium update方法
        river._appearance = undefined
        river.geometryInstances.geometry = _this.useCreatePolygonGeometry(boundary, riverHeight)
      },
    })
    return river
  }
  useCreatePolygonGeometry(boundary, extrudedHeight) {
    const polygon = new Cesium.PolygonGeometry({
      polygonHierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray(boundary)),
      extrudedHeight,
      vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
    })
    return polygon
  }

  // 生成光锥体点位
  /**
   * 光锥体点位
   * @param points 点位数据 [{longitude: 120, latitude: 38, height: 100}]
   * @param options 光锥体颜色,底部半径及高度
   * @param popupHtml 光锥体弹窗(html格式,不传则无点击弹窗功能) <table></table>
   * @param leftFnc 函数,图层左键点击事件回调(点击获取点位信息时使用)
   * @param rightObj 右键点击事件对象{text: '标题', offsetY: -170}
   */
  createLightCone(points, options = {
    color: 'rgba(255,0,0,0.9)', // 椎体颜色
    radius: 8000, // 底部半径
    height: 150000 // 椎体高度
  }, popupHtml, layername, leftFnc, rightObj) {
    let graphicLayer = null
    if (layername) {
      // 创建矢量数据图层
      let cusgraphicLayer = new mars3d.layer.GraphicLayer({ id: layername })
      graphicLayer = cusgraphicLayer
      this.marsmap.addLayer(graphicLayer)
    } else {
      graphicLayer = this.mgraphicLayer
    }
    if (popupHtml) {
      graphicLayer.bindPopup(popupHtml)
    }

    points.forEach(pointObj => {
      if (pointObj.longitude && pointObj.latitude) {
        const lightCone = new mars3d.graphic.LightCone({
          position: Cesium.Cartesian3.fromDegrees(pointObj.longitude, pointObj.latitude, (pointObj.height || 20)),
          style: {
            color: options.color,
            radius: options.radius,
            height: options.height
          },
          show: true
        })
        graphicLayer.addGraphic(lightCone)
      }
    })
    // if (leftFnc) {
    //   graphicLayer.on(mars3d.EventType.click, leftFnc)
    // }
    // if (rightObj) {
    //   // 在layer上绑定右键菜单
    //   graphicLayer.bindContextMenu(
    //     [
    //       {
    //         text: rightObj.text,
    //         icon: "fa fa-trash-o",
    //         callback: (e) => {
    //           const graphic = e.graphic
    //           console.log(graphic)
    //         }
    //       }
    //     ],
    //     { offsetY: rightObj.offsetY } // 右键菜单偏移量
    //   )
    // }
  }

  // 生成视频点位
  /**
   * 视频点位
   * @param points 点位数据 [{longitude: 120, latitude: 38, height: 100, videoUrl: 'http://data.mars3d.cn/file/video/lukou.mp4'}]
   */
  createVideoPoint(points) {
    // 创建矢量数据图层
    let graphicLayer = new mars3d.layer.GraphicLayer()
    this.marsmap.addLayer(graphicLayer)
    points.forEach(pointObj => {
      const graphicImg = new mars3d.graphic.DivGraphic({
        position: [pointObj.longitude, pointObj.latitude, (pointObj.height || 20)],
        style: {
          html: `<div class="mars3d-camera-content">
                  <img class="mars3d-camera-img" src="${require("../assets/img/icon/camera.svg").default}" >
                </div>
                <div class="mars3d-camera-line" ></div>
                <div class="mars3d-camera-point"></div>`,
          offsetX: -16,
          distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 100000)
        },
        // popup: `<video src='http://data.mars3d.cn/file/video/lukou.mp4' controls autoplay style="width: 300px;" ></video>`,
        popup: `<video src='${pointObj.videoUrl}' controls autoplay style="width: 300px;" ></video>`,
        popupOptions: {
          offsetY: -170, // 显示Popup的偏移值,是DivGraphic本身的像素高度值
          template: `<div class="marsBlackPanel animation-spaceInDown">
                      <div class="marsBlackPanel-text">{content}</div>
                      <span style="color: white;" class="mars3d-popup-close-button closeButton" >×</span>
                    </div>`,
          horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
          verticalOrigin: Cesium.VerticalOrigin.CENTER
        }
      })
      graphicLayer.addGraphic(graphicImg)
    })
  }

}
function animationVersion() {
  console.clear()
  console.log('\n'.repeat('1000'));
  window.requestAnimationFrame(animationVersion);
}
export { Criska_Cesium }