我试图从其顶点而不是中心旋转圆锥体,以便顶点保持在相同的位置。
我从以下链接找到了以下示例: https://groups.google.com/forum/#!topic/cesium-dev/f9ZiSWPMgus
但它只显示了如何将圆锥体旋转 90 度,如果您为滚动选择不同的值,例如 45 或 30 度,它会倾斜,并且顶点最终会出现在错误的位置。
我知道这与偏移有关,但无法从那里取得任何进展。有什么方法可以计算任何滚动值的正确偏移量吗?
我还想延长圆锥体旋转时的长度,这样当圆锥体旋转30度时,圆锥体的底部仍然会在那个方向到达地面,而顶点仍然保持在原来的位置,我不知道这有多可行。
下面是代码示例的一个错误: https://glitch.com/edit/#!/cesium-cone-rotation
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);
当您想要将圆柱体指向由方位角和仰角指定的特定方向时,我想到了旋转和平移圆柱体的方法。
/**
* 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];
}
这将为您提供创建圆柱体实体时要使用的位置/方向。它将放置圆柱体,使圆柱体的尖端位于“位置”,并指向方位角和仰角指定的方向。方位角相对于北,且朝向东的角度为正。高程是相对于东北平面的,向上为正角。范围是圆柱体的长度。
这并不能让你获得你想要的在旋转圆柱体时延长圆柱体的行为,但希望它能有所帮助。
我和你有同样的问题。这是我的参考代码。这是计算任意角度圆锥体矩阵的函数。
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());
}