3D Tiles的4x4的仿射变换矩阵
前言
项目需要,使用Cesium技术,把STL格式模型加载进去。
一、格式转换
第一步,先将STL文件转换为glTF格式
第二步,将glTF文件转换为3D Tiles格式,使用Cesium ion
二、矩阵整体结构
这个矩阵是一个4x4的仿射变换矩阵,用于在3D Tiles中描述模型的位置、旋转和缩放。
[
a, b, c, d,
e, f, g, h,
i, j, k, l,
m, n, o, p
]
- 第一到第三行前三列表示旋转矩阵
[
a, b, c,
e, f, g,
i, j, k,
]
- 第四行前三列(m, n, o)表示平移向量,
p
为齐次坐标的标准形式。
[
m, n, o,p
]
其实就是它的模型的位置
地心坐标系(ECEF: Earth-Centered, Earth-Fixed): 在这个坐标系中,地球的中心被定义为原点,X、Y、Z 轴固定在地球上并随地球自转。通常,X 轴指向本初子午线和赤道的交点,Y 轴指向90度经度和赤道的交点,Z 轴指向北极。
3D Tiles: 通常包含几何、材质、纹理等信息,使用的是地心坐标系来定义这些信息在地球表面的位置。
具体值替换,通过其他手段获取【模型目标放置位置】的经纬度,再转成地心坐标系ECEF。
三、经纬度转地心坐标系ECEF
将经纬度转换为地心坐标系 (ECEF, Earth-Centered, Earth-Fixed) 坐标系的步骤如下:
1. 了解坐标系
-
经纬度: 地理坐标系,表示地球表面的位置。由纬度 (latitude, φ)、经度 (longitude, λ) 和高度 (altitude, h) 定义。
- 纬度 φ: 从赤道向北或向南的角度,范围为 -90°(南极)到 90°(北极)。
- 经度 λ: 从本初子午线向东或向西的角度,范围为 -180°(西)到 180°(东)。
- 高度 h: 海拔高度,即点到地球表面的垂直距离。
-
地心坐标系 (ECEF): 地心为原点,X 轴指向赤道与本初子午线的交点,Y 轴指向赤道与经度 90° 的交点,Z 轴指向北极。
2. 转换公式
要将经纬度 (φ, λ, h) 转换为地心坐标系下的 (X, Y, Z) 坐标,需使用以下公式:
3. 示例代码 (Python)
import math
def lat_lon_to_ecef(lat, lon, alt):
# 常量
a = 6378137.0 # 长半轴 (meters)
b = 6356752.314245 # 短半轴 (meters)
e2 = 1 - (b**2 / a**2) # 离心率平方
# 将角度转换为弧度
lat_rad = math.radians(lat)
lon_rad = math.radians(lon)
# 计算N
N = a / math.sqrt(1 - e2 * math.sin(lat_rad)**2)
# 计算X, Y, Z
X = (N + alt) * math.cos(lat_rad) * math.cos(lon_rad)
Y = (N + alt) * math.cos(lat_rad) * math.sin(lon_rad)
Z = ((1 - e2) * N + alt) * math.sin(lat_rad)
return X, Y, Z
# 示例
lat = 52.2296756 # 纬度
lon = 21.0122287 # 经度
alt = 100 # 高度 (meters)
x, y, z = lat_lon_to_ecef(lat, lon, alt)
print(f"ECEF坐标: X={x}, Y={y}, Z={z}")
4. 结果解释
- X, Y, Z 表示点在地心坐标系中的位置。
- 在地心坐标系中,坐标的单位通常为米 (meters)。
5. 应用场景
- 地图渲染:将经纬度转换为地心坐标系,用于三维地球模型或地图渲染。
- 卫星导航:将卫星的经纬度位置转换为地心坐标系,用于定位和跟踪。
通过上述公式和代码,你可以将任何经纬度坐标转换为地心坐标系 (ECEF) 的三维坐标。
四、矩阵详细参数介绍
这个矩阵通常用于3D图形学中进行平移、旋转、缩放和投影变换。以下是该矩阵中每个字母的位置和意义的详细说明:
1. 矩阵形式
原矩阵格式为:
[ a, b, c, d ]
[ e, f, g, h ]
[ i, j, k, l ]
[ m, n, o, p ]
2. 每个字母的意义
a. 旋转与缩放部分(3x3部分):
- [a, b, c]:第一行描述的是X轴方向的旋转和缩放。
- [e, f, g]:第二行描述的是Y轴方向的旋转和缩放。
- [i, j, k]:第三行描述的是Z轴方向的旋转和缩放。
具体来说:
a
,f
,k
:沿着X、Y、Z轴的缩放因子。
变大变小,比如把加载进来的模型缩小10倍,这三个字母全部 乘 0.1 。剩下懂吧。
b
,c
,e
,g
,i
,j
:描述旋转的混合项,表示在X、Y、Z轴之间的旋转关系。
注意!!!!!
进行旋转操作前一定要先把缩放因子先全部改为1,旋转完后再改回去!!!
下面是使用Python实现计算3D仿真变换矩阵的代码,可以沿X轴、Y轴或Z轴旋转一个给定角度,并输出对应的旋转矩阵。
import numpy as np
def rotation_matrix_x(theta):
"""返回绕X轴旋转theta角度的4x4变换矩阵"""
return np.array([
[1, 0, 0, 0],
[0, np.cos(theta), -np.sin(theta), 0],
[0, np.sin(theta), np.cos(theta), 0],
[0, 0, 0, 1]
])
def rotation_matrix_y(theta):
"""返回绕Y轴旋转theta角度的4x4变换矩阵"""
return np.array([
[np.cos(theta), 0, np.sin(theta), 0],
[0, 1, 0, 0],
[-np.sin(theta), 0, np.cos(theta), 0],
[0, 0, 0, 1]
])
def rotation_matrix_z(theta):
"""返回绕Z轴旋转theta角度的4x4变换矩阵"""
return np.array([
[np.cos(theta), -np.sin(theta), 0, 0],
[np.sin(theta), np.cos(theta), 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
])
# 示例:旋转45度(π/4弧度)
theta = np.pi / 4
# 计算沿X轴、Y轴、Z轴旋转的矩阵
R_x = rotation_matrix_x(theta)
R_y = rotation_matrix_y(theta)
R_z = rotation_matrix_z(theta)
print("Rotation matrix around X axis:\n", R_x)
print("Rotation matrix around Y axis:\n", R_y)
print("Rotation matrix around Z axis:\n", R_z)
说明
theta
是旋转角度,以弧度为单位。如果你有角度,可以使用np.radians(angle_in_degrees)
来转换为弧度。rotation_matrix_x
,rotation_matrix_y
, 和rotation_matrix_z
函数分别计算绕X轴、Y轴、Z轴旋转的4x4变换矩阵。- 输出结果是对应轴旋转后的4x4矩阵。
运行这个代码后,你会得到沿各轴旋转45度的变换矩阵。可以根据需要调整 theta
来得到不同的旋转矩阵。
b. 平移部分(第四列的前三个元素):
- [d, h, l]:描述的是物体在X、Y、Z轴上的平移(移动)。
d
:表示X轴方向的平移。h
:表示Y轴方向的平移。l
:表示Z轴方向的平移。
c. 齐次坐标部分(第四行):
- [m, n, o]:理论上应该是[0, 0, 0],表示在平移变换中不涉及旋转或缩放的部分。
- p:通常为1,表示齐次坐标系统中的一个常数,用于确保矩阵的维度一致性。
3. 简化的理解
- 旋转:
a
,f
,k
主要控制旋转的缩放因子,b
,c
,e
,g
,i
,j
控制不同轴之间的旋转关系。 - 缩放:
a
,f
,k
也可以控制物体在X、Y、Z轴方向上的缩放比例。 - 平移:
d
,h
,l
直接控制物体的移动。单位为米。 - 齐次性:
p
保证矩阵的齐次特性(通常为1),m
,n
,o
通常为0。
4. 示例应用
- 如果你只需要一个简单的平移矩阵,a=f=k=1, b=c=e=g=i=j=0, d, h, l分别是X, Y, Z方向的平移量,p为1。
- 如果你只需要旋转,比如绕Z轴旋转θ角度,那么a=cos(θ), b=-sin(θ), e=sin(θ), f=cos(θ),其余元素为0或1(没有缩放和平移)。
5. 总结
- a, f, k:控制X、Y、Z方向的缩放。
- b, c, e, g, i, j:控制不同轴之间的旋转关系。
- d, h, l:控制X、Y、Z方向的平移。
- m, n, o:通常是0,表示没有额外的仿射变换。
- p:通常为1,表示矩阵的齐次性。