从 Cesium.Cartesian3 和 Cesium.HeadingPitchRoll 创建 Cesium.Ray

Create Cesium.Ray from Cesium.Cartesian3 and Cesium.HeadingPitchRoll

是否可以从 Cesium.Cartesian3Cesium.HeadingPitchRoll 创建一个 Cesium.Ray

如果是这样,你会怎么做?

编辑 1:

const hpr = Cesium.HeadingPitchRoll.fromDegrees(0, 0, 0)
const matrix3 = Cesium.Matrix3.fromHeadingPitchRoll(hpr)

// The UNIT_X vector is "forward" in Cesium.  We'll multiply the rotation
// matrix by that unit vector, to get our direction vector.
const direction = Cesium.Matrix3.multiplyByVector(
  matrix3,
  Cesium.Cartesian3.UNIT_X,
  new Cesium.Cartesian3()
)

const origin = Cesium.Cartesian3.fromDegrees(i.longitude, i.latitude, i.altitude)

// Now we can construct the Ray.
const ray = new Cesium.Ray(origin, direction)

const finalPoint = Cesium.Ray.getPoint(ray, i.altitude)
const e = map.viewer.entities.add({
  name: i.id,
  polyline: {
    positions: [origin, finalPoint],
    width: 4,
    arcType: Cesium.ArcType.NONE,
    material: new Cesium.PolylineArrowMaterialProperty(Cesium.Color.RED),
  },
})

将 HPR 设置为 (0,0,0),结果为:

间距为 0,我希望光线与 horizon 平行,而不是看起来像 +45 度。

是的,这是可能的。这两种对象包含不同类型的信息,因此请注意不要在转换过程中丢失数据。

  • 一个Ray有一个origin(笛卡尔位置)和一个direction,它只是一个单位向量,与完整方向不同。

  • HeadingPitchRoll是一个完整的方向。 Heading 和 Pitch 共同确定特定的“前进”方向,Roll 表示围绕该方向矢量的旋转。此 Roll 旋转不影响方向,因此不会对 Ray 产生影响。

代码如下:

// A Cesium Ray consists of an "origin" and a "direction".
// The origin is just a Cartesian3 from anywhere.
var origin = new Cesium.Cartesian3(1.0, 2.0, 3.0);

// For this question, "direction" comes from a HeadingPitchRoll.
// Let's establish an HPR here.
var heading = Cesium.Math.toRadians(0);  // YOUR VALUE HERE
var pitch = Cesium.Math.toRadians(0);    // YOUR VALUE HERE
var roll = Cesium.Math.toRadians(0);     // This one does nothing.

var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);

// Next we need a direction vector from the HPR.  We'll use
// a rotation matrix (3x3) to do the conversion.
var matrix3 = Cesium.Matrix3.fromHeadingPitchRoll(hpr);

// The UNIT_X vector is "forward" in Cesium.  We'll multiply the rotation
// matrix by that unit vector, to get our direction vector.
var direction = Cesium.Matrix3.multiplyByVector(matrix3, Cesium.Cartesian3.UNIT_X,
    new Cesium.Cartesian3());

// Now we can construct the Ray.
var ray = new Cesium.Ray(origin, direction);

console.log('Ray: ' + JSON.stringify(ray));

如果您 运行 使用此处显示的默认零 heading/pitch,您将再次获得单位 X 向量:

Ray: {"origin":{"x":1,"y":2,"z":3},"direction":{"x":1,"y":0,"z":0}}

但是如果你将俯仰设置为 45 度:

var heading = Cesium.Math.toRadians(0);
var pitch = Cesium.Math.toRadians(45);

您会看到 X 方向已向上倾斜到 +Z。

Ray: {"origin":{"x":1,"y":2,"z":3},"direction":{"x":0.7071067811865476,"y":0,"z":0.7071067811865475}}

正航向会将 X 矢量旋转到 -Y(从上面的 +Z 方向看是顺时针方向)。

var heading = Cesium.Math.toRadians(45);
var pitch = Cesium.Math.toRadians(0);

Ray: {"origin":{"x":1,"y":2,"z":3},"direction":{"x":0.7071067811865476,"y":-0.7071067811865475,"z":0}}


EDIT: 问题修改了一下。射线的方向需要在以地球为中心的固定坐标系中,而不是局部向上坐标系,以用于预期用途。

这里有一个更长的演示,展示了如何处理这个问题。您也可以在 Sandcastle 上 view a live demo

var viewer = new Cesium.Viewer("cesiumContainer");

const i = {
  id: 'test',
  longitude: -79,
  latitude: 40,
  altitude: 500
};

// Create the origin and hpr.
const origin = Cesium.Cartesian3.fromDegrees(i.longitude, i.latitude, i.altitude)

let hpr = Cesium.HeadingPitchRoll.fromDegrees(0, 0, 0)

// Cesium uses East-North-Up axes, where East is zero.  If you want North == Zero,
// you must subtract 90 degrees' worth of radians (pi/2).
hpr.heading -= Cesium.Math.PI_OVER_TWO

// We'll get the orientation, which is a quaternion.  This is specific to the
// location on the planet.  Also it comes in handy later for the 3D model vis.
const orientation = Cesium.Transforms.headingPitchRollQuaternion(origin, hpr);

// Get a Matrix3 version of that Quaternion.
const matrix3 = Cesium.Matrix3.fromQuaternion(orientation);

// The UNIT_X vector is "forward" in Cesium.  We'll multiply the rotation
// matrix by that unit vector, to get our direction vector.
const direction = Cesium.Matrix3.multiplyByVector(
  matrix3,
  Cesium.Cartesian3.UNIT_X,
  new Cesium.Cartesian3()
)


// Now we can construct the Ray.
const ray = new Cesium.Ray(origin, direction)

const finalPoint = Cesium.Ray.getPoint(ray, i.altitude)
const e = viewer.entities.add({
  name: i.id,
  polyline: {
    positions: [origin, finalPoint],
    width: 4,
    arcType: Cesium.ArcType.NONE,
    material: new Cesium.PolylineArrowMaterialProperty(Cesium.Color.RED),
  },
})

// Optionally, show an aircraft model with this HPR.
const m = viewer.entities.add({
  position: origin,
  orientation: orientation,
  model: {
    uri: "../SampleData/models/CesiumAir/Cesium_Air.glb",
    minimumPixelSize: 64,
  }
})

viewer.zoomTo(e)