刚好本人最近在研究数字孪生模拟相关的专题,涉及到三维空间中跟线代相关的计算,顺便重温了一下现代,在使用的过程中遇到的一些总结和实用技巧在下头阐述,相信这篇文章能够给短时间接触这些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)文章来源:https://www.toymoban.com/news/detail-689163.html
求两个向量的夹角文章来源地址https://www.toymoban.com/news/detail-689163.html
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中常用的一些数学计算(矩阵、向量)用法——向量的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!