Code covered by the BSD License

# Adjust Plane to Given Normal

### Bastian Tietjen (view profile)

27 Mar 2013 (Updated )

Adjust a more or less planar point cloud so that it fits a given normal vector.

transformCartCoord(oldCoordinates, inputA, inputB)
```function newCoordinates = transformCartCoord(oldCoordinates, inputA, inputB)
%Manipulate cartesian coordinates based on axis and angle, transformation
%matrix or vector offset.
%
%Revolve coordinates around axis:
%
%   function newCoordinates = transformCartCoord(oldCoordinates, T)
%
%oldCoordinates is a matrix with the minimum size 1x3, with no maximum side
%to either dimension. Each three succesive columns (e.g.
%oldCoordinates(:,1:3), oldCoordinates(:,4:6)) are treated as a
%x,y,z-coordinate to which the transformation is applied. If the number of
%columns is not a multiple of three, the remaining one or two columns are
%ignored (but not deleted). So if the columns correspond to e.g. a point
%coordinate, a vector and a scalar [x,y,z,u,v,w,abs] the coordinate and
%vector are transformed, the remaining scalar just copied (handy for the
%magnitude of the vector which doesn't change).
%T has the form [axis, angle]. The coordinates are revolved around the axis
%(1 for x, 2 for y and 3 for z) by the angle in radiants.
%
%Apply transformation matrix cartesian coordinates:
%
%   function newCoordinates = transformCartCoord(oldCoordinates, T)
%
%T is the transformation matrix T = [e_x, e_y, e_z]', where e_* is the
%respective unit vector of the new coordinate system represented in the old
%coordinate system. T must be of size 3x3. In the case of revolving a
%coordinate system around it's z-axis by the angle alpha they are for
%example:
%
%      /cos(alpha)\         /-sin(alpha)\         /0\
%e_x = |sin(alpha)| ; e_y = |cos(alpha) | ; e_z = |0|
%      \   0      /         \     0     /         \1/
%
%Hence, for alpha = 90�, T would be:
%
%    | 0 1 0|
%T = |-1 0 0|
%    | 0 0 1|
%
%The new coordinate is then computed as
%
%coord_new = T * (x,y,z)'
%
%Offsets cartesion coordinates:
%
%   function newCoordinates = transformCartCoord(oldCoordinates, offset)
%
%If called with this way, the last argument must be a vector with
%three entries which are added only to the first three columns of each row
%therefore relocating the coordinates.
%
%Transforms and then offsets the coordiantes:
%
%   function newCoordinates = transformCartCoord(oldCoordinates, T, offset)
%
%Equals to first calling a revolving/transformation and then an offest. If
%the last two arguments are switched, it equals to first calling an offset
%and then a revolving/transformation. In principle, it is possible for both
%arguments to be offsets or revolvings/transformations, which are then
%applied in the order of input.
%
%by Bastian Tietjen, released March 2013 under a Simplified BSD licence.

%----Check number and validity of input arguments--------------------------
if 3 > size(oldCoordinates,2)   %must contain at least three column entries
error('transformCartCoord:InputSizeMismatch', ...
'oldCoordinates must contain at least three columns');
end

if 2 == nargin	%The main function block below is always called with inputA!
%More inputs = recursive call to transformCartCoord itself!

if 3 == size(inputA, 1) && 3 == size(inputA, 2)   %means it is a 3x3 matrix
manipulationToPerform = 'transform';
elseif ( 1 == size(inputA, 1) && 2 == size(inputA, 2) ) || ...
( 2 == size(inputA, 1) && 1 == size(inputA, 2) )  %vector with 2 entries
manipulationToPerform = 'axisRevolve';
elseif ( 1 == size(inputA, 1) && 3 == size(inputA, 2) ) || ...
( 3 == size(inputA, 1) && 1 == size(inputA, 2) )  %vector with 3 entries
manipulationToPerform = 'spatialOffset';
else
error('transformCartCoord:InputSizeMismatch', ...
'second (and third) input must be a 3x3 matrix or vectors with 2 or 3 entries');
end

elseif 3 == nargin  %just call the function recursivly to keep the code tidy

newCoordinates = transformCartCoord(oldCoordinates, inputA);
newCoordinates = transformCartCoord(newCoordinates, inputB);
return

elseif 2 > nargin   %too little...

error('transformCartCoord:TooFewInputs', ...
'at least two inputs are required');

elseif 3 < nargin   %too much... (obsolete)

error('transformCartCoord:TooManyInputs', ...
'at most three inputs are required');
end
%----Check number and validity of input arguments end----------------------

%----start of actual function block----------------------------------------

%This here is ALWAYS a call with to inputs (oldCoordinates and inputA), see
%above. Therefore, no matter if it is a matrix or a vector, the input name
%is always inputA

%declare return value to avoid growing in loops
newCoordinates = oldCoordinates;
clear oldCoordinates

switch manipulationToPerform

case 'transform'    %the call was with a transformation matrix as checked above

%declare counter and apply the multiplication r * T to each three
%succesive elements of oldCoordinates. For speed purposes it makes use
%of the fact that (Tr)' = r' * T' instead of T * r and transposing the
%resulting column vector to a row vector
i = 1;
while i <= (size(newCoordinates,2) - 2)
newCoordinates(:,i:i+2) = newCoordinates(:,i:i+2) * inputA';
i = i+3;
end

case 'axisRevolve'        %revolve around axis

%this will just create the corresponding transformation matrix and
%call transformCartCoord with it

cosineAngle = cos(inputA(2));
sinusAngle = sin(inputA(2));

switch inputA(1)

case 1

T = [1, 0, 0; ...
0, cosineAngle, sinusAngle; ...
0, -sinusAngle, cosineAngle];

newCoordinates = transformCartCoord(newCoordinates, T);

case 2

T = [cosineAngle, 0, -sinusAngle; ...
0, 1, 0; ...
sinusAngle, 0, cosineAngle];

newCoordinates = transformCartCoord(newCoordinates, T);

case 3

T = [cosineAngle, sinusAngle, 0; ...
-sinusAngle, cosineAngle, 0; ...
0 0 1];

newCoordinates = transformCartCoord(newCoordinates, T);
end

case 'spatialOffset'    %the call was with an offset vector as checked above

%offset must be a column vector
if size(inputA, 2) == 1
inputA = inputA';
end

%create a vector with the same number of columns as the oldCoordinates
B = zeros(1, size(newCoordinates,2));
%replace the first three entries of B with the offset/inputA
B(1:3) = inputA;
%Utilize bsxfun to add B to each row of oldCoordinates
newCoordinates = bsxfun(@plus, newCoordinates, B);
%the whole procedure reduces the computing speed by a factor of 100 for
%oldCoordinates with 1e5 rows and 5 columns, compared to a for loop
%iterating through each row.

end

end
```