Skip to content

场景数据解析

场景基本信息(basicInfo)

查询场景基础信息

返回信息同提交一致basicInfo,可以进行默认视角定位等操作。

场景图层信息(scene)

查询场景图层信息,参数 jsonType 为 1。

返回信息同提交一致scene

数据加载

request.js

javascript
import axios from 'axios'
import useUserStore from '@/stores/user'
import qs from 'qs'
import { ElMessage } from 'element-plus'
const service = axios.create({
  baseURL: import.meta.env.VITE_BASE_API,
  timeout: 60000000,
  paramsSerializer: {
    serialize: (params) => {
      return qs.stringify(params, { arrayFormat: 'repeat' })
    }
  }
})

// 请求拦截器
service.interceptors.request.use(
  (config) => {
    const userStore = useUserStore()
    // 统一增加Authorization请求头, skipToken 跳过增加token
    if (userStore.getToken && !config.headers?.skipToken) {
      config.headers['Authorization'] = `Bearer ${userStore.getToken}`
    }
    return config // 必须返回配置
  },
  (error) => {
    return Promise.reject(error)
  }
)

// 响应拦截器
service.interceptors.response.use(
  (response) => {
    return response.data
  },
  (error) => {
    ElMessage({
      message: error,
      type: 'error',
      grouping: true
    })
    return Promise.reject(error)
  }
)

export { service }

api:scene.ts

ts
import { service as request } from '@/utils/request'

/**
 * @description:设置中科星图、天地图 等公共参数
 * @return {*}
 */
export const getCommonParameter = (param) => {
  return request({
    url: `/admin/param/info/${param}`,
    method: 'GET'
  })
}
/**
 * @description:获取授权代码
 * @param {*} params {account: 账号,password:密码}
 * @return {*}
 */
export const getSceneInfoApi = (params) => {
  return request({
    url: 'admin/api/scene/v1.0.0/getSceneInfo',
    method: 'GET',
    params
  })
}
/**
 * @description: 场景图层数据、标绘、分屏、水面等
 * @param {*} params
 * @param {*} params {sceneId: 场景id,jsonType:1场景,2点线面,3单体化,4压平、5水面,6裁剪,7飞行 数据,ROOTPATH、PAGEPATH:当前页面的location.origin}
 * @return {*}
 */
export const getSceneJsonInfoApi = (params) => {
  return request({
    url: 'admin/api/scene/v1.0.0/getSceneJsonInfo',
    method: 'GET',
    params
  })
}

/**
 * @description: 获取矢量数据样式
 * @param {*} params
 * @param {*} params {materialid: 矢量数据库id}
 * @return {*}
 */
export const getShpStyleApi = (params) => {
  return request({
    url: '/admin/tx/shp/getStyle',
    method: 'GET',
    params
  })
}

各种数据加载(materialLoader.ts)

ts
import { getCommonParameter } from '../api/commonApi'
import { getShpStyleApi } from '../api/scene'
// 在线影像
export const loadOnlineImagery = async (imageryData) => {
  const apiUrl = import.meta.env.VITE_BASE_API
  let lrcPath = ''
  switch (imageryData.name.title) {
    case 'zkxt-img':
      lrcPath = `${apiUrl}/admin/tx/preview/v1.0.0/geovis/zkxt-img.lrc`
      break
    case 'zkxt-img-annotation':
      lrcPath = `${apiUrl}/admin/tx/preview/v1.0.0/geovis/zkxt-img-annotation.lrc`
      break
    case 'skyLand':
      lrcPath = `${apiUrl}/admin/tx/preview/v1.0.0/tdt/tdtLayer.lrc`
      break
    case 'skyLandImage':
      lrcPath = `${apiUrl}/admin/tx/preview/v1.0.0/tdt/tdtMarker.lrc`
      break
    case 'tdtrender':
      lrcPath = `${apiUrl}/admin/tx/preview/v1.0.0/tdt/tdtrender.lrc`
      break
    case 'tdtvector':
      lrcPath = `${apiUrl}/admin/tx/preview/v1.0.0/tdt/tdtvector.lrc`
      break
  }

  try {
    const imageryProvider = await LSGlobe.LSImageryProvider.fromUrl(lrcPath)
    imageryProvider.name = imageryData.name
    const imageryLayer =
      viewer.imageryLayers.addImageryProvider(imageryProvider)
    imageryLayer.show = imageryData.show
  } catch (error) {
    console.error(`Error loading imagery: ${error}`)
  }
}

// 系统影像、CAD
export const loadSelfImagery = async (imageryData) => {
  const apiUrl = import.meta.env.VITE_BASE_API
  var imageryLayers = viewer.imageryLayers
  var sMaterialUrl =
    apiUrl +
    '/admin/tx/preview/data/index/' +
    imageryData.name.folderId +
    '?pageorigin=' +
    import.meta.env.VITE_BASE_SERVERORIGIN
  var oImageryParms = {
    url: sMaterialUrl
  }

  try {
    var imageryProvider = await LSGlobe.LSImageryProvider.fromUrl(
      oImageryParms.url,
      oImageryParms
    )
    imageryProvider.name = imageryData.name
    var oLayer = imageryLayers.addImageryProvider(imageryProvider)
    oLayer.show = imageryData.show

    oLayer.alpha = imageryData.name.alpha
    // 定位
    // var rect = imageryProvider.rectangle
    // viewer.camera.flyTo({
    //   destination: rect,
    //   duration: 0
    // })
  } catch (error) {
    console.error(`Error loading imagery: ${error}`)
  }
}

// 大矢量
// 默认样式
var oStyle = {
  styletyle: 'default',
  color: 'rgba(33, 150, 243,0.3)',
  lineType: LSGlobe.VectorTileLineType.SOLID,
  lineWidth: 1,
  outline: true,
  outlineColor: '#2196F3',
  icon: import.meta.env.VITE_BASE_API + '/scene/images/GEMarker/red-circle.png',
  textField: 'NAME',
  font: "normal 16px 'Microsoft YaHei'"
}
// 默认选中样式
var oSelectedStyle = {
  color: 'rgba(255, 87, 34,0.1)',
  lineType: LSGlobe.VectorTileLineType.SOLID,
  lineWidth: 1,
  outline: true,
  outlineColor: '#FF5722',
  icon: import.meta.env.VITE_BASE_API + '/scene/images/GEMarker/red-circle.png',
  textField: 'NAME',
  font: "normal 16px 'Microsoft YaHei'"
}
export const loadBigShp = async (imageryData, callback?) => {
  const apiUrl = import.meta.env.VITE_BASE_API

  var sMaterialUrl =
    apiUrl +
    '/admin/tx/preview/data/index/' +
    imageryData.name.folderId +
    '?pageorigin=' +
    import.meta.env.VITE_BASE_SERVERORIGIN

  var oVectorParms = {
    url: sMaterialUrl,
    viewer: viewer
  }

  try {
    var imageryProvider = await LSGlobe.VectorTileProvider.fromUrl(
      oVectorParms.url,
      oVectorParms
    )

    imageryProvider.name = imageryData.name

    // 可以获取矢量的一些信息
    var oLayer = viewer.imageryLayers.addImageryProvider(imageryProvider)

    oLayer.maximumLevel = 30

    oLayer.show = imageryData.show

    getShpStyleApi({
      folderId: imageryData.name.folderId,
      sceneId: import.meta.env.VITE_APP_SCENEID
    }).then((result) => {
      var styles = LSGlobe.VectorTileStyleCollection.fromJson(
        Object.assign(oStyle, JSON.parse(result.data.styleJson))
      )
      imageryProvider.styles = styles

      var oSelectedStylePortion = Object.assign({}, oSelectedStyle)
      if (JSON.parse(result.data.styleJson).styles[0].textField) {
        oSelectedStylePortion.color = 'rgba(255, 0, 0,1)'
        oSelectedStylePortion.outlineColor = '#000000'
        oSelectedStylePortion.textField = JSON.parse(
          result.data.styleJson
        ).styles[0].textField
      }
      imageryProvider.selectedStyles = new LSGlobe.VectorTileStyleCollection([
        new LSGlobe.VectorTileStyle(oSelectedStylePortion)
      ])
    })

    callback && callback(oLayer)
  } catch (error) {
    console.error(`Error loading vector tiles: ${error}`)
  }
}

// 在线地形
export const loadOnlineTerrain = async (terrainData) => {
  if (terrainData.name == 'nintyTdtTerrain') {
    var terrainLayers = viewer.terrainLayers
    // 服务域名
    var tdtUrl = 'https://t{s}.tianditu.gov.cn/'
    // 服务负载子域
    var subdomains = ['0', '1', '2', '3', '4', '5', '6', '7']
    var terrainUrls = new Array()
    const paramRes = await getCommonParameter('TDT_KEY')
    const stdtkey = paramRes.data.publicValue
    for (var i = 0; i < subdomains.length; i++) {
      var url =
        tdtUrl.replace('{s}', subdomains[i]) + 'mapservice/swdx?tk=' + stdtkey
      terrainUrls.push(url)
    }
    var terrainLayer = new LSGlobe.TDTTerrainProvider({
      urls: terrainUrls
    })
    terrainLayer.name = 'nintyTdtTerrain'
    var oLayer = terrainLayers.addTerrainProvider(terrainLayer)
    oLayer.show = terrainData.show
  } else if (terrainData.name === 'zkxtTerrain') {
    try {
      const paramRes = await getCommonParameter('GEO_VIS_KEY')
      const code = paramRes.data.publicValue
      const terrainProvider = await LSGlobe.CesiumTerrainProvider.fromUrl(
        `https://tiles.geovisearth.com/base/v1/terrain/?token=${code}`
      )
      var oLayer = viewer.terrainLayers.addTerrainProvider(terrainProvider)
      terrainProvider.name = 'zkxtTerrain'

      oLayer.show = terrainData.show
    } catch (error) {
      console.log(error)
    }
  }
}

// 系统地形
export const loadSelfTerrain = async (terrainData) => {
  const apiUrl = import.meta.env.VITE_BASE_API

  var sMaterialUrl =
    apiUrl +
    '/admin/tx/preview/data/index/' +
    terrainData.name.folderId +
    '?pageorigin=' +
    import.meta.env.VITE_BASE_SERVERORIGIN

  var terrainLayers = viewer.terrainLayers
  var oTerrainParms = {
    url: sMaterialUrl
  }

  try {
    var terrainLayer = await LSGlobe.LSTerrainProvider.fromUrl(
      oTerrainParms.url,
      oTerrainParms
    )
    terrainLayer.name = terrainData.name
    var oLayer = terrainLayers.addTerrainProvider(terrainLayer)

    oLayer.show = terrainData.show

    //飞到地形数据的位置
    // var rect = terrainLayer._rectangle
    // viewer.camera.flyTo({
    //   destination: rect
    // })
  } catch (error) {
    console.error(`Error loading Terrain: ${error}`)
  }
}

// 加载3dtiles
export const load3DTiles = async (tilesData) => {
  const apiUrl = import.meta.env.VITE_BASE_API
  var sMaterialUrl =
    apiUrl +
    '/admin/tx/preview/data/index/' +
    tilesData.name.folderId +
    '?pageorigin=' +
    import.meta.env.VITE_BASE_SERVERORIGIN

  var tileset
  var o3DTilesOption = {
    url: sMaterialUrl,
    modelMatrix: tilesData.modelMatrix,
    transform: tilesData.transform,
    skipLevelOfDetail: true,
    cacheBytes: 1024 * 1024 * 1024 * 1,
    dynamicScreenSpaceError: true
  }
  o3DTilesOption.maximumScreenSpaceError =
    tilesData.name.extraJson.maximumScreenSpaceError
  try {
    tileset = await LSGlobe.Cesium3DTileset.fromUrl(
      o3DTilesOption.url,
      o3DTilesOption
    )

    tileset.name = tilesData.name
    tileset.id = tilesData.name.id
    viewer.scene.primitives.add(tileset)

    if (4 == tileset.name.bizType) {
      tileset.style = new LSGlobe.Cesium3DTileStyle({
        pointSize: tileset.name.pointSize || 1, // 将点大小设置为 5.0,可根据需要调整
        ...tileset.name.style
      })
    } else if (5 == tileset.name.bizType) {
      tileset.style = new LSGlobe.Cesium3DTileStyle({
        color:
          "color('rgba(255,255,255," + (tileset.name.transparency ?? 1) + ")')"
      })
    }

    tileset.show = tilesData.show
  } catch (error) {
    console.error(`Error loading LSPageLOD: ${error}`)
  }
}

// 加载glb/gltf
export const loadGltf = async (gltfData) => {
  if (typeof gltfData.name !== 'object') {
    // 用来过滤模型编辑插件Ring.glft
    return
  }
  const apiUrl = import.meta.env.VITE_BASE_API
  const sMaterialUrl =
    apiUrl +
    '/admin/tx/preview/data/index/' +
    gltfData.name.folderId +
    '?token=' +
    localStorage.getItem('token')

  const getHeadingAndScale = () => {
    const { scale } = gltfData
    return { scale }
  }
  const { scale } = getHeadingAndScale()
  const modelMatrix = gltfData.modelMatrix

  try {
    const gltf = await LSGlobe.Model.fromGltfAsync({
      url: sMaterialUrl,
      modelMatrix: modelMatrix,
      scale,
      gltfData
    })
    const model = viewer.scene.primitives.add(gltf)
    model.readyEvent.addEventListener(() => {
      model.activeAnimations.addAll({
        loop: LSGlobe.ModelAnimationLoop.REPEAT,
        multiplier: 1
      })
      // debugger
      //添加到全局对象里方便使用
      model.name = gltfData.name
    })
  } catch (error) {
    console.error(`加载gltf错误: ${error}`)
  }
}

// 加载kml
export const loadKML = async (kmlData) => {
  const apiUrl = import.meta.env.VITE_BASE_API
  var options = {
    camera: viewer.scene.camera,
    canvas: viewer.scene.canvas,
    clampToGround: true,
    attachPolygon: true
  }
  var sMaterialUrl =
    apiUrl +
    '/admin/tx/preview/data/index/' +
    kmlData.name.id +
    '?token=' +
    localStorage.getItem('token')
  var promise = LSGlobe.KmlDataSource.load(sMaterialUrl, options)
  promise
    .then(function (dataSource) {
      dataSource.name = kmlData.name
      viewer.dataSources.add(dataSource)
      dataSource.show = kmlData.name.show
    })
    .catch(function (error) {
      console.error(error)
    })
}

数据分类加载、定位、删除(sceneUtils.ts)

ts
import {
  loadOnlineImagery,
  loadSelfImagery,
  loadBigShp,
  loadOnlineTerrain,
  loadSelfTerrain,
  load3DTiles,
  loadGltf,
  loadKML
} from './materialLoader'
import { flyToCameraStateByCartesian3 } from '@/components/txearth/utils'
export const loadSceneMaterial = (sceneData) => {
  console.log('图层数据--树结构', sceneData.Tree)
  console.log('图层数据--数据', sceneData.scene)
  console.log('图层数据--场景更新时间', sceneData.asset.date)
  viewer.clock.currentTime = new LSGlobe.JulianDate.fromDate(
    new Date(sceneData.asset.date)
  )
  console.log(`图层数据--数据>>>>>>
    datasources:kml、标绘;
    imageryLayers:影像类、shp、cad;
    layers:倾斜、小品、bim、点云;
    terrainLayers:地形;
             `)

  loadImageryLayers(sceneData.scene.imageryLayers)
  loadTerrainLayers(sceneData.scene.terrainLayers)
  loadLayers(sceneData.scene.layers)
  loadDatasources(sceneData.scene.datasources)
}

// 影像类、shp、cad;
var onlineImagery = [
  'zkxt-img',
  'zkxt-img-annotation',
  'starLand',
  'skyLand',
  'skyLandImage',
  'arcgis',
  'tdtrender',
  'tdtvector'
]
export const loadImageryLayers = (imageryLayersData) => {
  for (let index = 0; index < imageryLayersData.length; index++) {
    const element = imageryLayersData[index]
    if (onlineImagery.includes(element.name?.title)) {
      loadOnlineImagery(element)
    } else if (element.type == 'VectorTileProvider') {
      loadBigShp(element, () => {})
    } else {
      loadSelfImagery(element)
    }
  }
}

// 地形;
// 在线地形;
var onlineTerrain = ['nintyTdtTerrain', 'zkxtTerrain']
export const loadTerrainLayers = async (terrainLayers) => {
  for (let index = 0; index < terrainLayers.length; index++) {
    const element = terrainLayers[index]
    if (onlineTerrain.indexOf(element.name) > -1) {
      //在线地图
      await loadOnlineTerrain(element)
    } else {
      await loadSelfTerrain(element)
    }
  }
}

// 倾斜、小品、bim、点云;
export const loadLayers = (layers) => {
  for (let index = 0; index < layers.length; index++) {
    const element = layers[index]
    if (element.type == 'Cesium3DTileset') {
      load3DTiles(element)
    } else if (['GLTF', 'Model'].includes(element.type)) {
      loadGltf(element)
    }
  }
}

// datasources
export const loadDatasources = (datasources) => {
  for (let index = 0; index < datasources.length; index++) {
    const element = datasources[index]
    if ('kmlDataSource' == element.type || 'KmlDataSource' == element.type) {
      loadKML(element)
    }
  }
}

// 加载点线面标绘
export const loadDrawLayers = (draw) => {
  if (draw.features.length > 0) {
    var promise = LSGlobe.GeoJsonDataSource.load(draw, {
      // clampToGround : true,
      // attachPolygon : true
    })
    promise
      .then(function (dataSource) {
        viewer.dataSources.remove(getDatasource('drawDataSource'))
        dataSource.name = 'drawDataSource'
        dataSource._sourceUri = ''
        viewer.dataSources.add(dataSource)
      })
      .catch(function (error) {
        console.log(error)
      })
  }
}

// 加载单体化
export const loadMonomerLayer = (monomer) => {
  if (monomer.features.length > 0) {
    var promise = LSGlobe.GeoJsonDataSource.load(monomer, {
      // clampToGround : true,
      // attachPolygon : true
    })
    promise
      .then(function (dataSource) {
        viewer.dataSources.remove(getDatasource('monomerDataSource'))
        dataSource.name = 'monomerDataSource'
        dataSource._sourceUri = ''
        viewer.dataSources.add(dataSource)
      })
      .catch(function (error) {
        console.log(error)
      })
  }
}

// 加载压平
export const loadPushLayer = (push) => {
  if (push.features.length > 0) {
    var promise = LSGlobe.GeoJsonDataSource.load(push, {
      // clampToGround : true,
      // attachPolygon : true
    })
    promise
      .then(async function (dataSource) {
        viewer.dataSources.remove(getDatasource('pushDataSource'))
        dataSource.name = 'pushDataSource'
        dataSource._sourceUri = ''
        await viewer.dataSources.add(dataSource)

        renderPushLayer()
      })
      .catch(function (error) {
        console.error(error)
      })
  }
}

// 渲染压平
export const renderPushLayer = () => {
  // 清除所有倾斜上面的压平
  for (var i = 0; i < viewer.scene.primitives.length; i++) {
    var oTileSet = viewer.scene.primitives.get(i)
    // 倾斜
    if (oTileSet.name && oTileSet.name.bizType == 3) {
      try {
        if (oTileSet.flattenRegions) {
          oTileSet.flattenRegions.removeAll()
        }
      } catch (e) {
        console.error(e)
      }
    }
  }

  const pushDataSource = getDatasource('pushDataSource')
  var aPushEntities = pushDataSource ? pushDataSource.entities.values : []

  for (var i = 0; i < aPushEntities.length; i++) {
    // 降低透明度(entity只是存储数据用不用显示出来)
    aPushEntities[i].polygon.material = LSGlobe.Color.fromRandom({
      red: aPushEntities[i].polygon.material.color._value.red,
      green: aPushEntities[i].polygon.material.color._value.green,
      blue: aPushEntities[i].polygon.material.color._value.blue,
      alpha: 0.01
    })

    if (aPushEntities[i].show) {
      for (var j = 0; j < viewer.scene.primitives.length; j++) {
        var oTileSet = viewer.scene.primitives.get(j)
        if (oTileSet.name && oTileSet.name.bizType == 3) {
          var polygon = new LSGlobe.PolygonHierarchy(
            aPushEntities[i].polygon.hierarchy.getValue().positions
          )
          var flattenRegion = new LSGlobe.FlattenRegion({
            polygon: polygon,
            show: true
          })
          try {
            if (oTileSet.flattenRegions) {
              oTileSet.flattenRegions.add(flattenRegion)
            } else {
              const flattenRegionCollection =
                new LSGlobe.FlattenRegionCollection({
                  flattenRegions: [flattenRegion], // 传入的坑对象数组
                  enabled: true, // 是否启用,设为false不显示;默认值为true。
                  numberOfCascades: 4, // 级联数量,设为1或4:1——性能高;4——精度高;默认值为4。
                  // 距离相机的最远作用距离,超过此距离后模型没有效果。距离越大精度越低,默认值为5000,最大距离限制为20000。
                  maximumDistance: 8000,
                  // 使用的映射纹理尺寸。数值越大性能越低占用显存越高但精度高;默认值为2048。
                  size: 2048,
                  // 可见映射范围的延伸长度,降低不在视景体内的顶点对压平效果的影响。值越大影响越小,但是精度越低。
                  visibleOverlayExtension: 10,
                  // 是否对被压物体进行压平测试。压平测试可以减少被压对象的数量,从而提升渲染性能;但压平测试需要被压物体与每个压平面进行相交判断,在压平面较多时此测试本身对性能影响较大。
                  flattenTest: false
                })
              oTileSet.flattenRegions = flattenRegionCollection
            }
          } catch (e) {
            console.error(e)
          }
        }
      }
    }
  }
}

// 加载水面
export const loadWaterLayer = (water) => {
  if (water.features.length > 0) {
    var promise = LSGlobe.GeoJsonDataSource.load(water, {
      // clampToGround : true,
      // attachPolygon : true
    })
    promise
      .then(async function (dataSource) {
        viewer.dataSources.remove(getDatasource('waterDataSource'))
        dataSource.name = 'waterDataSource'
        dataSource._sourceUri = ''
        await viewer.dataSources.add(dataSource)

        renderWaterLayer()
      })
      .catch(function (error) {
        console.error(error)
      })
  }
}
// 渲染水面
export const renderWaterLayer = () => {
  if (!viewer.scene.waterCollection) {
    viewer.scene.waterCollection = {}
    viewer.scene.waterCollection.water = []
  }

  // 此处是从数据源中获取数据,当然也可以直接解析数据源的坐标
  const waterDataSource = getDatasource('waterDataSource')
  var entities = waterDataSource ? waterDataSource.entities.values : []
  for (var i = 0; i < entities.length; i++) {
    var entity = entities[i]
    var WaterId = entity.id
    var WaterName = entity.name
    if (entity.polygon) {
      // entity.polygon.perPositionHeight = false;
      entity.polygon.outline = false
      //贴模型
      // entity.polygon.classificationType = LSGlobe.ClassificationType.BOTH;

      var wateritem = new LSGlobe.Water(viewer.scene)
      wateritem.waterPolygon = new LSGlobe.PolygonGeometry({
        polygonHierarchy: new LSGlobe.PolygonHierarchy(
          entity.polygon.hierarchy.getValue().positions
        ),
        perPositionHeight: true
      })
      var oProperties = entity.properties.getValue()
      wateritem.id = WaterId
      wateritem.waveWidth = oProperties.waveWidth
      wateritem.flowDirection = oProperties.flowDirection
      wateritem.flowSpeed = oProperties.flowSpeed
      wateritem._waterColor = LSGlobe.Color.fromCssColorString(
        oProperties._waterColor
      ).withAlpha(oProperties.alpha / 100)
      wateritem.name = WaterName
      wateritem.des = oProperties.des
      wateritem.alpha = oProperties.alpha
      wateritem.isVisible = entity.show
      viewer.scene.waterCollection.water.push(wateritem)
    }
  }
}

// 加载裁剪
export const loadCutLayer = (cut) => {
  if (cut.features.length > 0) {
    var promise = LSGlobe.GeoJsonDataSource.load(cut, {
      // clampToGround : true,
      // attachPolygon : true
    })
    promise
      .then(async function (dataSource) {
        viewer.dataSources.remove(getDatasource('cutDataSource'))
        dataSource.name = 'cutDataSource'
        dataSource._sourceUri = ''
        await viewer.dataSources.add(dataSource)
        renderCutLayer()
      })
      .catch(function (error) {
        console.error(error)
      })
  }
}

// 渲染裁剪
export const renderCutLayer = () => {
  // 此处是从数据源中获取数据,当然也可以直接解析数据源的坐标
  const cutDataSource = getDatasource('cutDataSource')
  var entities = cutDataSource.entities._entities._array
  for (var i = 0; i < entities.length; i++) {
    var entity = entities[i]
    var oProperties = entity.properties.getValue()
    var CutId = entity.id
    var CutName = entity.name

    if (entity.polygon && entity.show) {
      entity.polygon.outline = false
      var oPrimitive = getPrimitive(oProperties.tilesetId)
      if (oPrimitive) {
        if (!oPrimitive.pits) {
          const pitCollection = new LSGlobe.PitCollection({
            pits: [], // 传入的坑对象数组
            enabled: true, // 是否启用,设为false不显示;默认值为true。
            numberOfCascades: 4, // 级联数量,设为1或4:1——性能高;4——精度高;默认值为4。
            // 距离相机的最远作用距离,超过此距离后模型没有效果。距离越大精度越低,默认值为5000,最大距离限制为20000。
            maximumDistance: 8000,
            // 使用的映射纹理尺寸。数值越大性能越低占用显存越高但精度高;默认值为2048。
            size: 2048
          })
          oPrimitive.pits = pitCollection
        }
        var cutPolygonHierarchy = new LSGlobe.PolygonHierarchy(
          entity.polygon.hierarchy._value.positions
        )
        var pit = new LSGlobe.Pit({
          polygon: cutPolygonHierarchy,
          show: true
        })

        pit.name = CutName
        pit.id = CutId

        if ('clip' == oProperties.cutType) {
          // 包含模式开发中
          oPrimitive.addClipPolygon(cutPolygon)
        } else {
          oPrimitive.pits.add(pit)
        }
      }
    }
  }
}

// 设置图层显示状态
export const setLayerDisplayState = (item, show) => {
  console.log(item, show)
  debugger
  let layer
  switch (item.type) {
    // 1影像/6部分矢量
    case 1:
    case 6:
      if (
        item.type == 1 ||
        item.secondType == 'shp' ||
        item.secondType == 'lcad' ||
        item.secondType == 'dwg' ||
        item.secondType == 'dxf'
      ) {
        layer = getImageryLayer(item.id)
        layer.show = show
      } else {
        // dataSource
        const dataSource = getDatasource(item.id)
        dataSource.show = show
      }

      break
    // 2地形
    case 2:
      layer = getTerrainLayer(item.id)
      layer.show = show
      break
    // 3倾斜、4.点云、5.bim
    case 3:
    case 4:
    case 5:
    case 8:
      layer = getPrimitive(item.id)
      layer.show = show
      break
    case 'draw':
      const targetDataSource = getDatasource('drawDataSource')
      targetDataSource.entities.getById(item.id).show = show
      break
    case 'monomer':
      const monomerDataSource = getDatasource('monomerDataSource')
      monomerDataSource.entities.getById(item.id).show = show
      break
    case 'pushpanel':
      const pushDataSource = getDatasource('pushDataSource')
      pushDataSource.entities.getById(item.id).show = show
      renderPushLayer()
      break
    case 'water':
      // 此处只是同步修改数据存储的状态
      const waterDataSource = getDatasource('waterDataSource')
      waterDataSource.entities.getById(item.id).show = show
      // 同步修改水面渲染状态
      getWater(item.id).isVisible = show
      break
  }
}
// 定位单体化、压平、水面等
export const flyToEntity = (entity) => {
  const flyToBoundingSphere_draw = (positions) => {
    const boundingSphere = LSGlobe.BoundingSphere.fromPoints(positions)
    viewer.camera.flyToBoundingSphere(boundingSphere, {
      offset: new LSGlobe.HeadingPitchRange(0, -LSGlobe.Math.PI_OVER_TWO, 0)
    })
  }
  if (entity) {
    if (entity.polygon) {
      var positions = entity.polygon.hierarchy.getValue().positions
      flyToBoundingSphere_draw(positions)
    } else if (entity.polyline) {
      var positions = entity.polyline.positions.getValue()
      flyToBoundingSphere_draw(positions)
    } else {
      viewer.flyTo(entity, {
        offset: new LSGlobe.HeadingPitchRange(0, -LSGlobe.Math.PI_OVER_TWO, 0)
      })
    }
  }
}

// 定位
export const locationLayer = (item) => {
  let layer
  switch (item.type) {
    case 1:
    case 6:
      if (
        item.type == 1 ||
        item.secondType == 'shp' ||
        item.secondType == 'lcad' ||
        item.secondType == 'dwg' ||
        item.secondType == 'dxf'
      ) {
        layer = getImageryLayer(item.id)
        var rect = layer._imageryProvider.rectangle
        viewer.camera.flyTo({
          destination: rect,
          duration: 1
        })
      } else {
        debugger
        const dataSource = getDatasource(item.id)
        viewer.flyTo(dataSource)
      }

      break
    case 2:
      layer = getTerrainLayer(item.id)
      var rect = layer.terrainProvider.rectangle
      viewer.camera.flyTo({
        destination: rect,
        duration: 1
      })
      break
    case 3:
    case 4:
    case 5:
      layer = getPrimitive(item.id)
      //(3dtiles)
      const boundingSphere = layer.boundingSphere
      viewer.camera.viewBoundingSphere(
        boundingSphere,
        new LSGlobe.HeadingPitchRange(0, -2.0, 0)
      )
      viewer.camera.lookAtTransform(LSGlobe.Matrix4.IDENTITY)
      break
    case 8:
      layer = getPrimitive(item.id)
      const heading = LSGlobe.Math.toRadians(0.0)
      const pitch = LSGlobe.Math.toRadians(-90.0)
      const range = layer.boundingSphere.radius * 2
      const hpr = new LSGlobe.HeadingPitchRange(heading, pitch, range)
      let flyOpts = { offset: hpr }
      viewer.camera.flyToBoundingSphere(layer.boundingSphere, flyOpts)
      break
    case 'draw':
      const targetDataSource = getDatasource('drawDataSource')
      const entity = targetDataSource.entities.getById(item.id)
      var oPos = entity.properties.position._value
      var oUp = entity.properties.up._value
      var oDir = entity.properties.direction._value
      flyToCameraStateByCartesian3({
        destination: oPos,
        up: oUp,
        direction: oDir
      })
      break
    case 'monomer':
      const monomerDataSource = getDatasource('monomerDataSource')
      const monomerEntity = monomerDataSource.entities.getById(item.id)
      flyToEntity(monomerEntity)
      break
    case 'pushpanel':
      const pushDataSource = getDatasource('pushDataSource')
      const pushpanelEntity = pushDataSource.entities.getById(item.id)
      flyToEntity(pushpanelEntity)
      break
    case 'water':
      // 方法1
      // const waterDataSource = getDatasource('waterDataSource');
      // const waterEntity = waterDataSource.entities.getById(item.id);
      // flyToEntity(waterEntity);

      // 方法2
      const water = getWater(item.id)
      viewer.camera.flyToBoundingSphere(water._waterGeometry.boundingSphere, {
        offset: new LSGlobe.HeadingPitchRange(0, -LSGlobe.Math.PI_OVER_TWO, 0)
      })
      break
  }
}

// 删除图层
export const removeLayer = (item) => {
  let layer
  switch (item.type) {
    case 1:
    case 6:
      if (
        item.type == 1 ||
        item.secondType == 'shp' ||
        item.secondType == 'lcad' ||
        item.secondType == 'dwg' ||
        item.secondType == 'dxf'
      ) {
        layer = getImageryLayer(item.id)
        viewer.imageryLayers.remove(layer)
      } else {
        const dataSource = getDatasource(item.id)
        viewer.dataSources.remove(dataSource)
      }

      break
    case 2:
      layer = getTerrainLayer(item.id)
      viewer.terrainLayers.remove(layer)
      break
    case 3:
    case 4:
    case 5:
    case 8:
      layer = getPrimitive(item.id)
      //(3dtiles)
      viewer.scene.primitives.remove(layer)
      break
    case 'draw':
      const targetDataSource = getDatasource('drawDataSource')
      targetDataSource.entities.removeById(item.id)
      break
    case 'monomer':
      const monomerDataSource = getDatasource('monomerDataSource')
      monomerDataSource.entities.removeById(item.id)
      break
    case 'pushpanel':
      const pushDataSource = getDatasource('pushDataSource')
      pushDataSource.entities.removeById(item.id)
      renderPushLayer()
      break
    case 'water':
      // 删除存储
      const waterDataSource = getDatasource('waterDataSource')
      waterDataSource.entities.removeById(item.id)
      // 删除渲染
      getWater(item.id).destroy()
      break
  }
}

//获取imagerylayer
export const getImageryLayer = (name) => {
  const layer = viewer.imageryLayers._layers.find(
    (layer) =>
      layer.imageryProvider.name &&
      (layer.imageryProvider.name.title === name ||
        layer.imageryProvider.name.id == name)
  )
  return layer
}

// 获取terrainlayer
export const getTerrainLayer = (name) => {
  const layer = viewer.terrainLayers._layers.find(
    (layer) =>
      layer.terrainProvider.name &&
      (layer.terrainProvider.name === name ||
        layer.terrainProvider.name.id == name)
  )
  return layer
}

// 获取primitive
export const getPrimitive = (name) => {
  const layer = viewer.scene.primitives._primitives.find(
    (primitive) =>
      primitive.name && (primitive.name === name || primitive.name.id == name)
  )
  return layer
}

//获取Datasource
export const getDatasource = (datasourceid) => {
  const targetDataSource = viewer.dataSources._dataSources.find(
    (datasource) =>
      datasource.name &&
      (datasource.name == datasourceid || datasource.name.id == datasourceid)
  )
  return targetDataSource
}

// 获取水面
export const getWater = (waterid) => {
  const targetWater = viewer.scene.waterCollection.water.find(
    (water) => water.id && water.id == waterid
  )
  return targetWater
}

Released under the MIT License.