600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > cesium 缩放_Cesium 中的图形变换:局部平移 缩放 旋转思路及代码实现

cesium 缩放_Cesium 中的图形变换:局部平移 缩放 旋转思路及代码实现

时间:2019-02-21 02:01:49

相关推荐

cesium 缩放_Cesium 中的图形变换:局部平移 缩放 旋转思路及代码实现

开门见山:tileset.modelMatrix

这个属性可以在数据本身的基础上再进行坐标变换,不熟悉转换矩阵各个部分的含义的可参考图形学有关资料。

此文不一定是最佳算法,但是提供一种思路。转载请注明出处 全网@秋意正寒 。

平移思路

获取当前瓦片数据集的包裹范围(boundingSphere)中心(此时参考系是世界坐标)

计算当参考系是局部坐标时,此位置为原点的局部坐标系,到世界坐标的转换矩阵(eastNorthUpToFixedFrame)

利用上一步的转换矩阵,左乘一个局部平移向量,得到此平移向量在世界坐标系下的平移目标位置(矩阵×向量,结果是向量)

向量相减:世界坐标系下,指向平移目标点位的目标向量 - 指向数据集中心的向量,得到世界坐标系下的平移向量。

将世界坐标系下的平移向量转换成平移矩阵,赋予 tileset.modelMatrix

代码

tileset

.readyPromise

.then(tileset => {

const tileset_center = tileset.boundingSphere.center; // Cartesian3

const frompoint_to_world_matrix = Cesium.Transforms.eastNorthUpToFixedFrame(tileset_center); // Matrix4

const local_translation = new Cesium.Cartesian3(310, -140, 10); // 向模型中心为原点,正北为y,正东为x,地心朝上为z分别平移 310、-140、10米

const result = new Cesium.Cartesian3(0,0,0);

Cesium.Matrix4.multiplyByPoint(frompoint_to_world_matrix, local_translation, result); // 转换矩阵左乘局部平移向量,结果存储在 result 中,结果是世界坐标下的平移终点向量

const targetpoint_to_world_matrix = Cesium.Transforms.eastNorthUpToFixedFrame(result);

const world_translation = new Cesium.Cartesian3(

targetpoint_to_world_matrix[12] - frompoint_to_world_matrix[12],

targetpoint_to_world_matrix[13] - frompoint_to_world_matrix[13],

targetpoint_to_world_matrix[14] - frompoint_to_world_matrix[14],

); // 向量相减,得到世界坐标下的平移向量

tileset.modelMatrix = Cesium.Matrix4.fromTranslation(world_translation); // 构造平移矩阵并赋值

viewer.zoomTo(tileset);

});

图解

解释:

红点:frompoint(地表点)

蓝点:targetpoint(frompoint局部坐标向东向北向上偏移各 310、-140、10米 后得到的目标点)

红向量:地表点向量

蓝向量:目标点向量

绿向量:平移向量。如果是局部坐标,那么就是 (310, -140, 10),如果是世界坐标下的,那就是 蓝向量 - 红向量

cesium 的场景数据最终都是世界坐标的,所以要求的是绿向量的世界坐标表达,然后构造平移矩阵。

现在是已知红向量和局部坐标的绿向量,要先求蓝向量,才能得到世界坐标的绿向量。

平移思路二

先平移到世界坐标中心,然后在世界坐标中心求平移,最后再移动回原点。

tileset.modelMatrix \(= M_{backToOrigin}·M_{localTranslation}·M_{moveToWorldCenter}\)

读者可自行实现。

旋转思路

局部旋转,应该先将模型移动到世界坐标中心,旋转后,再移动到原来的地方

tileset.modelMatrix \(= M_{backToOrigin}·M_{localRotate}·M_{moveToWorldCenter}\)

其中,\(M_{moveToWorldCenter}\) 是一个平移矩阵,只需使用模型中心向量取个负值即可

\(M_{backToOrigin}\) 则是从世界坐标中心再移动到模型原点

注意,这里是左乘优先顺序,从右往左乘。

旋转矩阵比较容易构造,就不细说了。

这个思路的计算量比较大!

效果图(绕模型本身x轴转90度)

代码

tileset

.readyPromise

.then(tileset => {

const tileset_center = tileset.boundingSphere.center; // Cartesian3

//console.log(tileset_center);

const backto_matrix = Cesium.Matrix4.fromTranslation(tileset_center);

const moveto_vec = Cesium.Cartesian3.multiplyByScalar(tileset_center, -1, new Cesium.Cartesian3());

//console.log(moveto_vec);

const moveto_matrix = Cesium.Matrix4.fromTranslation(moveto_vec);

/* 绕x(即东方轴)转90度 */

const cos_rotateX = Math.cos(Math.PI/2);

const sin_rotateX = Math.sin(Math.PI/2);

const arr = [1,0,0,0, 0, cos_rotateX, sin_rotateX,0, 0,-sin_rotateX,cos_rotateX,0, 0,0,0,1];

const rotateX_matrix = Cesium.Matrix4.fromArray(arr);

/* 计算最终矩阵 */

const temp = Cesium.Matrix4.multiply(rotateX_matrix, moveto_matrix, new Cesium.Matrix4());

const r = Cesium.Matrix4.multiply(backto_matrix, temp, new Cesium.Matrix4());

tileset.modelMatrix = r; // 构造平移矩阵并赋值

viewer.zoomTo(tileset);

});

可以看到会产生非常多中间变量,会引发 JS 的GC,而且矩阵计算本身也比较复杂。

缩放思路

缩放思路和旋转类似,先移动到世界坐标系中心,缩放,然后再移动到原来的地方

tileset.modelMatrix \(= M_{backToOrigin}·M_{localScale}·M_{moveToWorldCenter}\)

读者可自行实现。

思路不一定是最佳算法,有更高性能的算法可在评论区指出。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。