Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

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

Asked by Cameron Skinner on 6 Mar 2013

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.

0 Comments

Cameron Skinner

Products

1 Answer

Answer by Teja Muppirala on 6 Mar 2013
Accepted answer

%% 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));

1 Comment

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.

Teja Muppirala

Contact us