首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Cesium.js围绕顶点旋转圆锥体

使用Cesium.js围绕顶点旋转圆锥体
EN

Stack Overflow用户
提问于 2017-03-22 10:53:21
回答 2查看 1.2K关注 0票数 2

我正在尝试从圆锥体的顶点旋转圆锥体,而不是从圆锥体的中心旋转,以便圆锥体的顶点保持不变。

我在下面的链接中找到了下面的示例:https://groups.google.com/forum/#!topic/cesium-dev/f9ZiSWPMgus

但它只显示了如何将圆锥体旋转90度,如果您选择不同的滚动值,例如45度或30度,它会倾斜,顶点最终会出现错误的位置。

我知道这与偏移量有关,但从那里无法取得任何进展。有没有什么方法可以计算出任何值的正确偏移量?

我还想在圆锥体旋转时延长它的长度,这样当它旋转30度时,圆锥体的底部仍然会沿着那个方向到达地面,而顶端仍然保持在原来的位置,但我不知道这是否可行。

下面是代码示例中的一个小问题:https://glitch.com/edit/#!/cesium-cone-rotation

代码语言:javascript
运行
复制
var viewer = new Cesium.Viewer('cesiumContainer');

var position = Cesium.Cartesian3.fromDegrees(-75, 40, 90); 

//Original, non-rotated cone for comparison.
viewer.entities.add(new Cesium.Entity({
    position: position,
    point: {
        color: Cesium.Color.YELLOW,
        show: true,
        pixelSize: 20
    },
    cylinder: {
        topRadius: 0,
        bottomRadius: 45,
        length: 180,
        material: Cesium.Color.YELLOW.withAlpha(0.5)
    }
}));

var heading = Cesium.Math.toRadians(0.0);
var pitch = Cesium.Math.toRadians(0.0);
var roll = Cesium.Math.toRadians(90.0);
var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);

//Create a rotation
var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);

// offset the rotation so it's rotating from the apex of the cone, instead of the centre
var offset = new Cesium.Cartesian3(0, 90, 90);

//Create a transform for the offset.
var enuTransform = Cesium.Transforms.eastNorthUpToFixedFrame(position);

//Transform the offset
Cesium.Matrix4.multiplyByPointAsVector(enuTransform, offset, offset);

//Add the offset to the original position to get the final value.
Cesium.Cartesian3.add(position,  offset,  position);

viewer.entities.add(new Cesium.Entity({
    position: position,
    orientation: orientation,
    point: {
        color: Cesium.Color.YELLOW,
        show: true,
        pixelSize: 20
    },
    cylinder: {
        topRadius: 0,
        bottomRadius: 45,
        length: 180,
        material: Cesium.Color.YELLOW.withAlpha(0.5)
    }
}));

viewer.zoomTo(viewer.entities);
EN

回答 2

Stack Overflow用户

发布于 2020-04-09 10:21:21

这是我想出的旋转和平移圆柱体的方法,当你想要将它指向由方位和高度指定的特定方向时。

代码语言:javascript
运行
复制
/**
 * Calculate the position and orientation needed for the beam entity.
 * @param {Cesium.Cartesian3} position - The position of the desired origin.
 * @param {Number} az - The azimuth of the beam center in radians.
 * @param {Number} el - The elevation of the beam center in radians.
 * @param {Number} range - The range of the beam in meters.
 * 
 * @returns {[Cesium.Cartesian3, Cesium.Quaternion]} Array of the position and
 * orientation to use for the beam.
 */
calculateBeam(position, az, el, range) {
    // The origin of Cesium Cylinder entities is the center of the cylinder.
    // They are also pointed straight down towards the local East-North plane. The
    // math below rotates and translates the cylinder so that its origin is the tip
    // of the cylinder and its orientation is pointed in the direction specified by
    // the az/el.
    let heading = az - Cesium.Math.toRadians(90);
    let pitch = Cesium.Math.toRadians(90) + el;
    let hpr = new Cesium.HeadingPitchRoll(heading, pitch, 0.0);
    let x = range/2.0 * Math.sin(pitch) * Math.cos(heading);
    let y = -range/2.0 * Math.sin(heading) * Math.sin(pitch);
    let z = -range/2.0 * Math.cos(pitch);
    var offset = new Cesium.Cartesian3(x, y, z);
    let enuTransform = Cesium.Transforms.eastNorthUpToFixedFrame(position);
    Cesium.Matrix4.multiplyByPointAsVector(enuTransform, offset, offset);
    let newPosition = Cesium.Cartesian3.add(position, offset, new Cesium.Cartesian3());
    let orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);
    return [newPosition, orientation];
}

这将为您提供创建圆柱体图元时要使用的位置/方向。它将放置圆柱体,使圆柱体的尖端位于“位置”,并指向由方位角和高度指定的方向。方位角是相对于北边与东边的正角度。标高相对于东北平面,具有正向上的角度。范围是圆柱体的长度。

这不会在旋转圆柱体时得到您想要的行为,但希望它能有所帮助。

票数 2
EN

Stack Overflow用户

发布于 2020-09-16 14:02:09

我和你有同样的问题。这是我的参考代码。这是一个计算任意角度的锥体矩阵的函数。

代码语言:javascript
运行
复制
 computedModelMatrix(Cartesian3: any, attitude: any, length: any) {
        //锥体距离卫星的高度
        let oldLength = length / 2;
        let centerCartesian3 = new Cesium.Cartesian3(Cartesian3.x, Cartesian3.y, Cartesian3.z);
        let oldX = 0, oldY = 0, oldZ = -oldLength, newX = 0, newY = 0, newZ = 0;
        let heading = attitude.heading;
        //规定顺时针为正旋转,正东方向为0度
        if (heading < 0) {
            heading = heading + 360;
        }
        let roll = attitude.roll;
        let pitch = attitude.pitch;
        let headingRadians = Cesium.Math.toRadians(heading);
        let pitchRadians = Cesium.Math.toRadians(pitch);
        let rollRadians = Cesium.Math.toRadians(roll);
        let hpr = new Cesium.HeadingPitchRoll(headingRadians, pitchRadians, rollRadians);
        let orientation = Cesium.Transforms.headingPitchRollQuaternion(centerCartesian3, hpr);
        //旋转roll
        newY = oldY + oldLength * Math.sin(rollRadians);
        newZ = oldZ + oldLength - oldLength * Math.cos(rollRadians);
        let pitchTouying = oldLength * Math.cos(rollRadians);//进行pitch变化时在Y轴和Z轴组成的平面的投影
        //旋转pitch
        newX = oldX + pitchTouying * Math.sin(pitchRadians);
        newZ = newZ + (pitchTouying - pitchTouying * Math.cos(pitchRadians));
        if (heading != 0) {
            let headingTouying = Math.sqrt(Math.pow(Math.abs(newX), 2) + Math.pow(Math.abs(newY), 2));//进行heading变化时在Y轴和X轴组成的平面的投影
            //旋转heading
            let Xdeg = Cesium.Math.toDegrees(Math.acos(Math.abs(newX) / Math.abs(headingTouying)));//现有投影线与X轴的夹角
            let newXdeg = 0;//旋转heading后与X轴的夹角
            let newXRadians = 0;//旋转heading后与X轴的夹角弧度
            if (newX >= 0 && newY >= 0) {
                newXdeg = heading - Xdeg;
            } else if (newX > 0 && newY < 0) {
                newXdeg = heading + Xdeg;
            } else if (newX < 0 && newY > 0) {
                newXdeg = heading + (180 + Xdeg);
            } else {
                newXdeg = heading + (180 - Xdeg)
            }
            if (newXdeg >= 360) {
                newXdeg = 360 - newXdeg;
            }
            if (newXdeg >= 0 && newXdeg <= 90) {
                newXRadians = Cesium.Math.toRadians(newXdeg);
                newY = -headingTouying * Math.sin(newXRadians);
                newX = headingTouying * Math.cos(newXRadians);
            } else if (newXdeg > 90 && newXdeg <= 180) {
                newXRadians = Cesium.Math.toRadians(180 - newXdeg);
                newY = -headingTouying * Math.sin(newXRadians);
                newX = -headingTouying * Math.cos(newXRadians)
            } else if (newXdeg > 180 && newXdeg <= 270) {
                newXRadians = Cesium.Math.toRadians(newXdeg - 180);
                newY = headingTouying * Math.sin(newXRadians);
                newX = -(headingTouying * Math.cos(newXRadians))
            } else {
                newXRadians = Cesium.Math.toRadians(360 - newXdeg);
                newY = headingTouying * Math.sin(newXRadians);
                newX = headingTouying * Math.cos(newXRadians)
            }
        }
        let offset = new Cesium.Cartesian3(newX, newY, newZ);
        let newPosition = this.computeOffset(centerCartesian3, offset);
        return Cesium.Matrix4.fromTranslationQuaternionRotationScale(newPosition, orientation, new Cesium.Cartesian3(1, 1, 1))
    }
computeOffset(Cartesian3: any, offset: any) {
        let enuTransform = Cesium.Transforms.eastNorthUpToFixedFrame(Cartesian3);
        Cesium.Matrix4.multiplyByPointAsVector(enuTransform, offset, offset);
        return Cesium.Cartesian3.add(Cartesian3, offset, new Cesium.Cartesian3());
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42941855

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档