cesium模型的旋转、平移和缩放带辅助操作

在这里插入图片描述
前言:
最近在做cesium的开发,需要加载大量模型,但是只有经纬度信息。
找了网上部分代码,这个是比较全的,但是缺少了很多代码和函数,自己补充上然后记录在这儿。
代码可以直接复制粘贴使用,需要自己整理代码。
只支持 单模型的旋转平移。
句柄其实不太好操作,比threejs差远了。
1.主类

import ArrowPolyline from '../model/ArrowPolyline'
import EventConstant from '../constant/EventConstant'
import {cartesian3ToQuaternion, normalizingQuaternion, projectOnPlane, rayPlaneIntersection} from './math'
import AxisSphere from '../model/AxisSphere'
import EventManager from '../event/EventManager'

export default class TranslationController {

    /**
     * 视图
     * @type {Viewer}
     */
    viewer = null

    /**
     * 模型
     * @type {Cesium.Model}
     */
    model = null

    /**
     * 模型位置
     * @type {Cesium.Cartesian3}
     */
    position = null

    /**
     * z轴
     * @type {ArrowPolyline}
     */
    axisZ = null

    /**
     * x轴
     * @type {ArrowPolyline}
     */
    axisX = null

    /**
     * y轴
     * @type {ArrowPolyline}
     */
    axisY = null

    /**
     * 操作杆集合
     * @type {Cesium.PrimitiveCollection}
     */
    primitives = null

    /**
     * 从摄像头发出与视窗上一点相交的射线
     */
    pickRay = new Cesium.Ray()

    /**
     * 拾取到的位置
     * @type {Cesium.Cartesian3}
     */
    pickPoint = null

    /**
     * 当前操作轴
     * @type {ArrowPolyline}
     */
    axis = null

    /**
     * Z旋转轴
     * @type {AxisSphere}
     */
    axisSphereZ = null

    /**
     * X旋转轴
     * @type {AxisSphere}
     */
    axisSphereX = null

    /**
     * Y旋转轴
     * @type {AxisSphere}
     */
    axisSphereY = null

    /**
     * 辅助球
     * @type {Cesium.Primitive}
     */
    auxiliaryBall = null
    //模型半径
    radius = null
    //模型原始矩阵
    orgModelMatrix = null
    //是否允许旋转
    rotateEnable = null
    //是否允许移动
    moveEnable = null

    constructor(viewer, model) {
        this.viewer = viewer
        this.model = model
        this.rotateEnable = false
        this.moveEnable = true
        this.orgModelMatrix = this.model.modelMatrix.clone(new Cesium.Matrix4())
        this.position = Cesium.Matrix4.getTranslation(
            model.modelMatrix,
            new Cesium.Cartesian3()
        )
        this.primitives = new Cesium.PrimitiveCollection()
        this.viewer.baseViewer.scene.primitives.add(this.primitives)

        // 创建平移轴
        this._createRod()
        // 旋转平移轴
        this._rotationRod()
        // 添加平移轴
        this._addRod()

        // 创建旋转轴
        this._createSphereAxis()
        // 旋转旋转轴
        this._rotationSphereAxis()
        // 添加旋转轴
        this._addSphereAxis()
        // 添加辅助球
        this.auxiliaryBall = {
            show: false
        }
        this.addAuxiliaryBall(6, Cesium.Color.RED.withAlpha(0.2))
        this._initEventManager()
        // 添加监听器
        this._addListener()
    }

    //复原model
    resetModel() {
        this.model.modelMatrix = this.orgModelMatrix
        this._resetMaterial()
    }

    //初始化监听
    _initEventManager() {
        this.viewer.eventManager = new EventManager(this.viewer.baseViewer)
    }

    // 添加监听器
    _addListener() {
        this.viewer.eventManager.addEventListener(EventConstant.LEFT_DOWN, this._clickListener)
        this.viewer.eventManager.addEventListener(EventConstant.LEFT_UP, this._clickUpListener)
        this.viewer.eventManager.addEventListener(EventConstant.MOUSE_MOVE, this._moveListener)
    }

    // 清除操纵杆, 监听器
    destroy() {
        this.primitives.removeAll()
        this.viewer.baseViewer.scene.primitives.remove(this.primitives)
        this._removeListener()
        this.viewer.baseViewer.scene.screenSpaceCameraController.enableRotate = true
        this.viewer.baseViewer.scene.screenSpaceCameraController.enableTranslate = true
    }

    // 移除监听器
    _removeListener() {
        this.viewer.eventManager.removeEventListener(EventConstant.LEFT_DOWN, this._clickListener)
        this.viewer.eventManager.removeEventListener(EventConstant.LEFT_UP, this._clickUpListener)
        this.viewer.eventManager.removeEventListener(EventConstant.MOUSE_MOVE, this._moveListener)
    }

    // 创建操作杆
    _createRod() {
        const boundingShpere = this.model.boundingSphere
        const radius = boundingShpere.radius
        this.radius = radius

        const options = {
            width: (radius / 15) > 10 ? 10 : radius / 15,
            headWidth: (radius / 6) > 20 ? 20 : radius / 6,
            length: radius * 1,//坐标轴的长度应该视模型的直径而定
            headLength: (radius / 3) > 50 ? 50 : radius / 3,
            position: this.position
        }
        // 向上的向量
        const vectorNormalUp = new Cesium.Cartesian3()
        const vZ = new Cesium.Cartesian3(0, 0, 1)
        Cesium.Cartesian3.normalize(this.position.clone(), vectorNormalUp)

        // 向右的向量
        const vectorNormalRight = new Cesium.Cartesian3()
        // 由z轴向上 地表向上两个向量叉乘, 则可以得出, 向右的向量
        Cesium.Cartesian3.cross(vZ, vectorNormalUp, vectorNormalRight)

        // 向前的向量
        const vectorNormalFront = new Cesium.Cartesian3()
        Cesium.Cartesian3.cross(vectorNormalRight, vectorNormalUp, vectorNormalFront)
        Cesium.Cartesian3.multiplyByScalar(vectorNormalFront, -1, vectorNormalFront)

        this.axisX = new ArrowPolyline({
            id: 'axisX',
            color: Cesium.Color.GREEN,
            direction: vectorNormalRight,
            unit: Cesium.Cartesian3.UNIT_X,
            ...options
        })
        this.axisZ = new ArrowPolyline({
            id: 'axisZ',
            color: Cesium.Color.RED,
            direction: vectorNormalUp,
            unit: Cesium.Cartesian3.UNIT_Z,
            ...options
        })
        this.axisY = new ArrowPolyline({
            id: 'axisY',
            color: Cesium.Color.BLUE,
            direction: vectorNormalFront,
            unit: Cesium.Cartesian3.UNIT_Y,
            ...options
        })
    }

    // 添加操作杆
    _addRod() {
        this.primitives.add(this.axisZ.primitive)
        this.primitives.add(this.axisX.primitive)
        this.primitives.add(this.axisY.primitive)
    }

    // 初始化操作杆
    _rotationRod() {
        const mx = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(90))
        const rotationX = Cesium.Matrix4.fromRotationTranslation(mx)
        this.axisX.rotation(rotationX)
        const my = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(90))
        const rotationY = Cesium.Matrix4.fromRotationTranslation(my)
        this.axisY.rotation(rotationY)
    }

    // 点击监听
    _clickListener = (e) => {
        if (this.translationAxisIsSelected() || this.rotationAxisIsSelected()) {
            this.viewer.baseViewer.scene.screenSpaceCameraController.enableRotate = false
            this.pickPoint = this.viewer.baseViewer.scene.pickPosition(e.message.position)
        }
    }

    /**
     * 平移轴被选中
     * @return {boolean}
     */
    translationAxisIsSelected() {
        return this.axisX.selected || this.axisY.selected || this.axisZ.selected
    }

    /**
     * 旋转轴被选中
     * @return {boolean}
     */
    rotationAxisIsSelected() {
        return this.axisSphereZ.selected || this.axisSphereX.selected || this.axisSphereY.selected
    }

    _clickUpListener = () => {
        this.pickPoint = null
        this.axis = null
        this.viewer.baseViewer.scene.screenSpaceCameraController.enableRotate = true
        this.auxiliaryBall.show = false
    }
    // 移动监听
    _moveListener = (e) => {
        const pick = this.viewer.baseViewer.scene.pick(e.message.endPosition)
        if (!this.viewer.eventManager.press) {
            this._resetMaterial()
        } else if (this.axis && this.viewer.eventManager.press) {
            this.translationAxisIsSelected() && this._precessTranslation(e, this.axis)
            this.rotationAxisIsSelected() && this._precessRotation(e, this.axis)
            return
        }
        if (pick && pick.id) {
            this._resetMaterial()
            let axis = null
            if (this.axisX.is(pick.id)) {
                axis = this.axisX
            } else if (this.axisY.is(pick.id)) {
                axis = this.axisY
            } else if (this.axisZ.is(pick.id)) {
                axis = this.axisZ
            } else if (this.axisSphereX.is(pick.id)) {
                axis = this.axisSphereX
            } else if (this.axisSphereY.is(pick.id)) {
                axis = this.axisSphereY
            } else if (this.axisSphereZ.is(pick.id)) {
                axis = this.axisSphereZ
            }
            if (axis) {
                this.axis = axis
                this.axis.select()
                if (this.rotationAxisIsSelected()) {
                    this.auxiliaryBall.show = true
                }
            }
        }
    }

    /**
     * 处理旋转
     * @param e
     * @param axis{AxisSphere}
     * @private
     */
    _precessRotation(e, axis) {
        this.auxiliaryBall.show = true
        if (!this.pickPoint) return

        let cartesian3 = this.viewer.baseViewer.scene.pickPosition(e.message.startPosition)
        Cesium.Cartesian3.subtract(cartesian3, this.position, cartesian3)
        const vtStart = projectOnPlane(cartesian3, axis.direction)

        cartesian3 = this.viewer.baseViewer.scene.pickPosition(e.message.endPosition)
        Cesium.Cartesian3.subtract(cartesian3, this.position, cartesian3)
        const vtEnd = projectOnPlane(cartesian3, axis.direction)

        const cartesian = Cesium.Cartesian3.cross(vtStart, vtEnd, new Cesium.Cartesian3())

        const angle = Cesium.Math.toDegrees(Cesium.Cartesian3.angleBetween(cartesian, axis.direction))
        // 利用叉乘性质判断方向
        let rotateAngleInRadians = Cesium.Cartesian3.angleBetween(vtEnd, vtStart)
        if (angle > 1) {
            rotateAngleInRadians = -rotateAngleInRadians
        }

        let mx = null
        if (axis.id === 'axisSphereX') {
            mx = Cesium.Matrix3.fromRotationX(rotateAngleInRadians)
        } else if (axis.id === 'axisSphereY') {
            mx = Cesium.Matrix3.fromRotationY(rotateAngleInRadians)
        } else if (axis.id === 'axisSphereZ') {
            mx = Cesium.Matrix3.fromRotationZ(rotateAngleInRadians)
        }
        const rotationX = Cesium.Matrix4.fromRotationTranslation(mx)
        this.rotation(rotationX, axis, rotateAngleInRadians)
    }

    /**
     *
     * @param rotationX{Cesium.Matrix4} 旋轉角度
     * @param axis{AxisSphere}
     * @param rotateAngleInRadians
     */
    rotation(rotationX, axis, rotateAngleInRadians) {
        this.axisSphereX.rotationAxis(rotationX)
        this.axisSphereY.rotationAxis(rotationX)
        this.axisSphereZ.rotationAxis(rotationX)
        this.axisX.rotationAxis(rotationX)
        this.axisY.rotationAxis(rotationX)
        this.axisZ.rotationAxis(rotationX)
        this.rotateVectorByAxisForAngle(this.axisX.direction, axis.direction, rotateAngleInRadians)
        this.rotateVectorByAxisForAngle(this.axisY.direction, axis.direction, rotateAngleInRadians)
        this.rotateVectorByAxisForAngle(this.axisZ.direction, axis.direction, rotateAngleInRadians)
        Cesium.Matrix4.multiply(
            this.model.modelMatrix,
            rotationX,
            this.model.modelMatrix
        )
        const number = Cesium.Math.toDegrees(rotateAngleInRadians)
        axis.updateAngle(number)
    }

    /**
     * 处理选中
     * @param e{{message: {startPosition: Cesium.Cartesian2, endPosition: Cesium.Cartesian2}}}
     * @param axis{ArrowPolyline}
     * @private
     */
    _precessTranslation(e, axis) {
        this.auxiliaryBall.show = false
        if (!this.pickPoint) return
        this.viewer.baseViewer.camera.getPickRay(e.message.startPosition, this.pickRay)
        const startPosition = rayPlaneIntersection(this.pickRay, this.viewer.baseViewer.camera.direction, this.pickPoint)
        this.viewer.baseViewer.camera.getPickRay(e.message.endPosition, this.pickRay)
        const endPosition = rayPlaneIntersection(this.pickRay, this.viewer.baseViewer.camera.direction, this.pickPoint)
        const moveVector = new Cesium.Cartesian3()
        Cesium.Cartesian3.subtract(endPosition, startPosition, moveVector)
        const moveLength = Cesium.Cartesian3.dot(axis.direction, moveVector)
        this.translation(moveVector, axis.unit, moveLength)
    }

    /**
     * 平移
     * @param moveVector
     * @param unit
     * @param moveLength
     */
    translation(moveVector, unit, moveLength) {
        this.axisX.translation(moveVector, unit, moveLength)
        this.axisY.translation(moveVector, unit, moveLength)
        this.axisZ.translation(moveVector, unit, moveLength)
        this.axisSphereX.translation(moveVector, unit, moveLength)
        this.axisSphereY.translation(moveVector, unit, moveLength)
        this.axisSphereZ.translation(moveVector, unit, moveLength)

        const matrix4 = this.model.modelMatrix.clone(new Cesium.Matrix4())
        //平移矩阵和当前模型矩阵相乘
        Cesium.Matrix4.multiplyByTranslation(
            this.model.modelMatrix,
            // Cesium.Cartesian3.multiplyByScalar(new Cesium.Cartesian3(-unit.y, unit.x, unit.z), moveLength, new Cesium.Cartesian3()),
            Cesium.Cartesian3.multiplyByScalar(unit, moveLength, new Cesium.Cartesian3()),
            this.model.modelMatrix
        )
        //更新position模型当前的位置
        Cesium.Matrix4.getTranslation(this.model.modelMatrix, this.position)

        Cesium.Matrix4.subtract(this.model.modelMatrix, matrix4, matrix4)
        const cartesian3 = Cesium.Matrix4.getTranslation(matrix4, new Cesium.Cartesian3())
        Cesium.Matrix4.multiplyByTranslation(
            this.auxiliaryBall.modelMatrix,
            cartesian3,
            this.auxiliaryBall.modelMatrix
        )
    }

    // 复位所有的材质
    _resetMaterial() {
        this.axisX.rest()
        this.axisY.rest()
        this.axisZ.rest()
        this.axisSphereY.rest()
        this.axisSphereZ.rest()
        this.axisSphereX.rest()
        this.auxiliaryBall.show = false
    }

    // 创建 旋转轴
    _createSphereAxis() {
        const radius = this.radius * 2
        this.axisSphereZ = new AxisSphere('axisSphereZ', radius, this.position, Cesium.Color.RED)
        this.axisSphereX = new AxisSphere('axisSphereX', radius, this.position, Cesium.Color.GREEN)
        this.axisSphereY = new AxisSphere('axisSphereY', radius, this.position, Cesium.Color.BLUE)
        this.axisSphereZ.direction = this.axisZ.direction
        this.axisSphereX.direction = this.axisX.direction
        this.axisSphereY.direction = this.axisY.direction
    }

    // 旋转 旋转轴
    _rotationSphereAxis() {
        const mx = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(90))
        const rotationX = Cesium.Matrix4.fromRotationTranslation(mx)
        this.axisSphereX.rotation(rotationX)
        const my = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(90))
        const rotationY = Cesium.Matrix4.fromRotationTranslation(my)
        this.axisSphereY.rotation(rotationY)
    }

    // 添加旋转轴
    _addSphereAxis() {
        if (this.rotateEnable && !this.primitives.contains(this.axisSphereZ.primitive)) {
            this.primitives.add(this.axisSphereZ.primitive)
            this.primitives.add(this.axisSphereY.primitive)
            this.primitives.add(this.axisSphereX.primitive)
        } else if (this.rotateEnable === false) {
            this.primitives.remove(this.axisSphereZ.primitive)
            this.primitives.remove(this.axisSphereY.primitive)
            this.primitives.remove(this.axisSphereX.primitive)
        }

    }

    //开启旋转
    setEnableRotate(enabled) {
        this.rotateEnable = enabled
        this._addSphereAxis()
    }

    /**
     * 添加辅助球, 用于辅助位置拾取
     * @param {number} radius
     * @param {Cesium.Color} color
     */
    addAuxiliaryBall(radius, color) {
        // const cartesian3 = CesiumUtils.extended(this.position, -radius)
        const cartesian3 = this.position
        const modelMatrix = Cesium.Matrix4.multiplyByTranslation(
            Cesium.Transforms.eastNorthUpToFixedFrame(cartesian3),
            new Cesium.Cartesian3(0.0, 0.0, radius),
            new Cesium.Matrix4()
        );

        const sphereGeometry = new Cesium.SphereGeometry({
            vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
            radius: radius,
        });
        const sphereInstance = new Cesium.GeometryInstance({
            id: 'auxiliaryBall',
            geometry: sphereGeometry,
            modelMatrix: modelMatrix,
            attributes: {
                color: Cesium.ColorGeometryInstanceAttribute.fromColor(
                    color
                ),
            },
        });

        this.auxiliaryBall = this.primitives.add(
            new Cesium.Primitive({
                geometryInstances: sphereInstance,
                appearance: new Cesium.PerInstanceColorAppearance({
                    translucent: true,
                    closed: true,
                }),
            })
        )
        this.auxiliaryBall.show = false
    }

    /**
     * 通过轴旋转角度
     * @param vector
     * @param axis
     * @param angle
     */
    rotateVectorByAxisForAngle(vector, axis, angle) {
        const rotateQuaternion = normalizingQuaternion(Cesium.Quaternion.fromAxisAngle(axis, angle, new Cesium.Quaternion()))
        const quaternion = cartesian3ToQuaternion(vector)
        Cesium.Quaternion.multiply(
            Cesium.Quaternion.multiply(
                rotateQuaternion,
                quaternion,
                quaternion
            ),
            Cesium.Quaternion.inverse(rotateQuaternion, new Cesium.Quaternion()),
            quaternion
        )
        vector.x = quaternion.x
        vector.y = quaternion.y
        vector.z = quaternion.z
        return quaternion
    }
}

2.其他的辅助类
1)Axis.js 辅助轴线类

export default class Axis {
    /**
     * 实体
     * @type {Cesium.Primitive}
     */
    primitive = null

    /**
     * 选中状态
     * @type {boolean}
     */
    selected = false

    /**
     * 轴的颜色
     * @type {Cesium.Color}
     * @private
     */
    _color = null

    /**
     * 平移
     * @param moveVector{Cesium.Cartesian3} 移动距离
     * @param unit
     * @param moveLength
     */
    translation(moveVector, unit, moveLength) {
        Cesium.Matrix4.multiplyByTranslation(
            this.primitive.modelMatrix,
            Cesium.Cartesian3.multiplyByScalar(unit, moveLength, new Cesium.Cartesian3()),
            this.primitive.modelMatrix
        )
    }

    /**
     * 旋转轴
     * @param {Cesium.Matrix4} rotation
     */
    rotationAxis(rotation){
        Cesium.Matrix4.multiply(
            this.primitive.modelMatrix,
            rotation,
            this.primitive.modelMatrix,
        )
    }

    /**
     * 旋转
     * @param rotationX{Cesium.Matrix4} 旋转角度
     */
    rotation(rotationX) {
        this.instance = []
        if (this.primitive.geometryInstances.constructor === Array) {
            this.instance = this.primitive.geometryInstances
        } else {
            this.instance = [this.primitive.geometryInstances]
        }
        for (let i = 0; i < this.instance.length; i++) {
            Cesium.Matrix4.multiply(
                this.instance[i].modelMatrix,
                rotationX,
                this.instance[i].modelMatrix
            )
        }
    }

    // 复位颜色
    rest() {
        this.selected = false
        this.primitive.appearance.material.uniforms.color = this._color
    }

    // 选中
    select() {
        this.selected = true
        this.primitive.appearance.material.uniforms.color = Cesium.Color.WHITE
    }

    /**
     * 是否是当前轴
     * @param id
     * @return {boolean}
     */
    is(id) {
        return !!this.primitive._instanceIds.find(item => item === id)
    }
}

2)ArrowPolyline.js 辅助线类

import Axis from './Axis'

export default class ArrowPolyline extends Axis {

    /**
     * 方向
     * @type {Cesium.Cartesian3}
     */
    direction = null

    /**
     * 哪个轴
     * @type {Cartesian3}
     */
    unit = null

    /**
     * 箭头线
     */
    constructor(option = {}) {
        super()
        this._color = option.color || Cesium.Color.RED;
        this._width = option.width || 3;
        this._headWidth = option.headWidth || 2 * this._width;
        this._length = option.length || 300
        this._headLength = option.headLength || 10
        this._inverse = option.inverse || false
        this.position = option.position
        this.direction = option.direction
        this.unit = option.unit
        const id = option.id
        //这里用的是圆锥几何对象,当topRadius和bottomRadius相同时,它就是一个圆柱
        const line = Cesium.CylinderGeometry.createGeometry(new Cesium.CylinderGeometry({
            length: this._length,
            topRadius: this._width,
            bottomRadius: this._width
        }));
        const arrow = Cesium.CylinderGeometry.createGeometry(new Cesium.CylinderGeometry({
            length: this._headLength,
            topRadius: 0,
            bottomRadius: this._headWidth
        }));
        let offset = (this._length + this._headLength) / 2
        if (this._inverse) {
            offset = -offset
        }

        this.translate(arrow, [0, 0, offset]);
        let modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(this.position)
        // Cesium.Matrix4.multiplyByTranslation(modelMatrix,
        //     Cesium.Cartesian3.multiplyByScalar(Cesium.Cartesian3.UNIT_Z, 2000, new Cesium.Cartesian3()),
        //     modelMatrix)
        this.primitive = new Cesium.Primitive({
            modelMatrix: modelMatrix,
            geometryInstances: [new Cesium.GeometryInstance(
                {
                    id: id + '-line',
                    geometry: line,
                }
            ),
                new Cesium.GeometryInstance({
                    id: id + '-arrow',
                    geometry: arrow,
                })],
            appearance: new Cesium.MaterialAppearance({
                material: Cesium.Material.fromType('Color', {color: this._color})
            }),
            asynchronous: false
        });
    }

    /**
     * 按上面的方法画出的箭头在线的中间,我们需要把它平移到线的一端
     */
    translate(geometry, offset) {
        const scratchOffset = new Cesium.Cartesian3();
        if (Array.isArray(offset)) {
            scratchOffset.x = offset[0];
            scratchOffset.y = offset[1];
            scratchOffset.z = offset[2];
        } else {
            Cesium.Cartesian3.clone(offset, scratchOffset);
        }

        for (let i = 0; i < geometry.attributes.position.values.length; i += 3) {
            geometry.attributes.position.values[i] += scratchOffset.x;
            geometry.attributes.position.values[i + 1] += scratchOffset.y;
            geometry.attributes.position.values[i + 2] += scratchOffset.z;
        }
    }
}

3)AxisSphere.js

import Axis from './Axis'

export default class AxisSphere extends Axis {

    id = ''

    /**
     * 轴位置
     * @type {[]}
     */
    position = []

    /**
     * 方向
     * @type {Cesium.Cartesian3}
     */
    direction = null

    /**
     * 轴的角度
     * @type {number}
     */
    angle = 0

    /**
     * 构造一个旋转轴
     * @param id{string} id
     * @param radius{number} 半径
     * @param position{Cesium.Cartesian3} 位置
     * @param color{Cesium.Color} 颜色
     */
    constructor (id, radius, position, color) {
        super()
        this.id = id
        this._color = color
        this._calculation(radius/3, position)
        this._createAxisSphere(id, position, color)
    }

    /**
     * 创建圆环轴
     * @param id{string} id
     * @param matrix{Cesium.Cartesian3} 位置
     * @param color{Cesium.Color} 颜色
     * @private
     */
    _createAxisSphere(id, position, color) {
        const matrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
        // Cesium.Matrix4.multiplyByTranslation(matrix,
        //     Cesium.Cartesian3.multiplyByScalar(Cesium.Cartesian3.UNIT_Z, 2000, new Cesium.Cartesian3()),
        //     matrix)
        const geometry = new Cesium.PolylineGeometry({
            positions: this.position,
            width: 10
        });
        const instance = new Cesium.GeometryInstance({
            geometry: geometry,
            id: id,
            attributes: {
                color: Cesium.ColorGeometryInstanceAttribute.fromColor(color)
            }
        });
        this.primitive = new Cesium.Primitive({
            geometryInstances: instance,
            appearance: new Cesium.PolylineColorAppearance({
                translucent: false
            }),
            modelMatrix: matrix
        });
    }

    /**
     * 计算轴圆弧位置
     * @param radius{number}
     */
    _calculation (radius, position) {
        for (let i = 0; i <= 360; i += 3) {
            const sin = Math.sin(Cesium.Math.toRadians(i));
            const cos = Math.cos(Cesium.Math.toRadians(i));
            const x = radius * cos;
            const y = radius * sin;
            this.position.push(new Cesium.Cartesian3(x, y, 0));
        }
    }

    /**
     * 更新轴的角度
     * @param angle
     */
    updateAngle(angle) {
        this.angle += angle
        if(this.angle >= 360 || this.angle <= 360) {
            this.angle = 0
        }
    }

    /**
     * 选中
     */
    select () {
        this.selected = true
    }

    // 复位颜色
    rest () {
        this.selected = false
    }
}

4)其他的工具函数
math.js

export const projectOnPlane = (vp, vn) => {
    const vt = new Cesium.Cartesian3()
    const multi = new Cesium.Cartesian3()
    const divide = new Cesium.Cartesian3()
    const cartesian3 = Cesium.Cartesian3.multiplyByScalar(vn, Cesium.Cartesian3.dot(vp, vn), multi);
    Cesium.Cartesian3.divideByScalar(
        cartesian3,
        Cesium.Cartesian3.dot(vn, vn),
        divide
    )
    Cesium.Cartesian3.subtract(vp, divide, vt)
    return vt
}

export const rayPlaneIntersection = (ray, cameraDirection, pickPoint, result = new Cesium.Cartesian3()) => {
    if (!pickPoint) {
        throw new Error("cuowu")
        return
    }
    const number = Cesium.Cartesian3.dot(cameraDirection, pickPoint);
    const number1 = Cesium.Cartesian3.dot(cameraDirection, ray.origin);
    const number2 = Cesium.Cartesian3.dot(cameraDirection, ray.direction);
    const t = (number - number1) / number2
    return Cesium.Cartesian3.add(ray.origin, Cesium.Cartesian3.multiplyByScalar(ray.direction, t, result), result)
}
export const cartesian3ToQuaternion = (cartesian3) => {
    return new Cesium.Quaternion(
        cartesian3.x,
        cartesian3.y,
        cartesian3.z,
        0
    )
}

function moduloQuaternion(quaternion) {
    let result = Math.sqrt(quaternion.x*quaternion.x + quaternion.y*quaternion.y + quaternion.z*quaternion.z+ quaternion.w*quaternion.w)
    console.log(result)
    return result
}

export const normalizingQuaternion = (quaternion) => {
    // Normalize( q ) = q/ |q| = q / (x*x + y*y + z*z + w*w)
    return Cesium.Quaternion.divideByScalar(
        quaternion,
        moduloQuaternion(quaternion),
        quaternion
    )
}

EventConstant.js

export default {
    LEFT_DOWN: Cesium.ScreenSpaceEventType.LEFT_DOWN,
    LEFT_UP: Cesium.ScreenSpaceEventType.LEFT_UP,
    MOUSE_MOVE: Cesium.ScreenSpaceEventType.MOUSE_MOVE,
    RIGHT_DOWN: Cesium.ScreenSpaceEventType.RIGHT_DOWN,
}

EventManager.js

import EventConstant from "../constant/EventConstant";

export default class EventManager {
    /**
     * 记录是否按下左键
     * @type {boolean}
     */
    press = false;
    /**
     *
     * @type {null}
     */
    handler = null
    listener = null
    evtDict = null

    constructor(viewer) {
        this.press = false
        this.handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
        this.evtDict = {}
    }

    addEventListener(eventType, func) {
        let listener = (e) => {
            if (eventType === EventConstant.LEFT_DOWN) this.press = true
            let evt = {message: e}
            return func(evt)
        }
        this.handler.setInputAction(listener, eventType)
        this.evtDict[eventType] = listener

    }

    removeEventListener(eventType) {
        if (eventType === EventConstant.MOUSE_MOVE) this.press = false
        this.handler.removeInputAction(eventType, this.evtDict[eventType])
        this.evtDict = {}
    }
}
  • 12
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 29
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值