剛好本人最近在研究數(shù)字孿生模擬相關(guān)的專題,涉及到三維空間線代向量、矩陣相關(guān)的計算,順便重溫了一下線代,在使用的過程中遇到問題的一些總結(jié)和實用技巧在下頭闡述,相信這篇文章能夠給短時間接觸這些API的人一些啟發(fā)。
在三維中可以把矩陣的列看出變換后的基向量:
通常而言,表示坐標(biāo)系的i、j向量為(1,0)、(0,1),當(dāng)我們把坐標(biāo)軸逆時針旋轉(zhuǎn)90°后,坐標(biāo)系的基向量發(fā)生成了變化,i–>(0,1)、(-1, 0);
矩陣乘以一個向量有什么幾何意義
矩陣乘向量就是把這個向量旋轉(zhuǎn),而且向量的大小也會改變,可以看出某空間下的向量到另一個空間的映射,其實就是向量空間的線性變換。
對于這一塊理解比較模糊的同學(xué)推薦看一下國外的Blue1Brown視頻->線性代數(shù)的本質(zhì)
來看一下一些常見的用法:
特別的仿射四維矩陣:
左上角是旋轉(zhuǎn)矩陣、右上角是平移矩陣,旋轉(zhuǎn)矩陣的最后一維是0,平移矩陣的最后一維是1。
總結(jié)一下Cesium 中Matrix4的一些常見用法:
Cesium.Matrix4,4x4矩陣,一般用于描述旋轉(zhuǎn)加平移變換。
在計算機圖形學(xué)中,Cesium.Matrix3,3x3矩陣,一般用于描述旋轉(zhuǎn)變換。
矩陣和標(biāo)量相乘
Cesium.Matrix4.multiplyByScalar (matrix, scalar, new Cesium.Matrix4())
矩陣的縮放倍數(shù)
result[0] = matrix[0] * scalar;
result[1] = matrix[1] * scalar;
result[2] = matrix[2] * scalar;
result[3] = matrix[3] * scalar;
result[4] = matrix[4] * scalar;
result[5] = matrix[5] * scalar;
result[6] = matrix[6] * scalar;
result[7] = matrix[7] * scalar;
result[8] = matrix[8] * scalar;
result[9] = matrix[9] * scalar;
result[10] = matrix[10] * scalar;
result[11] = matrix[11] * scalar;
result[12] = matrix[12] * scalar;
result[13] = matrix[13] * scalar;
result[14] = matrix[14] * scalar;
result[15] = matrix[15] * scalar;
return result;
* // m = [10.0, 11.0, 12.0, 13.0]
* // [14.0, 15.0, 16.0, 17.0]
* // [18.0, 19.0, 20.0, 21.0]
* // [22.0, 23.0, 24.0, 25.0]
*
* const a = Cesium.Matrix4.multiplyByScalar(m, -2, new Cesium.Matrix4());
*
* // m remains the same
* // a = [-20.0, -22.0, -24.0, -26.0]
* // [-28.0, -30.0, -32.0, -34.0]
* // [-36.0, -38.0, -40.0, -42.0]
* // [-44.0, -46.0, -48.0, -50.0]
*/
矩陣和向量相乘部分
Cesium.Matrix4.multiplyByScale (matrix, scale, new Cesium.Matrix4())
對矩陣空間中的列向量進行成比例縮放,縮放了空間基向量的長度
const scaleX = scale.x;
const scaleY = scale.y;
const scaleZ = scale.z;
// Faster than Cartesian3.equals
if (scaleX === 1.0 && scaleY === 1.0 && scaleZ === 1.0) {
return Matrix4.clone(matrix, result);
}
result[0] = scaleX * matrix[0];
result[1] = scaleX * matrix[1];
result[2] = scaleX * matrix[2];
result[3] = matrix[3];
result[4] = scaleY * matrix[4];
result[5] = scaleY * matrix[5];
result[6] = scaleY * matrix[6];
result[7] = matrix[7];
result[8] = scaleZ * matrix[8];
result[9] = scaleZ * matrix[9];
result[10] = scaleZ * matrix[10];
result[11] = matrix[11];
result[12] = matrix[12];
result[13] = matrix[13];
result[14] = matrix[14];
result[15] = matrix[15];
return result;
Cesium.Matrix4.multiplyByTranslation (matrix, translation, new Cesium.Matrix4())
const x = translation.x;
const y = translation.y;
const z = translation.z;
const tx = x * matrix[0] + y * matrix[4] + z * matrix[8] + matrix[12];
const ty = x * matrix[1] + y * matrix[5] + z * matrix[9] + matrix[13];
const tz = x * matrix[2] + y * matrix[6] + z * matrix[10] + matrix[14];
result[0] = matrix[0];
result[1] = matrix[1];
result[2] = matrix[2];
result[3] = matrix[3];
result[4] = matrix[4];
result[5] = matrix[5];
result[6] = matrix[6];
result[7] = matrix[7];
result[8] = matrix[8];
result[9] = matrix[9];
result[10] = matrix[10];
result[11] = matrix[11];
result[12] = tx;
result[13] = ty;
result[14] = tz;
result[15] = matrix[15];
Cesium.Matrix4.multiplyByVector(matrix, cartesian, new Cesium.Cartesian3())
將一個3D向量進行線性變換,使其沿著矩陣的行方向進行縮放、旋轉(zhuǎn)和平移
cartesian的w分量為0,表示這個結(jié)果是一個向量,而不是一個點,你可以用這個函數(shù)獲取一個向量。
// 源碼
const vX = cartesian.x;
const vY = cartesian.y;
const vZ = cartesian.z;
const vW = cartesian.w;
const x = matrix[0] * vX + matrix[4] * vY + matrix[8] * vZ + matrix[12] * vW;
const y = matrix[1] * vX + matrix[5] * vY + matrix[9] * vZ + matrix[13] * vW;
const z = matrix[2] * vX + matrix[6] * vY + matrix[10] * vZ + matrix[14] * vW;
const w = matrix[3] * vX + matrix[7] * vY + matrix[11] * vZ + matrix[15] * vW;
result.x = x;
result.y = y;
result.z = z;
result.w = w;
將這個向量乘以矩陣,得到一個新的向量,即將原向量進行變換后得到新向量。
Cesium.Matrix4.multiplyByPoint(matrix, cartesian, new Cesium.Cartesian3())
cartesian的w分量為1,表示這個結(jié)果是一個點,不是一個向量,你可以用這個函數(shù)獲取一個坐標(biāo)點。
// 源碼
const vX = cartesian.x;
const vY = cartesian.y;
const vZ = cartesian.z;
const x = matrix[0] * vX + matrix[4] * vY + matrix[8] * vZ + matrix[12];
const y = matrix[1] * vX + matrix[5] * vY + matrix[9] * vZ + matrix[13];
const z = matrix[2] * vX + matrix[6] * vY + matrix[10] * vZ + matrix[14];
result.x = x;
result.y = y;
result.z = z;
常用于,將模型從局部空間轉(zhuǎn)換到世界空間,或者相機空間等。任何位移,旋轉(zhuǎn),縮放的組合都可以用一個4x4矩陣來表示,這樣就可以簡單地使用矩陣乘法來變換點和向量。
通俗一點,即將局部坐標(biāo)系下的點坐標(biāo)轉(zhuǎn)化為世界坐標(biāo)的點。以下點A通過矩陣變換:
Cesium.Matrix4.multiplyByPoint(局部坐標(biāo)系, A在局部坐標(biāo)的位置, A在世界坐標(biāo)系下的點位置)
Cesium.Matrix4.multiplyByPointAsVector(matrix, new Cesium.Cartesian3(x, y, z), new Cesium.Cartesian3());
w分量為0,等效于調(diào)用 Matrix4.multiplyByVector,但是multiplyByPointAsVector方法返回的是一個Cartesian4對象,表示這個結(jié)果是一個向量,而不是一個點
// 源碼
const vX = cartesian.x;
const vY = cartesian.y;
const vZ = cartesian.z;
const x = matrix[0] * vX + matrix[4] * vY + matrix[8] * vZ;
const y = matrix[1] * vX + matrix[5] * vY + matrix[9] * vZ;
const z = matrix[2] * vX + matrix[6] * vY + matrix[10] * vZ;
result.x = x;
result.y = y;
result.z = z;
Cesium.Matrix4.setTranslation (matrix, translation, new Cesium.Matrix4())
設(shè)置平移矩陣
result[0] = matrix[0];
result[1] = matrix[1];
result[2] = matrix[2];
result[3] = matrix[3];
result[4] = matrix[4];
result[5] = matrix[5];
result[6] = matrix[6];
result[7] = matrix[7];
result[8] = matrix[8];
result[9] = matrix[9];
result[10] = matrix[10];
result[11] = matrix[11];
result[12] = translation.x;
result[13] = translation.y;
result[14] = translation.z;
result[15] = matrix[15];
Cesium.Matrix4.setScale (matrix, scale, new Cesium.Matrix4())
設(shè)置矩陣的比例縮放。
const existingScale = Matrix4.getScale(matrix, scaleScratch1);
const scaleRatioX = scale.x / existingScale.x;
const scaleRatioY = scale.y / existingScale.y;
const scaleRatioZ = scale.z / existingScale.z;
result[0] = matrix[0] * scaleRatioX;
result[1] = matrix[1] * scaleRatioX;
result[2] = matrix[2] * scaleRatioX;
result[3] = matrix[3];
result[4] = matrix[4] * scaleRatioY;
result[5] = matrix[5] * scaleRatioY;
result[6] = matrix[6] * scaleRatioY;
result[7] = matrix[7];
result[8] = matrix[8] * scaleRatioZ;
result[9] = matrix[9] * scaleRatioZ;
result[10] = matrix[10] * scaleRatioZ;
result[11] = matrix[11];
result[12] = matrix[12];
result[13] = matrix[13];
result[14] = matrix[14];
result[15] = matrix[15];
矩陣和矩陣相乘部分
Cesium.Matrix4.multiplyByMatrix3 (matrix, rotation, new Cesium.Matrix4())
乘以一個轉(zhuǎn)換矩陣(3x3旋轉(zhuǎn)矩陣),優(yōu)化 Matrix4.multiply(m,Matrix4.fromRotationTranslation(rotation),m)的計算,使得分配和運算量較少。
Cesium.Matrix4.multiply(left, right, new Cesium.Matrix4());
四維矩陣相乘。
A * B B左乘A, 可以把A看做坐標(biāo)系,A的行向量是坐標(biāo)系的基向量。把B看做列向量集合。 A * B就是把B中的列向量投影到A的所有基向量上。計算過程就是設(shè)b為B中的一個列向量。b點乘A中的所有基向量得到b在A的所有基向量上的投影,得到b向量在A坐標(biāo)系中的表示方法。所以B做成A就是,將B中的所有向量轉(zhuǎn)換為在A坐標(biāo)空間中的表示方法。
Cesium.Matrix4.multiplyTransformation(left, right, new Cesium.Matrix4()) ;
當(dāng)兩個矩陣都是左上角旋轉(zhuǎn)矩陣+右上角平移矩陣+底為[0,0,0,1]的這種形式的,用這種方法計算比一般用Matrix4.multiply 的速度更快。
// 源碼
const column0Row0 = left0 * right0 + left4 * right1 + left8 * right2;
const column0Row1 = left1 * right0 + left5 * right1 + left9 * right2;
const column0Row2 = left2 * right0 + left6 * right1 + left10 * right2;
const column1Row0 = left0 * right4 + left4 * right5 + left8 * right6;
const column1Row1 = left1 * right4 + left5 * right5 + left9 * right6;
const column1Row2 = left2 * right4 + left6 * right5 + left10 * right6;
const column2Row0 = left0 * right8 + left4 * right9 + left8 * right10;
const column2Row1 = left1 * right8 + left5 * right9 + left9 * right10;
const column2Row2 = left2 * right8 + left6 * right9 + left10 * right10;
const column3Row0 =
left0 * right12 + left4 * right13 + left8 * right14 + left12;
const column3Row1 =
left1 * right12 + left5 * right13 + left9 * right14 + left13;
const column3Row2 =
left2 * right12 + left6 * right13 + left10 * right14 + left14;
result[0] = column0Row0;
result[1] = column0Row1;
result[2] = column0Row2;
result[3] = 0.0;
result[4] = column1Row0;
result[5] = column1Row1;
result[6] = column1Row2;
result[7] = 0.0;
result[8] = column2Row0;
result[9] = column2Row1;
result[10] = column2Row2;
result[11] = 0.0;
result[12] = column3Row0;
result[13] = column3Row1;
result[14] = column3Row2;
result[15] = 1.0;
矩陣的常見用法
Cesium.Matrix4.subtract (left, right, new Cesium.Matrix4())
矩陣求差
Cesium.Matrix4.add (left, right, new Cesium.Matrix4())
矩陣求和
Cesium.Matrix4.abs (matrix, new Cesium.Matrix4())
求矩陣絕對值
Cesium.Matrix4.clone (matrix, new Cesium.Matrix4())
克隆當(dāng)前矩陣實例
Cesium.Matrix4.equals(left, right)
對比矩陣的每個元素值是否相等
逆矩陣部分
Cesium.Matrix4.inverse(matrix, new Cesium.Matrix4()) ;
逆矩陣是和這個矩陣相乘以后成為單位矩陣的矩陣。 當(dāng)行列式不為0,矩陣才有逆矩陣。如果輸入矩陣不可逆,則會返回一個全零并且平移為負的矩陣。計算矩陣的逆矩陣,從世界坐標(biāo)系到局部坐標(biāo)系的變換矩陣。
Cesium.Matrix4.inverseTransformation(matrix, new Cesium.Matrix4());
當(dāng)其中左上3x3元素是旋轉(zhuǎn)矩陣,第四列中的上三個元素是平移矩陣,最下面的一行是[0,0,0,1]時求矩陣的逆矩陣,用inverseTransformation這種方法比計算一般4x4矩陣使用 Matrix4.multiply的速度更快
const matrix0 = matrix[0];
const matrix1 = matrix[1];
const matrix2 = matrix[2];
const matrix4 = matrix[4];
const matrix5 = matrix[5];
const matrix6 = matrix[6];
const matrix8 = matrix[8];
const matrix9 = matrix[9];
const matrix10 = matrix[10];
const vX = matrix[12];
const vY = matrix[13];
const vZ = matrix[14];
const x = -matrix0 * vX - matrix1 * vY - matrix2 * vZ;
const y = -matrix4 * vX - matrix5 * vY - matrix6 * vZ;
const z = -matrix8 * vX - matrix9 * vY - matrix10 * vZ;
result[0] = matrix0;
result[1] = matrix4;
result[2] = matrix8;
result[3] = 0.0;
result[4] = matrix1;
result[5] = matrix5;
result[6] = matrix9;
result[7] = 0.0;
result[8] = matrix2;
result[9] = matrix6;
result[10] = matrix10;
result[11] = 0.0;
result[12] = x;
result[13] = y;
result[14] = z;
result[15] = 1.0;
return result;
inverse方法僅計算輸入矩陣的逆矩陣,而inverseTransformation方法計算輸入矩陣的逆矩陣和平移向量的相反數(shù)。在不同的場景下,選擇不同的方法可以更方便地實現(xiàn)所需的功能。
Cesium.Matrix4.transpose (matrix, new Cesium.Matrix4())
矩陣的轉(zhuǎn)置,將矩陣的行列互換得到的新矩陣稱為轉(zhuǎn)置矩陣,轉(zhuǎn)置矩陣的行列式不變。
//returns transpose of a Matrix4
// m = [10.0, 11.0, 12.0, 13.0]
// [14.0, 15.0, 16.0, 17.0]
// [18.0, 19.0, 20.0, 21.0]
// [22.0, 23.0, 24.0, 25.0]
var a = Cesium.Matrix4.transpose(m, new Cesium.Matrix4());
// m remains the same
// a = [10.0, 14.0, 18.0, 22.0]
// [11.0, 15.0, 19.0, 23.0]
// [12.0, 16.0, 20.0, 24.0]
// [13.0, 17.0, 21.0, 25.0]
轉(zhuǎn)置的作用相當(dāng)于對矩陣進行旋轉(zhuǎn),使得行變成列,列變成列。
Cesium.Matrix4.inverseTranspose(matrix,result)
求逆轉(zhuǎn)置
// 源碼
return Matrix4.inverse(
Matrix4.transpose(matrix, scratchTransposeMatrix),
result
);
在模型視圖變換時,頂點乘模型視圖變換矩陣,而頂點對應(yīng)的頂點法線向量(或其他的法線向量)則要乘模型視圖矩陣的逆轉(zhuǎn)置矩陣。
https://blog.51cto.com/u_15127690/4750355
Cesium.Matrix4.negate (matrix, result)
對矩陣每一個元素取相反數(shù)
// 實現(xiàn)邏輯
//create a new Matrix4 instance which is a negation of a Matrix4
// m = [10.0, 11.0, 12.0, 13.0]
// [14.0, 15.0, 16.0, 17.0]
// [18.0, 19.0, 20.0, 21.0]
// [22.0, 23.0, 24.0, 25.0]
var a = Cesium.Matrix4.negate(m, new Cesium.Matrix4());
// m remains the same
// a = [-10.0, -11.0, -12.0, -13.0]
// [-14.0, -15.0, -16.0, -17.0]
// [-18.0, -19.0, -20.0, -21.0]
// [-22.0, -23.0, -24.0, -25.0]
用Matrix4類的API生成四維矩陣
Cesium.Matrix4.fromTranslation(translation, new Cesium.Matrix4());
if (!defined(result)) {
return new Matrix4(
1.0,
0.0,
0.0,
translation.x,
0.0,
1.0,
0.0,
translation.y,
0.0,
0.0,
1.0,
translation.z,
0.0,
0.0,
0.0,
1.0
);
}
Cesium.Matrix4.getTranslation(matrix, new Cesium.Cartesian3())
從矩陣獲取平移向量, 用于獲取一個4x4矩陣的平移部分,返回的是矩陣的平移部分,也就是矩陣的第4列的前3個元素。這個結(jié)果是一個Cartesian3對象,表示3D空間中的一個點,這個點的坐標(biāo)就是矩陣所表示的變換中的平移部分。
通常,一個4x4的矩陣可以分解為三個部分:平移部分、旋轉(zhuǎn)部分和縮放部分。
同理, Cesium.Matrix4.getScale(matrix, new Cesium.Cartesian3()), Cesium.Matrix4.getRotation(matrix, new Cesium. Matrix3()) ,分別用于獲取縮放比例和旋轉(zhuǎn)部分。
Cesium.Matrix4.fromRotationTranslation(rotation, translation, result)
Cesium.Matrix4.fromScale(scale, result)
Cesium.Matrix4.fromTranslationQuaternionRotationScale(translation, rotation, scale, result)
Cesium.Matrix4.fromTranslationRotationScale(translationRotationScale, result)
如何可視化世界矩陣的局部坐標(biāo)系?文章來源:http://www.zghlxwxcb.cn/news/detail-695734.html
// 局部坐標(biāo)系的局部坐標(biāo)軸 ---核心代碼
addlocalAxis(parentMatrix, color) {
let parentPosition = Cesium.Matrix4.getTranslation(parentMatrix, new Cesium.Cartesian3());
this.addEntity(parentPosition, Cesium.Color.RED);
// 求矩陣的x軸基向量
// Cesium.Cartesian3.UNIT_X <=> new Cesium.Cartesian3(1, 0, 0)
const localAxisX = Cesium.Matrix4.multiplyByPointAsVector(parentMatrix, new Cesium.Cartesian3(1, 0, 0), new Cesium.Cartesian3());
// 求矩陣的y軸基向量
// Cesium.Cartesian3.UNIT_Y <=> new Cesium.Cartesian3(0, 1, 0)
const localAxisY = Cesium.Matrix4.multiplyByPointAsVector(parentMatrix, new Cesium.Cartesian3(0, 1, 0), new Cesium.Cartesian3());
// 求矩陣的z軸基向量
// Cesium.Cartesian3.UNIT_Z <=> new Cesium.Cartesian3(0, 0, 1)
const localAxisZ = Cesium.Matrix4.multiplyByPointAsVector(parentMatrix, new Cesium.Cartesian3(0, 0, 1), new Cesium.Cartesian3());
this.addPolyline(parentPosition, localAxisX, color);
this.addPolyline(parentPosition, localAxisY, color);
this.addPolyline(parentPosition, localAxisZ, color);
}
addPolyline(position, vector, color) {
return this.viewer.entities.add({
polyline: {
width: 10,
positions: [position, Cesium.Cartesian3.add(position, vector, new Cesium.Cartesian3())],
material: new Cesium.PolylineArrowMaterialProperty(
color
),
},
});
}
// 添加entity點
addEntity(position, color) {
return this.viewer.entities.add({
position: position,
point: {
color: color,
pixelSize: 10,
},
})
}
線性代數(shù),可能我們只學(xué)了它的計算,但其實更重要的是它的幾何含義。計算只是解決問題的工具,而明白其幾何含義幫助我們知道解決什么問題要用什么工具,以及如何解讀最終結(jié)果的含義,學(xué)無止境,繼續(xù)加油吧。文章來源地址http://www.zghlxwxcb.cn/news/detail-695734.html
到了這里,關(guān)于Cesium中常用的一些數(shù)學(xué)計算(矩陣、向量)用法——矩陣的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!