Metashape chunk的坐标系统真是一个谜。
首先,生成的点云是在reference setting中用户所设置的Coordinate System下的。但是chunk.region.center就搞不清楚到底在哪个坐标系下了。这样的话我想通过脚本来改变chunk.region的位置和大小就无从下手了。
于是我不得不去查阅官方提供的API文档,有这么一段:
transform
4x4 matrix specifying chunk location in the world coordinate system.
Type ChunkTransform
就这么短短一句话,说transform属性是一个4x4的矩阵,规定了chunk在世界坐标系下的位置,然后类型为ChunkTransform。点击跳到ChunkTransform的定义后,可以看到:
class Metashape.ChunkTransform
Transformation between chunk and world coordinates systems.
copy()
Return a copy of the object.
Returns A copy of the object.
Return type ChunkTransform
matrix
Transformation matrix.
Type Matrix
rotation
Rotation component.
Type Matrix
scale
Scale component.
Type float
translation
Translation component.
Type Vector
可以看到这个类里面有4个属性,分别为matrix、rotation、scale、translation,是不是很熟悉?没错,就是咱们做7参数转换时需要用到的东西。其中rotation为3x3的旋转矩阵,translation为平移参数向量,scale为尺度缩放参数。至于matrix,则是将前面三个东西放在一起搞成4x4的变换矩阵而已,方便计算。也就是说,你可以用rotation、translation和scale进行坐标转换,也可以直接用matrix进行转换,结果都是一样的。
我们现在知道chunk提供了进行坐标转换的东西,那么这是从哪个坐标系转换到哪个坐标系下的呢?
我到现在都不知道chunk.region.center到底属于哪个坐标系,但是从其显示的数值可以判断它是一个局部坐标系,也可能就是Metashape自己定义的。但是使用上文中的matrix对其进行转换后却得到了一组类似地心直角坐标系的坐标,说类似是因为我把XYZ坐标的平方求和后开根号得到了与地球半径很接近的结果,并且用地球半径乘以region.center代表的纬度值的正弦值,得到的结果和Z坐标几乎相同。不管了,我就当它是地心直角坐标系吧。
从reference setting中可以查到地心坐标系中有好多可以选择,我就选了最简单的WGS-84(EPSG::4978),如图:
这样的话,我们可以先将我们希望设为中心的那组坐标转换到这个地心坐标系下,然后将chunk.region.center设为该转换后的地心坐标,然后通过matrix的逆矩阵反变换回chunk.region.center原来所在的局部坐标系下。这样就大功告成了。具体操作如下:
import Metashape
chunk=Metashape.app.document.chunk
#chunk中心的坐标(chunk局部坐标系下)
center=chunk.region.center
#chunk的变换矩阵matrix
matrix=chunk.transform.matrix
#定义Metashape内置的坐标系
ccs=Metashape.CoordinateSystem("EPSG::4978") #GeoCentric Coordinate System WGS-84
pcs=Metashape.CoordinateSystem("EPSG::32650") #UTM zone 50N坐标系 WGS-84
#我自己想要设为中心的坐标(WGS-84 UTM Zone 50N坐标系下,就是举个例子)
center_pcs=Metashape.Vector([x,y,z]) #x,y,z请自行替换
#将我自己的坐标变换到地心坐标系下
center_ccs=Metashape.CoordinateSystem.transform(center_pcs,pcs,ccs)
center_ccs=Metashape.Vector((center_ccs[0],center_ccs[1],center_ccs[2],1)) #调整坐标维度
#通过matrix逆变换得到chunk.region.center局部坐标系下的坐标
center_loc=matrix.inv()*center_ccs
#将chunk.region.center设为上一把变换后的地心坐标
chunk.region.center=Metashape.Vector((center_loc[0],center_loc[1],center_loc[2]))
print("----------大功告成!---------------")