Mars3D使用过程遇到的问题记录【持续更新】

需要标注线面的角度heading

2022年6月23日

heading计算方式:

https://turfjs.fenxianglu.cn/

计算两点之间的角度

直接F12在控制台可以计算

eg:

function c(a,b){
    console.log( [(b[0]+a[0])/2,(a[1]+b[1])/2,(b[2]+a[2])/2])

    var point1 = turf.point([a[0],a[1]]);
    var point2 = turf.point([b[0],b[1]]);
    var bearing = turf.bearing(point1, point2);
    console.log(bearing)
}

加载gltf模型,模型是透明的,需要改为不透明

2022年6月23日

用文本编辑器打开.gltf,把里面的"alphaMode":"BLEND"改成"alphaMode":"OPAQUE"

模型旋转之后,标注的点也旋转的计算方式

2022年6月24日

Q:项目需要将模型沿Z 轴旋转(模型之前设置的z:1 后来改为0.65,相当于旋转了-0.35度),之前标注的点因此错位。需要将之前标注的线段、点等也旋转-0.35度。

A:利用turf.js中的【旋转】transformRotate

// 原来标注的线段
var poly = turf.lineString([[75.87926657839982, 39.20165857293024], [75.8792225335169, 39.2016347276248]]);

// pivot:旋转的质点(模型的中心点)
var options = {pivot: [75.879766,39.201592]};

// -0.35为旋转角度,应与模型旋转角度相同
var line = turf.transformRotate(poly, -0.35, options);

console.log(line.geometry.coordinates)

计算两点间的中点

2022年6月24日

function min_point(b,c){
    console.log( [(b[0]+c[0])/2,(c[1]+b[1])/2,(b[2]+c[2])/2])
}

计算对称点(已知左侧跟中点,右侧对称点)

2022年6月24日

function other_point(b,c){
    console.log( [(2*b[0]-c[0]),(2*b[1]-c[1]),(2*b[2]-c[2])])
}

视线离得越远设置Graphic越小

 scaleByDistance: new schinta3d.Cesium.NearFarScalar(100, 1,500, 0),100距离的时候是正常展示,距离超过500就隐藏了

const graphic = new schinta3d.graphic.DivGraphic({

      position: opt.position,

      style: DefaultOptions.getLabelStyleOptions({

        html: HtmlBuilder[`get${opt.type}LabelHtml`](opt),

        scaleByDistance: new schinta3d.Cesium.NearFarScalar(100, 1,500, 0),

        distanceDisplayCondition: new schinta3d.Cesium.DistanceDisplayCondition(0, far)

      }),

      attr: opt.attr || {}

    })

模拟水闸放水时的粒子效果(项目中引入ParticleSystem.js

2022年8月5日17:22:44

 /**
   * 添加水柱(粒子效果)(与闸门无关的粒子)
   * @param {number[]} waterGate 出水点对象
   * @param {number} gravity 重力因子
   * @param {number[]} speed 发射的速度(越大越远)
   * @param {number} heading 方向
   * @param {number} pitch 俯仰角
   * @returns {*[]}
   */
  addWaterParticle(waterParticle) {
    if(!waterParticle){
      return
    }
    let graphicLayer = this.mapInstance.getLayer('water_particle')
    if (graphicLayer){
      graphicLayer.clear(true)
    }else{
      graphicLayer = new schinta3d.layer.GraphicLayer({name: 'water_particle'})
      this.addLayer(graphicLayer)
    }
    for (let i = 0, len = waterParticle.length; i < len; i++) {
      const {name,position,gravity=-11,speed=19,heading=140,pitch=50,minSpeed,maxSpeed,maxDistance=160,emissionRate=500}=waterParticle[i];

      const particleSystem = new ParticleSystem({
        id:'WaterParticle_'+name,
        position, // 位置
        style: {
          image:require("../assets/img/smoke.png"),
          particleSize: 20,
          startColor: schinta3d.Cesium.Color.LIGHTCYAN.withAlpha(0.3), // 粒子出生时的颜色
          endColor: schinta3d.Cesium.Color.WHITE.withAlpha(0.0), // 当粒子死亡时的颜色
          startScale:2.0, // 粒子出生时的比例,相对于原始大小
          endScale: 6.0, // 粒子在死亡时的比例
          minimumParticleLife: 6.0, // 最小寿命时间(秒)
          maximumParticleLife: 7.0, // 最大寿命时间(秒)
          minimumSpeed: minSpeed, // 最小速度(米/秒)
          maximumSpeed: maxSpeed, // 最大速度(米/秒)
          emissionRate, // 每秒要发射的粒子数。
          lifetime: 1.0, // 粒子的生命周期为(以秒为单位)。
          heading, // 方向角
          pitch, // 俯仰角
        },

        gravity:gravity || -11,
        //target:target || new schinta3d.Cesium.Cartesian3(-0.25, -0.12, 0.1), // 粒子的方向
        maxDistance: maxDistance, //超出后不显示粒子效果
        maxHeight: 1500 // 超出该高度后不显示粒子效果
      })

   

调用:

/**
 * 粒子效果对象
 * @param {number[]} position 出水点
 * @param {number} gravity 重力因子
 * @param {number[]} speed 发射的速度(越大越远)
 * @param {number} heading 方向 (喷的左右方向)
 * @param {number} pitch 俯仰角 (喷的高低方向)
 * @returns {*[]}
 */

const obj={
      name: 'xxxxx闸口1#',
      position: [71.70923741915449, 39.1242423560064, 1418.562869989279],
      gravity: -1,
      minSpeed: 1,
      maxSpeed: 4,
      heading: 213,
      pitch: 95
    },
// 添加放水粒子效果
this.mapViewer.addWaterGate({oPosition,gravity:-11,tPosition,pointHight:5});

根据线段生成等宽的面

2022年7月21日20:36:07


//lineArr:线段数组; width:生成的线宽度
function calc(lineArr,width=5){

    // 平移到左边的点集合
    var left_point=[]
    // 平移到右边的点集合
    var right_point=[]
    for(var i=0;i<lineArr.length-1;i++){
        // 每两个点算一次
        var b=lineArr[i];
        var c=lineArr[i+1];
    
        var point1 = turf.point(b);
        var point2 = turf.point(c);
        // 两点间恒向角度
        var bearing = turf.rhumbBearing(point1, point2);

        // 与这个角度垂直的话就 加减90度

        var leftbearing = bearing +90;
        var rightbearing =bearing - 90;

        // 平移
        var translatedPolyleft = turf.transformTranslate(point1, width/2000, leftbearing);
        var translatedPolyright = turf.transformTranslate(point1, width/2000, rightbearing);

        left_point.push(translatedPolyleft.geometry.coordinates);
        right_point.unshift(translatedPolyright.geometry.coordinates);

    }

    // 合并 成面
    var newpolygn=[...left_point,...right_point]

    console.log(JSON.stringify(newpolygn))
    return newpolygn
}

// 调用

// 线段(沿着渠道底部中点)
var a=[[75.735847,39.138099,1378.8],[75.735871,39.138122,1378.8],[75.735898,39.138145,1378.8],[75.735918,39.138163,1379.3]]

calc(a,5)

支持高亮显示Entity、Primitive和3DTiles等   点击时的描边效果

 2022年8月5日17:19:37

公司版本比较老,没有mars3d.effect.OutlineEffect。项目组有一个createEdgeStage.js文件用来处理模型描边。

1、调用 然后初始化effect

#initEffects() {
    
    // 抗锯齿
    this.mapInstance.viewer.scene.postProcessStages.fxaa.enabled = true
    // 阴影透明度
    this.mapInstance.viewer.shadowMap.darkness = 0.55
    // 环境遮罩

    // 与模型描边效果冲突,不能同时开启
    // this.postStage.ambientOcclusion =
    //   this.mapInstance.viewer.scene.postProcessStages.ambientOcclusion;
    // this.postStage.ambientOcclusion.enabled = true;

    // 模型描边效果处理器初始化
    this.postStage.edgeStage = createEdgeStage()
    this.postStage.edgeStage.visibleEdgeColor =     schinta3d.Cesium.Color.fromCssColorString('#7ca6b1')
    this.postStage.edgeStage.hiddenEdgeColor = schinta3d.Cesium.Color.fromCssColorString('#1d3c4d')
    this.postStage.edgeStage.selected = []
    this.postStage.edgeStage.enabled = false
    this.mapInstance.viewer.postProcessStages.add(this.postStage.edgeStage)
    this.postStage.blackFog = new schinta3d.effect.FogEffect({
      enabled: false,
      color: schinta3d.Cesium.Color.BLACK,
      fogByDistance: new schinta3d.Cesium.Cartesian4(10, 0.0, 3000, 1)
    })
    this.mapInstance.addThing(this.postStage.blackFog)

    this.postStage.groundTransparent = new schinta3d.thing.Underground({
      alpha: 0.2
    })

  }

2、高亮的方法highlightPicked

highlightPicked(pickedObjectArray, options) {
    let opt = options || {}
    this.postStage.edgeStage.thresholdAngle = (opt.thresholdAngle * Math.PI) / 180 || (12 * Math.PI) / 180
    this.postStage.edgeStage.visibleEdgeColor = schinta3d.Cesium.Color.fromCssColorString(
      // opt.visibleEdgeColor || "#7ca6b1"
      opt.visibleEdgeColor || '#F8F846'
    )
    this.postStage.edgeStage.hiddenEdgeColor = schinta3d.Cesium.Color.fromCssColorString(
      // opt.hiddenEdgeColor || "#1d3c4d"
      opt.hiddenEdgeColor || ''
    )
    this.postStage.edgeStage.showGlow = true
    if (pickedObjectArray && pickedObjectArray.length > 0) {
      this.postStage.edgeStage.selected = pickedObjectArray
      // this.postStage.ambientOcclusion.enabled = false;
      this.postStage.edgeStage.enabled = true
    } else {
      this.postStage.edgeStage.selected = []
      this.postStage.edgeStage.enabled = false
      // this.postStage.ambientOcclusion.enabled = true;
    }
  }

3、Entity、Primitive被click时调用highlightPicked参考:https://zhuanlan.zhihu.com/p/407871786

// 添加点击事件
          this.mapViewer.additionalLayers.gltf_models.on(schinta3d.EventType.click, (event) => {
            const { id, options } = event.graphic
            console.log(options.name)

            // 模型描边-start  参考:https://zhuanlan.zhihu.com/p/407871786
            let picked=event.pickedObject

            if (picked && picked.primitive) {
              let primitive = picked.primitive
              let pickIds = primitive._pickIds;//Entity、Primitive
              //已经单体化的3D Tiles或者其他pickObject本身带有pickId属性的情况
              let pickId = picked.pickId;
              //未单体化的3D Tiles
              if (!pickId && !pickIds && picked.content) {
                  pickIds = picked.content._model._pickIds;
              }

              if (!pickId) {
                  if (picked.id) {
                      //Entity
                      pickId = pickIds.find(pickId => {
                          return pickId.object == picked;
                     })
                 } else if (pickIds) {
                      pickId = pickIds[0]
                 }
              }

              this.mapViewer.highlightPicked([{
                    pickId: pickId
              }]);

              // 模型描边-end

         }

4、3DTiles点击对象为模型时 

const tilesetLayer = new schinta3d.layer.TilesetLayer({...opts, preloadWhenHidden: true, preloadFlightDestinations: true, preferLeaves: true })
// 左键单击 鼠标事件
tilesetLayer.on(schinta3d.EventType.click, (event) => {
     this.tilesetClicked.next(event);
     // console.log(event.pickedObject)
     this.highlightPicked([event.pickedObject]);
});

文章来源地址https://uudwc.com/A/Ykn8

原文地址:https://blog.csdn.net/u012804473/article/details/125424381

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

h
上一篇 2023年06月16日 02:53
用QT实现一个模型交互的网络请求
下一篇 2023年06月16日 02:53