Cesium中常用的一些数学计算(矩阵、向量)用法——向量

刚好本人最近在研究数字孪生模拟相关的专题,涉及到三维空间中跟线代相关的计算,顺便重温了一下现代,在使用的过程中遇到的一些总结和实用技巧在下头阐述,相信这篇文章能够给短时间接触这些API的人一些启发。

不同人看向量存在着差异。物理专业学生的视角,向量由方向和长度决定;对于数学专业的学生来说,向量则会被概括为列表的形式方便计算机的存储;

向量是将几何问题转化为代数问题的桥梁,通常,我们研究的二维向量是平面的,而对于我们生活的三维空间,则更多使用三维的向量表示。理解其几何意义可以更好的运用于实际的案例,理解其代数实现可以更好地在计算机进行实现,先来总结一下Cesium 中Cartesian3的一些常见用法:

笛卡尔坐标系(Cartesian3)

地球几何中心为原点,以米为单位。
在这里插入图片描述

坐标经典转换

如何将经纬度或弧度转空间直角坐标系

// wgs84的弧度的经纬度
var position = Cesium.Cartesian3.fromRadians(-2.007, 0.645)
 //#WGS84经纬度转换为世界(笛卡尔)坐标直接转换
var position = Cesium.Cartesian3.fromDegrees(longitude, latitude, height, ellipsoid, result)//其中,高度默认值为0,可以不用填写;longitude和latitude为经纬度
var positions = Cesium.Cartesian3.fromDegreesArray(coordinates);//其中,coordinates格式为不带高度的数组。例如:[-115.0, 37.0, -107.0, 33.0]
var positions = Cesium.Cartesian3.fromDegreesArrayHeights(coordinates);//coordinates格式为带有高度的数组。例如:[-115.0, 37.0, 100000.0, -107.0, 33.0, 150000.0]

如何将笛卡尔空间直角坐标(Cartesian3)转经纬度或弧度(wgs84)

// 第一种:直接转换,转换为弧度
const cartographic = Cesium.Cartographic.fromCartesian(cartesian3)
// 第二种:间接转化,转换为角度
const ellipsoid = viewer.scene.globe.ellipsoid
const cartesian3 = new Cesium.cartesian3(x,y,z)
const cartographic = ellipsoid.cartesianToCartographic(cartesian3)
const lat = Cesium.Math.toDegrees(cartograhphic.latitude)
const lng = Cesium.Math.toDegrees(cartograhpinc.longitude)
const alt = cartographic.height

常用方法

Cesium.Cartesian3.abs(cartesian, new Cesium.Cartesian3())

求向量的绝对值

Cesium.Cartesian3.add(a, b, new Cesium.Cartesian3())

  // 源码
  // 代数理解
  // A(X1,Y1) B(X2,Y2),则A + B=(X1+X2,Y1+Y2)
  result.x = left.x + right.x;
  result.y = left.y + right.y;
  result.z = left.z + right.z;

向量相加得到的结果。由起点指向下一个向量的终点(几何意义的理解)。
向量和

Cesium.Cartesian3.subtract(pointA, pointB, new Cesium.Cartesian3());

  // 源码
  // A(X1,Y1) B(X2,Y2),A - B=(X1-X2,Y1-Y2)
  result.x = left.x - right.x;
  result.y = left.y - right.y;
  result.z = left.z - right.z;

计算A、B两个笛卡尔向量差,第一个参数是起点,第二个参数是终点。
由减向量的终点指向被减向量的终点。
在这里插入图片描述

Cesium.Cartesian3.normalize(vector, new Cesium.Cartesian3());

  // 源码
  const magnitude = Cartesian3.magnitude(cartesian);
  result.x = cartesian.x / magnitude;
  result.y = cartesian.y / magnitude;
  result.z = cartesian.z / magnitude;

将向量归一化(即单位向量),实际应用中使得我们可以只考虑单位向量的方向,不去管他的大小。

Cesium.Cartesian3.negate(cartesian, new Cesium.Cartesian3())

向量方向取反

// 例子
Cesium.Cartesian3.negate(new Cesium.Cartesian3(3,4,5), new Cesium.Cartesian3()) 
// new Cesium.Cartesian3(-3, -4, -5)

Cesium.Cartesian3.dot(left, right) ;

// 源码
// 代数实现: 两个维数相同的向量对应维相乘再相加
// 计算向量的点积(注:点积是标量,只有数值,没有方向)
 return left.x * right.x + left.y * right.y + left.z * right.z;

几何意义:b在a向量上的投影和a长度的乘积;
如果两个向量的指向方向大致相同时,则点积为正数;两个互相垂直的向量结果为0;两个向量的指向大致相反时,点积为负数。
在这里插入图片描述
点积与顺序无关。

点积在图形学上的用途:主要用于求夹角、求两个向量投影的长度、比较两个向量的接近程度(方向上,如果点积越大,说明夹角越小)

Cesium.Cartesian3.cross(left, right, result)

计算向量叉积(注:叉积是向量)

  // 源码
  const leftX = left.x;
  const leftY = left.y;
  const leftZ = left.z;
  const rightX = right.x;
  const rightY = right.y;
  const rightZ = right.z;

  const x = leftY * rightZ - leftZ * rightY;
  const y = leftZ * rightX - leftX * rightZ;
  const z = leftX * rightY - leftY * rightX;

  result.x = x;
  result.y = y;
  result.z = z;
  return result;

向量的叉积:两个互相垂直的向量,结果是向量的乘积;向量叉乘自身得到长度为0的向量;

叉积的用途很多,可用于求平面的法向量(向量的方向同时垂直于向量a、b组成的平面)、建立三维空间坐标中的直角坐标系、计算三角形的面积、判断左右和内外等等;例如可以判断凹凸多边形、点是否在三角形面内。

Cesium.Cartesian3.projectVector(a, b, new Cesium.Cartesian3())

求向量a投影到向量b上的向量

 // 源码
  const scalar = Cartesian3.dot(a, b) / Cartesian3.dot(b, b);
  return Cartesian3.multiplyByScalar(b, scalar, result);

源码解析:按照几何理解,a、b的点积是a向量在b向量上投影的长度 乘以 b向量的长度(模),b的点积是b长度的平方,所以scalar = a向量在b向量上投影的长度/b向量的长度,将b向量乘以他们的比例即等于a在b上的投影。

Cesium.Cartesian3.midpoint(left, right, new Cesium.Cartesian3())

求两个点的中间点

  result.x = (left.x + right.x) * 0.5;
  result.y = (left.y + right.y) * 0.5;
  result.z = (left.z + right.z) * 0.5;

绿色的点
绿色的点为蓝色点的中点

Cesium.Cartesian3.multiplyByScalar(cartesian, scalar, new Cesium.Cartesian3())

向量的缩放比例

  // 源码
  result.x = cartesian.x * scalar;
  result.y = cartesian.y * scalar;
  result.z = cartesian.z * scalar;

Cesium.Cartesian3.multiplyComponents(left, right, new Cesium.Cartesian3())

两个Cartesian的分量乘积

  result.x = left.x * right.x;
  result.y = left.y * right.y;
  result.z = left.z * right.z;

Cesium.Cartesian3.divideByScalar(cartesian, scalar, new Cesium.Cartesian3())

将提供的笛卡尔分量除以提供的标量

  result.x = cartesian.x / scalar;
  result.y = cartesian.y / scalar;
  result.z = cartesian.z / scalar;

Cesium.Cartesian3.divideComponents(left, right, new Cesium.Cartesian3())

两个笛卡尔坐标的分量商

  result.x = left.x / right.x;
  result.y = left.y / right.y;
  result.z = left.z / right.z;

Cesium.Cartesian3.magnitude(cartesian)

求向量的长度(向量的模)(注:一个向量)

// 源码
return Math.sqrt(Cartesian3.magnitudeSquared(cartesian));

Cesium.Cartesian3.magnitudeSquared(cartesian)

求向量长度的平方(向量模的平方)(注:一个向量)

// 源码
return (cartesian.x * cartesian.x + cartesian.y * cartesian.y + cartesian.z * cartesian.z);

Cesium.Cartesian3.distance(left, right)

求两个向量之间的距离(注:求两点的直线距离)

 // 源码
 Cartesian3.subtract(left, right, distanceScratch);
  return Cartesian3.magnitude(distanceScratch);

区别于直线距离,还有地表距离,可以用下面的方式计算:

// 求取地表两点距离  由经纬度返回弧度
 let startPosition1=new Cesium.Cartographic.fromDegrees(110,30);
 let endPosition1=new Cesium.Cartographic.fromDegrees(110,30.1);
 let geodesic = new Cesium.EllipsoidGeodesic(startPosition1,endPosition1);
 //设置测地线的起点和终点
 // geodesic.setEndPoints(startPosition1, endPosition1);
 let distance1 = geodesic.surfaceDistance;//求地表距离,单位为米
 console.log("两点的地表距离:",distance1);

Cesium.Cartesian3.distanceSquared(left, right)

求两个向量之间距离的平方(注:两个向量)

  // 源码
  Cartesian3.subtract(left, right, distanceScratch);
  return Cartesian3.magnitudeSquared(distanceScratch);

Cesium.Cartesian3.angleBetween(left, right)

求两个向量的夹角

  Cartesian3.normalize(left, angleBetweenScratch);
  Cartesian3.normalize(right, angleBetweenScratch2);
  const cosine = Cartesian3.dot(angleBetweenScratch, angleBetweenScratch2);
  const sine = Cartesian3.magnitude(
    Cartesian3.cross(
      angleBetweenScratch,
      angleBetweenScratch2,
      angleBetweenScratch
    )
  );
  return Math.atan2(sine, cosine);
Cesium提供了一些有用的工具和API,可以帮助你计算卫星轨道。下面是一些可能会用到的API和工具: 1. Cesium.Cartesian3.fromRadians(longitude, latitude, height):将经纬度和高度转换为笛卡尔坐标系的坐标。 2. Cesium.Cartesian3.normalize(vector, result):将一个向量规范化为单位向量。 3. Cesium.Cartesian3.cross(vector1, vector2, result):计算两个向量的叉积。 4. Cesium.Matrix3.fromQuaternion(quaternion, result):将四元数转换为3x3矩阵。 5. Cesium.Matrix3.multiply(matrix1, matrix2, result):计算两个3x3矩阵的乘积。 6. Cesium.Transforms.computeTemeToPseudoFixedMatrix(julianDate, result):计算从TEME(地球惯性参考系)到Pseudo-Fixed(地球固定参考系)的变换矩阵。 7. Cesium.Simon1994PlanetaryPositions.computeSatellitePositionInEarthInertialFrame(satelliteNumber, time, result):计算卫星在地球惯性参考系的位置和速度。 根据以上API和工具,你可以通过以下步骤计算卫星轨道: 1. 获取卫星的初始位置和速度向量。 2. 计算卫星的轨道半长轴、轨道偏心率、轨道倾角、升交点赤经和升交点赤纬等轨道参数。 3. 计算卫星的平近点角和真近点角。 4. 计算卫星的位置和速度向量在地心惯性参考系的坐标。 5. 计算从TEME到Pseudo-Fixed的变换矩阵。 6. 计算卫星在Pseudo-Fixed参考系的位置和速度。 7. 将卫星的位置和速度转换为经纬度和高度。 请注意,这是一个复杂的计算过程,需要涉及许多数学和物理知识。如果你需要精确的卫星轨道计算结果,建议参考相关文献或寻求专业人士的帮助。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值