常用的坐标转换模型有哪些? 常用的坐标转换模型如下: (1)三维七参数转换模型:用于不同地球椭球基准下的大地坐标系统间点位坐标转换,涉及三个平移参数,三个旋转参数和一个尺度因子,同时需顾及两种大地坐标系所对应的两个地球椭球长半轴和扁率差。 (2)二维七参数转换模型:用于不同地球椭球基准下的椭球面上的点位坐标转换,涉及三个平移参数,三个旋转参数和一个尺度因子。 (3)三维四参数转换模型:用于局部坐标系间的坐标转换,涉及三个平移参数和一个旋转参数。 (4)二维四参数转换模型:用于范围较小的不同高斯投影平面坐标转换,涉及两个平移参数,一个旋转参数和一个尺度因子。对于三维坐标,需将坐标通过高斯投影变换得到平面坐标,再计算转换参数。 (5)多项式拟合模型:用于全国/全省或相对独立的平面坐标系统转换。
三维坐标系之间的转换关系:R(旋转矩阵) 、T(平移矩阵) 在大地测量、工程测量、摄影测量等领域中,坐标系之间的转换是必不可少的。空间坐标转换的实质是用公共点的2套坐标和非公共点的1套坐标推估非公共点的另1套坐标。 坐标转换过程通常分2步,先由公共点坐标解算转换参数,再由转换参数转换非公共点。转换参数通常分为旋转、平移和尺度参数,其中旋转参数的确定是坐标转换的核心。 传统的三维坐标转换模型是用3个旋转角作为旋转参数,建立的模型是非线性的,常需要用泰勒级数展开的方法将模型线性化,计算比较繁杂。 在小角度旋转情况下,可对旋转矩阵作近似处理,得到线性模型,如常用的布尔莎模型。 针对大旋角的坐标转换问题,多采用罗德里格矩阵表示旋转矩阵的坐标转换方法,仅有3个旋转参数,计算过程无需线性化,且能适用大旋角转换。 https://zhuanlan.zhihu.com/p/458827599
通过3个以上的已知点求坐标转换系数
function [R,lambda,dxyz]= getCoordTransformPara_3dTo3d(xyzs,XYZs) %该函数用来进行坐标转换 %输入xyzs:xyz坐标系的点,每一行代表一个点,3列,分别表示x,y,z %输入XYZs:同上 %输出R:旋转矩阵 %输出lambda:缩放因子,暂定为1 %这两行是测试代码 %xyzs = [0,2,0;2,0,0;1,1,2]; %XYZs = [-1,1,-1;1,-1,-1;0,0,1]; xs = xyzs(:,1)';ys = xyzs(:,2)';zs = xyzs(:,3)'; Xs = XYZs(:,1)';Ys = XYZs(:,2)';Zs = XYZs(:,3)'; xn1s = xs(2:end)-xs(1); yn1s = ys(2:end)-ys(1);zn1s = zs(2:end)-zs(1); Xn1s = Xs(2:end)-Xs(1);Yn1s = Ys(2:end)-Ys(1);Zn1s = Zs(2:end)-Zs(1); lambda = 1; n_point = length(xs); A = []; for i = 1:n_point-1 A = [A; 0 ,-lambda* zn1s(i)-Zn1s(i) , -lambda*yn1s(i)-Yn1s(i); -lambda* zn1s(i)-Zn1s(i), 0 ,lambda* xn1s(i)+Xn1s(i); lambda*yn1s(i)+Yn1s(i), lambda* xn1s(i)+Xn1s(i) ,0 ]; end L = []; for i = 1:n_point-1 L = [L ; Xn1s(i) - lambda * xn1s(i); Yn1s(i) - lambda * yn1s(i); Zn1s(i) - lambda * zn1s(i) ]; end X = inv(A'*A)*A'*L; a = X(1); b=X(2);c = X(3); %[a,b,c] = X'; R = 1/(1+a^2+b^2+c^2)*[1+a^2-b^2-c^2 , -2*c-2*a*b , -2*b+2*a*c ; 2*c-2*a*b , 1-a^2+b^2-c^2 , -2*a-2*b*c ; 2*b+2*a*c , 2*a-2*b*c , 1-a^2-b^2+c^2 ]; dxyz = [Xs(1);Ys(1);Zs(1)] - lambda*R*[xs(1);ys(1);zs(1)];
那么相应的坐标转换的函数 就写为
function [XYZs]= coordTransform_3dTo3d(xyzs,R,lambda,dxyz) [m,n] = size(xyzs); XYZs = []; for i = 1: m u = lambda * R * xyzs(i,:)'+dxyz; XYZs = [XYZs;u']; end
写一个代码对上述过程进行测试
xyzs_base = [-2,-2,0;-(2-sqrt(2)/2),-(2+sqrt(2)/2),0;-2,-2,2];%世界坐标系 XYZs_base = [0,0,0;0,1,0;1,0,0];%摄像头坐标系 [R,lambda,dxyz]= getCoordTransformPara_3dTo3d(xyzs_base,XYZs_base); %坐标转换 xyzs = [0,0,0;1,0,0;1,1,0;0,1,0;0,0,1;1,0,1;1,1,1;0,1,1]; faces = [1,2,3,4;5,8,7,6;8,4,3,7;5,6,2,1;5,1,4,8;6,7,3,2]; [XYZs]= coordTransform_3dTo3d(xyzs,R,lambda,dxyz); for i_face = 1:length(faces(:,1)) h = fill(XYZs(faces(i_face,:),1),XYZs(faces(i_face,:),2),[0.8,0.8,0.8]); set(h,'facealpha',0.3); hold on; end
通常我们在软件中进行3维预览时,往往通过拖动鼠标来移动视角(实际就是变化摄像头坐标),这时就需要把三个标准点也进行绕轴旋转,基本原理在https://blog.csdn.net/maple_2014/article/details/104443928
x = nx * t + x0; y = ny * t + y0; z = nz * t + z0; t0 = solve(nx * (x - px) + ny * (y - py) + nz * (z - pz) == 0, t) %} t0 = nx * (px - x0) + ny * (py - y0) + nz * (pz - z0); xc = x0 + nx * t0; yc = y0 + ny * t0; zc = z0 + nz * t0; r = sqrt((px - xc)^2 + (py - yc)^2 + (pz - zc)^2); OP = [px - xc; py - yc; pz - zc] / r; yVector = cross([nx; ny; nz], OP); R = [OP, yVector, [nx; ny; nz]]; xtemp = r * cos(alpha); ytemp = r * sin(alpha); p = [R(1,1) * xtemp + R(1,2) * ytemp + xc R(2,1) * xtemp + R(2,2) * ytemp + yc R(3,1) * xtemp + R(3,2) * ytemp + zc]; p = [simplify(p(1)); simplify(p(2)); simplify(p(3))] %% 写成矩阵形式,并验证结果正确性 K = 1 - cos(alpha); M = nx * x0 + ny * y0 + nz * z0; T = [nx^2 * K + cos(alpha), nx * ny * K - nz * sin(alpha), nx * nz * K + ny * sin(alpha), (x0 - nx * M) * K + (nz * y0 - ny * z0) * sin(alpha) nx * ny * K + nz * sin(alpha), ny^2 * K + cos(alpha), ny * nz * K - nx * sin(alpha), (y0 - ny * M) * K + (nx * z0 - nz * x0) * sin(alpha) nx * nz * K - ny * sin(alpha), ny * nz * K + nx * sin(alpha), nz^2 * K + cos(alpha), (z0 - nz * M) * K + (ny * x0 - nx * y0) * sin(alpha) 0, 0, 0, 1] res = simplify([nx^2 * K + cos(alpha), nx * ny * K - nz * sin(alpha), nx * nz * K + ny * sin(alpha), (x0 - nx * M) * K + (nz * y0 - ny * z0) * sin(alpha) nx * ny * K + nz * sin(alpha), ny^2 * K + cos(alpha), ny * nz * K - nx * sin(alpha), (y0 - ny * M) * K + (nx * z0 - nz * x0) * sin(alpha) nx * nz * K - ny * sin(alpha), ny * nz * K + nx * sin(alpha), nz^2 * K + cos(alpha), (z0 - nz * M) * K + (ny * x0 - nx * y0) * sin(alpha) 0, 0, 0, 1] * [px; py; pz; 1] - [p(1); p(2); p(3); 1])
另外一种更直观的方法是让视野中一点A跟随鼠标位置,固定平面上一点O,类似于摇杆操作,那么求B点的程序如下
function ABO = getABO(A1,O1,l,d); %设A点坐标为(xA,yA,zA),xA、yA为已知 %O点坐标为(xO,yO,0),是已知的 %下面开始推导: xO = O1(1); yO =O1(2); xA = A1(1); yA = A1(2); OA1 = sqrt((xA-xO)^2+(yA-yO)^2); zA = sqrt(l^2-OA1^2); theta1 = acos(OA1/l); theta2 = atan((xO-xA) /(yO-yA)); %以下代码用来求斜角 dd = 1/cos(theta1); ee = 1/cos(theta2); ff2= tan(theta1)^2+tan(theta2)^2; theta3 = acos((dd^2+ee^2-ff2)/(2*dd*ee)); %求B的坐标 zB = d/tan(theta3)*sin(theta1); OE = d/sin(theta3); xE = xO; yE = yO+OE; xB = xE - zB/tan(theta1)*sin(theta2); yB = yE - zB/tan(theta1)*cos(theta2); A =[xA,yA,zA]; B = [xB,yB,zB]; O = [xO,yO,0]; ABO = [A;B;O];
获得B后我们就可以根据三点求旋转参数,进而求出其他点的坐标,用鼠标控制摇杆位置的程序如下所示
function main() clc;clear all; figure(); text(0,0.5,'图中点击,将会看到跟随移动的立方体'); set(gcf,'WindowButtonDownFcn',@ButttonDownFcn); end function ButttonDownFcn(src,event) pt = get(gca,'CurrentPoint'); x = pt(1,1); y = pt(1,2); l = 10; %手柄长度 d = 2;%手柄半宽度 A = [0,0,l];%物体坐标系中的点 B = [0,d,0]; O=[0,0,0]; A1 = [x,y]; O1 = [0,0]; ABO = getABO(A1,O1,l,d);%世界坐标系中的点 [R,lambda,dxyz]= getCoordTransformPara_3dTo3d([A;B;O],ABO); %坐标转换 xyzs = [-d,-d,0;-d,d,0;d,d,0;d,-d,0;-d,-d,l;-d,d,l;d,d,l;d,-d,l]; faces = [1,2,3,4;5,6,7,8;1,2,6,5;3,4,8,7;1,5,8,4;2,6,7,3]; [XYZs]= coordTransform_3dTo3d(xyzs,R,lambda,dxyz); la = 10; x_axis = [0,-la/720,0;la,-la/720,0;la,-la/180,0;la+la/20,0,0;la,la/180,0;la,la/720,0;0,la/720,0]; %绘制坐标轴 fill(x_axis(:,1),x_axis(:,2),[0.8,0.8,0.8]);hold on; text(la+la/20,la/20,'x'); fill(x_axis(:,2),x_axis(:,1),[0.8,0.8,0.8]);hold on text(la/20,la+la/20,0,'y'); %绘制两个面 for i_face = 1:length(faces(:,1)) h = fill(XYZs(faces(i_face,:),1),XYZs(faces(i_face,:),2),[0.8,0.8,0.8]); set(h,'facealpha',0.3); hold on; end axis([-l*1.2, l *1.2,-l*1.2, l*1.2 ]); hold off end============================找指导老师布置任务吧==============================