How Do I Move a Set of (x,y,z) Points so they Align with the X-Y Plane?
20 views (last 30 days)
Show older comments
Hi all,
I have a large set of (x,y,z) data points creating a “bumpy” (non-flat) surface that I am trying to get to “flatten out” onto the x-y plane without losing any integrity of the surface features.
I tried following the suggestion here
but the asker was specific to ask for their data to follow along the x axis. I am trying to get my data to fall along the x-y plane in whatever angle it originates at. It does not necessarily need to be centered at zero or anything (in my example it is, but I would not like it to), just flattened to the x-y plane using only the given (x,y,z) data.
With the help of the above suggestion, I’ve tried this code:
XYZ = [11 11 11
12 12 13
13 13 12
14 14 15
15 15 17
16 16 17
17 17 18
18 18 18
19 19 20
10 12 12
11 13 11
12 14 13
13 15 14
14 16 19
15 17 13
16 18 15
17 19 18
18 20 17
12 10 11
13 11 13
14 12 14
15 13 12
16 14 17
17 15 19
18 16 18
19 17 15
20 18 19];
X = XYZ(:,1);
Y = XYZ(:,2);
Z = XYZ(:,3);
% Plot the raw data
scatter3(X,Y,Z,'b','LineWidth',5) % blue dots
xlabel('X-Axis','FontSize',14,'FontWeight','bold')
ylabel('Y-Axis','FontSize',14,'FontWeight','bold')
zlabel('Z-Axis','FontSize',14,'FontWeight','bold')
xyz0=mean(XYZ);
A=bsxfun(@minus,XYZ,xyz0); % center the data at zero
% Find the direction of most variance using SVD and rotate the data to make
% that the x-axis
[U,S,V]=svd(A,0);
A_rot = A*V; % V(:,1) is the direction of most variance
hold on
scatter3(A_rot(:,1),A_rot(:,2),A_rot(:,3),'g','LineWidth',5); % green dots
This code centers the data at (0,0,0), flattens it out, and rotates it in the direction of most variance (close to the x-axis) while making use of the svd function. I’m looking to see if I can keep the plot in the same position at its same x-y position, but flatten it down from its z position. I don’t believe I can simply adjust the data by a specific angle, because other surfaces may not be at a nice easy angle and I will not always know what the angle is. It simply needs to be moved down with the same surface features into the x-y plane.
If anybody can help me out on this, it would be very much appreciated, and thank you in advance.
0 Comments
Answers (2)
Preetham Manjunatha
on 23 Jul 2021
Fit a oriented bounding box and obtain the orientation of that bounding box and invert the rotation matrix of the Euler angles. This will produce a re-orientated point cloud that is parallel to XY, YZ and XZ planes. If you need to rotate again, Eulaer angles [phi theta psi] can be used, for example [90 0 0] or [-90 0 0] and others. The program which does this can be downloaded at 3DspaceTile.
This program actually divides the 3D space, one can use the divisions as [1 1 1] in XYZ directions. Same program can reorient the point clouds to be parallel to XY, YZ and XZ planes. For the program requirements, please visit the GitHub page.
Hope this helps someone in future.
3 Comments
Bruno Luong
on 20 Apr 2022
Edited: Bruno Luong
on 20 Apr 2022
@TB I don't know about your code, but here is three rotations to bring the data to resp YZ, ZX, and XY plane
[Q,~] = qr(randn(3));
n = 500;
sigma = 0.01;
ptCloudOriginal = (rand(n,3).*[1 1 0] + sigma*randn(n,3)) * Q;
[~,~,V]=svd(ptCloudOriginal-mean(ptCloudOriginal,1),0);
N = V(:,3);
close all
scatter3(ptCloudOriginal(:,1),ptCloudOriginal(:,2),ptCloudOriginal(:,3));
hold on
for i=1:3
axisi = accumarray(i,1,[3 1]);
a=cross(N,axisi);
T=makehgtform('axisrotate', a, -atan2(norm(a),N(i)));
R=T(1:3,1:3);
XYZ_rot = ptCloudOriginal*R;
scatter3(XYZ_rot(:,1),XYZ_rot(:,2),XYZ_rot(:,3),'marker','.');
end
axis equal
Preetham Manjunatha
on 20 Apr 2022
@TB could you please share before and after transformed point clouds?
Bruno Luong
on 20 Apr 2022
Edited: Bruno Luong
on 20 Apr 2022
I guess what you describe as "but flatten it down from its z position"" or "move down" is that you want to rotate about the axis that is parallel to x-y plane (?). In this case try this code
NOTE: incidently this is also the most economical way (smalest roration angle) to rotate the point cloud to be parallel to x-y plane
% XYZ = [11 11 11
% 12 12 13
% 13 13 12
% 14 14 15
% 15 15 17
% 16 16 17
% 17 17 18
% 18 18 18
% 19 19 20
% 10 12 12
% 11 13 11
% 12 14 13
% 13 15 14
% 14 16 19
% 15 17 13
% 16 18 15
% 17 19 18
% 18 20 17
% 12 10 11
% 13 11 13
% 14 12 14
% 15 13 12
% 16 14 17
% 17 15 19
% 18 16 18
% 19 17 15
% 20 18 19];
[Q,~] = qr(randn(3));
n = 500;
sigma = 0.02;
XYZ = (rand(n,3).*[1 1 0] + sigma*randn(n,3)) * Q;
X = XYZ(:,1);
Y = XYZ(:,2);
Z = XYZ(:,3);
xyz0=mean(XYZ,1);
A=XYZ-xyz0; % center the data at zero
% Find the direction of most variance using SVD and rotate the data to make
% that the x-axis
[~,~,V]=svd(A,0);
a=cross(V(:,3),[0;0;1]);
T=makehgtform('axisrotate', a, -atan2(norm(a),V(3,3)));;
R=T(1:3,1:3);
A_rot = A*R;
A_rot = A_rot + [xyz0(1) xyz0(2) 0]; % move so the centers are aligned in z-diection
% Plot the raw data
close all
scatter3(X,Y,Z,'b','LineWidth',2) % blue dots
hold on
scatter3(A_rot(:,1),A_rot(:,2),A_rot(:,3),'g','LineWidth',2); % green dots
xlabel('X-Axis','FontSize',14,'FontWeight','bold')
ylabel('Y-Axis','FontSize',14,'FontWeight','bold')
zlabel('Z-Axis','FontSize',14,'FontWeight','bold')
axis equal
0 Comments
See Also
Categories
Find more on Surface and Mesh Plots in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!