2020年8月16日 星期日

[3D地圖]了解笛卡爾座標系

 

即便調整了x y z知道他會改變到哪裡
還是對他們的走向一知半解
於是找了此連結的方法
畫了參考座標軸

    addXYZArrow() {
      this.tileset.readyPromise.then(() => {
        let center = this.tileset.boundingSphere.center
        let axisX = this.addOneArrow({ color: Cesium.Color.RED, position: center, id: 1 })
        let axisY = this.addOneArrow({ color: Cesium.Color.GREEN, position: center, id: 2 })
        let axisZ = this.addOneArrow({ color: Cesium.Color.BLUE, position: center, id: 3 })
        axisX = this.rotatePrimitive('x', axisX)
        axisY = this.rotatePrimitive('y', axisY)
        this.viewer.scene.primitives.add(axisX)
        this.viewer.scene.primitives.add(axisY)
        this.viewer.scene.primitives.add(axisZ)
      })
    },
    addOneArrow(option) {
      const { color, position, id } = option
      const cylinderOption = {
        length: 3000,
        topRadius: 3,
        bottomRadius: 3,
      }
      const cylinder = new Cesium.CylinderGeometry(cylinderOption)
      const line = Cesium.CylinderGeometry.createGeometry(cylinder)
      const arrowOption = {
        length: 50,
        topRadius: 0,
        bottomRadius: 12
      }
      const arrowCylinder = new Cesium.CylinderGeometry(arrowOption)
      const arrow = Cesium.CylinderGeometry.createGeometry(arrowCylinder)
      let offset = ( 3000 + 50 ) / 2
      this.translateArrowPosition(arrow, [0, 0, offset])
      const myAppearance = {
        material: Cesium.Material.fromType('Color', { color })
      }
      const myPrimitiveOption = {
        asynchronous: false,
        modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(position),
        geometryInstances: [
          new Cesium.GeometryInstance({ geometry: line, id: `line${id}` }),
          new Cesium.GeometryInstance({ geometry: arrow, id: `arrow${id}` })
        ],
        appearance: new Cesium.MaterialAppearance(myAppearance)
      }
      const myPrimitive = new Cesium.Primitive(myPrimitiveOption)
      return myPrimitive
    },
    translateArrowPosition(geometry, offset) {
      if(!Array.isArray(offset)) return
      const scratchOffset = new Cesium.Cartesian3()
      scratchOffset.x = offset[0] //0
      scratchOffset.y = offset[1] //0
      scratchOffset.z = offset[2] //長度除以2
      let geometryPositionLength = geometry.attributes.position.values.length
      for (let i = 0; i < geometryPositionLength; i += 3) {
        geometry.attributes.position.values[i] += scratchOffset.x //0
        geometry.attributes.position.values[i + 1] += scratchOffset.y //0
        geometry.attributes.position.values[i + 2] += scratchOffset.z //長度除以2
      }
    },
    rotatePrimitive(type, primitive) {
      let myFunction = type == 'x' ? 'fromRotationX' : 'fromRotationY'
      const degree = Cesium.Matrix3[myFunction](Cesium.Math.toRadians(90));
      const rotation = Cesium.Matrix4.fromRotationTranslation(degree);
      const myLine = primitive.geometryInstances[0].modelMatrix
      const myArrow = primitive.geometryInstances[1].modelMatrix
      Cesium.Matrix4.multiply( myLine, rotation, myLine ); //left, right, result //矩陣相加
      Cesium.Matrix4.multiply( myArrow, rotation, myArrow );
      return primitive
    },


至此步驟的github


1. 關於geometry.attributes.position.values
由此
https://cesium.com/docs/cesiumjs-ref-doc/GeometryAttribute.html#values
可知value是三個三個一組的array
如下
[ 代表x, 代表y, 代表z, 代表x, 代表y, 代表z, 代表x, 代表y, 代表z ....]
//我實際把geometry.attributes.position.values印出來發現長度是1536

2.但實驗後發現,x y z 跟這三軸一點關係都沒有

        let center = this.tileset.boundingSphere.center //龍的中心點
        let x = center.x + 1000
        let y = center.y
        let z = center.z
        let newCenter = new Cesium.Cartesian3(x, y, z)
        let newBillboardCollection = new Cesium.BillboardCollection()
        this.myBillboard = this.viewer.scene.primitives.add(newBillboardCollection)
        this.myBillboard.add({
          position: newCenter,
          image: squirtleImage,
          width : 50,
          height : 100,
        })



        let center = this.tileset.boundingSphere.center //龍的中心點
        let x = center.x
        let y = center.y - 1000
        let z = center.z
        let newCenter = new Cesium.Cartesian3(x, y, z)
        let newBillboardCollection = new Cesium.BillboardCollection()
        this.myBillboard = this.viewer.scene.primitives.add(newBillboardCollection)
        this.myBillboard.add({
          position: newCenter,
          image: squirtleImage,
          width : 50,
          height : 100,
        })



        let center = this.tileset.boundingSphere.center //龍的中心點
        let x = center.x
        let y = center.y
        let z = center.z + 1000
        let newCenter = new Cesium.Cartesian3(x, y, z)
        let newBillboardCollection = new Cesium.BillboardCollection()
        this.myBillboard = this.viewer.scene.primitives.add(newBillboardCollection)
        this.myBillboard.add({
          position: newCenter,
          image: squirtleImage,
          width : 50,
          height : 100,
        })


3. 我想說轉成經緯度+高度的方式,但沒有想像中順利

        let center = this.tileset.boundingSphere.center //龍的中心點
        console.log(center);
        //x: 1215107.7612304366
        //y: -4736682.902037748
        //z: 4081926.095098698
        let cartographic = Cesium.Cartographic.fromCartesian(center)
        let height = cartographic.height
        let latitude = cartographic.latitude
        let longitude = cartographic.longitude
        let newCenter = Cesium.Cartesian3.fromDegrees(longitude, latitude, height)
        console.log(newCenter);
        //x: 6376477.655639131
        //y: -146893.86337388513
        //z: 77281.75309232753
        let newBillboardCollection = new Cesium.BillboardCollection()
        this.myBillboard = this.viewer.scene.primitives.add(newBillboardCollection)
        this.myBillboard.add({
          position: newCenter,
          image: squirtleImage,
          width : 50,
          height : 100,
        })


4. 換了另一種寫法後,就成功了

        let center = this.tileset.boundingSphere.center //龍的中心點
        console.log(center);
        // x: 1215107.7612304366
        // y: -4736682.902037748
        // z: 4081926.095098698
        let cartographic  = Cesium.Ellipsoid.WGS84.cartesianToCartographic(center);
        let longitude = Cesium.Math.toDegrees(cartographic.longitude);
        let latitude = Cesium.Math.toDegrees(cartographic.latitude);
        let height = cartographic.height
        let newCenter = Cesium.Cartesian3.fromDegrees(longitude, latitude, height)
        console.log(newCenter);
        // x: 1215107.7612304366
        // y: -4736682.902037748
        // z: 4081926.095098698
        let newBillboardCollection = new Cesium.BillboardCollection()
        this.myBillboard = this.viewer.scene.primitives.add(newBillboardCollection)
        this.myBillboard.add({
          position: newCenter,
          image: squirtleImage,
          width : 50,
          height : 100,
        })


5. 關於世界大地測量系統(WGS84)
6. 轉換的過程為: 「WGS84的Cartesian(x y z)」到「Cartographic(經緯弧度+高度)」到「經緯角度+高度」到「Cartesian(x y z)」

7. 成功綁到線上囉

        let center = this.tileset.boundingSphere.center //龍的中心點
        let cartographic  = Cesium.Ellipsoid.WGS84.cartesianToCartographic(center);
        let longitude = Cesium.Math.toDegrees(cartographic.longitude) + 0.01
        let latitude = Cesium.Math.toDegrees(cartographic.latitude)
        let height = cartographic.height
        let newCenter = Cesium.Cartesian3.fromDegrees(longitude, latitude, height)
        let newBillboardCollection = new Cesium.BillboardCollection()
        this.myBillboard = this.viewer.scene.primitives.add(newBillboardCollection)
        this.myBillboard.add({
          position: newCenter,
          image: squirtleImage,
          width : 50,
          height : 100,
        })



        let center = this.tileset.boundingSphere.center //龍的中心點
        let cartographic  = Cesium.Ellipsoid.WGS84.cartesianToCartographic(center);
        let longitude = Cesium.Math.toDegrees(cartographic.longitude)
        let latitude = Cesium.Math.toDegrees(cartographic.latitude) + 0.01
        let height = cartographic.height
        let newCenter = Cesium.Cartesian3.fromDegrees(longitude, latitude, height)
        let newBillboardCollection = new Cesium.BillboardCollection()
        this.myBillboard = this.viewer.scene.primitives.add(newBillboardCollection)
        this.myBillboard.add({
          position: newCenter,
          image: squirtleImage,
          width : 50,
          height : 100,
        })



        let center = this.tileset.boundingSphere.center //龍的中心點
        let cartographic  = Cesium.Ellipsoid.WGS84.cartesianToCartographic(center);
        let longitude = Cesium.Math.toDegrees(cartographic.longitude)
        let latitude = Cesium.Math.toDegrees(cartographic.latitude)
        let height = cartographic.height + 500
        let newCenter = Cesium.Cartesian3.fromDegrees(longitude, latitude, height)
        let newBillboardCollection = new Cesium.BillboardCollection()
        this.myBillboard = this.viewer.scene.primitives.add(newBillboardCollection)
        this.myBillboard.add({
          position: newCenter,
          image: squirtleImage,
          width : 50,
          height : 100,
        })


至此步驟的github

沒有留言:

張貼留言