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

on 6 Mar 2013

### Teja Muppirala (view profile)

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```

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.

## Products

### Teja Muppirala (view profile)

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

Cameron Skinner

### Cameron Skinner (view profile)

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.

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