Code covered by the BSD License  

Highlights from
Adjust Plane to Given Normal

image thumbnail

Adjust Plane to Given Normal



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

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';
        error('transformCartCoord:InputSizeMismatch', ...
        'second (and third) input must be a 3x3 matrix or vectors with 2 or 3 entries');
elseif 3 == nargin  %just call the function recursivly to keep the code tidy
    newCoordinates = transformCartCoord(oldCoordinates, inputA);
    newCoordinates = transformCartCoord(newCoordinates, inputB);
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');
%----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;
    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);
    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';
        %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.


Contact us