How do I move a cloud of points in 3D so that they are centered along the x-axis?

46 views (last 30 days)
Hi All,
I have a set of approximately 2 million (x,y,z) points collected from a surface scan of an object that is roughly parallel to the x axis. The object is offset from the origin and is at a small angle. I would like to:
1- translate the points so that they "sit" in the x>0 space
2- rotate the group of points so that the object's axis in on the x-axis
3- rotate the group of points about the x-axis to align the the object's faces with the x-y plane.
So far I have approached this by finding the center of the y and z data (medians actually) at each of the roughly 900 x positions to create an approximation to the axis of the object. I then found how to fit a line through this data (see below) but I am a little stymied at this stage.
Here is a sampling of the x,y,z median data:
XYZ=
10.0000 504.0000 219.0000
20.0000 490.0000 223.0000
30.0000 499.0000 223.0000
40.0000 488.0000 233.0000
50.0000 474.0000 231.0000
60.0000 471.0000 226.0000
70.0000 465.0000 232.0000
80.0000 489.5000 224.0000
90.0000 473.0000 224.5000
100.0000 469.0000 228.0000
110.0000 480.0000 231.0000
120.0000 481.0000 230.5000
130.0000 488.5000 231.0000
140.0000 477.0000 228.0000
150.0000 499.0000 214.0000
160.0000 488.0000 226.5000
170.0000 491.0000 221.0000
180.0000 488.0000 221.5000
190.0000 488.0000 220.0000
200.0000 495.0000 222.0000
210.0000 494.0000 224.0000
220.0000 482.0000 223.5000
230.0000 483.0000 224.0000
240.0000 486.0000 222.0000
250.0000 489.5000 217.0000
260.0000 483.0000 219.0000
270.0000 481.0000 220.0000
280.0000 480.0000 218.0000
290.0000 464.0000 235.0000
300.0000 492.0000 219.0000
310.0000 485.0000 218.0000
320.0000 485.0000 218.0000
330.0000 480.0000 225.0000
340.0000 493.0000 228.0000
350.0000 490.0000 231.0000
360.0000 483.0000 222.0000
370.0000 486.0000 224.0000
380.0000 483.0000 226.0000
390.0000 479.0000 225.0000
400.0000 480.0000 226.0000
410.0000 483.0000 225.0000
420.0000 479.0000 230.0000
430.0000 492.5000 221.0000
440.0000 487.0000 223.0000
450.0000 487.0000 225.0000
460.0000 487.0000 227.0000
470.0000 490.0000 223.0000
480.0000 486.0000 225.0000
490.0000 487.0000 227.0000
500.0000 485.0000 225.0000
510.0000 486.0000 226.0000
520.0000 483.0000 228.0000
530.0000 494.5000 221.0000
540.0000 497.0000 222.0000
550.0000 487.5000 226.0000
560.0000 489.0000 226.0000
570.0000 488.0000 225.0000
580.0000 484.0000 228.0000
590.0000 484.0000 227.0000
600.0000 493.0000 225.0000
610.0000 488.5000 227.0000
620.0000 497.0000 223.0000
630.0000 496.0000 226.0000
640.0000 495.5000 226.0000
650.0000 496.0000 225.0000
660.0000 494.0000 226.0000
670.0000 494.0000 226.0000
680.0000 501.0000 225.0000
690.0000 488.0000 223.0000
700.0000 490.0000 224.0000
710.0000 486.0000 222.0000
720.0000 496.0000 225.5000
730.0000 525.5000 213.0000
740.0000 499.0000 223.0000
750.0000 508.0000 218.0000
760.0000 475.0000 226.0000
770.0000 478.0000 220.0000
780.0000 472.0000 217.0000
790.0000 486.0000 225.0000
800.0000 495.0000 224.0000
810.0000 501.0000 223.0000
820.0000 493.0000 226.0000
830.0000 488.0000 227.0000
840.0000 496.0000 226.0000
850.0000 485.5000 229.0000
Following MattJ's suggestion (<http://www.mathworks.com/matlabcentral/newsreader/view_thread/302926>) I did:
xyz0=mean(XYZ);
A=bsxfun(@minus,XYZ,xyz0); %center the data
[U,S,V]=svd(A);
xyz0,
direction=cross(V(:,end),V(:,end-1)),
which yields
xyz0 = 430.0000 487.6471 224.4000
direction =
0.9999
0.0127
-0.0013
I would like to use this information to do the translation and alignment to the x-axis. Initially I would like to apply this transformation to the XYZ data (above) just to "see" that it works then I'll try it with the full set of data. Any help or direction to appropriate answers would be very welcome. Once I have jumped this hurdle I can then begin thinking about how to fit a surface to my data and rotate it so that the surface(s) are parallel to the x-y plane. There are a couple of answers already "out there" for the rotation in a plane that I have tried and it seems to work.
Thank you! Cameron.

Accepted Answer

Teja Muppirala
Teja Muppirala on 6 Mar 2013
%% Step 1. Center the data at zero:
xyz0=mean(XYZ);
A=bsxfun(@minus,XYZ,xyz0); %center the data
scatter3(A(:,1),A(:,2),A(:,3));
%% Step 2. Find the direction of most variance using SVD and rotate the data to make that the x axis. (Your data is almost perfectly aligned with the x-axis to begin with).
[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));
%% Step 3. Slide the data up the x axis so all the points are x >= 0.
A_final = bsxfun(@minus,A_rot,[min(A_rot(:,1)) 0 0]);
scatter3(A_final(:,1),A_final(:,2),A_final(:,3));
  2 Comments
Cameron Skinner
Cameron Skinner on 6 Mar 2013
Hi Teja,
Thanks, this worked the charm! I was able to apply the rotation and translation to the full set of data and noticed what seems to be a nice side-effect (maybe you intended/knew it was going to happen?). The full set of data appears to be already aligned parallel with the x-y plane and doesn't require rotation about the x-axis.
My understanding of SVD is fragmentary at the very best and its been 20 years since I've done any matrix mathematics. Oh Boy!!
Thanks again. C.
Math Enthusiast
Math Enthusiast on 30 Oct 2018
Hi,
Can we also apply it in case of 2D For any kind of Data.I have different contours (2D Points) at various orientations. Basically these are vertices of lines,square,rectangle,ellipse etc. With the above code,can I make sure,its aligned properly with X-Axis?

Sign in to comment.

More Answers (0)

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!