/* ----------------------------------------------------------------------------
@COPYRIGHT :
Copyright 1993,1994,1995 David MacDonald,
McConnell Brain Imaging Centre,
Montreal Neurological Institute, McGill University.
Permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without
fee is hereby granted, provided that the above copyright
notice appear in all copies. The author and McGill University
make no representations about the suitability of this
software for any purpose. It is provided "as is" without
express or implied warranty.
---------------------------------------------------------------------------- */
#include <internal_volume_io.h>
#ifndef lint
static char rcsid[] = "$Header: /software/source/minc/cvsroot/minc/volume_io/Geometry/transforms.c,v 1.20 2004/10/04 20:23:51 bert Exp $";
#endif
/* ----------------------------- MNI Header -----------------------------------
@NAME : make_identity_transform
@INPUT :
@OUTPUT : transform
@RETURNS :
@DESCRIPTION: Fills in the transform with the identity matrix.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void make_identity_transform( Transform *transform )
{
Transform_elem( *transform, 0, 0 ) = 1.0;
Transform_elem( *transform, 0, 1 ) = 0.0;
Transform_elem( *transform, 0, 2 ) = 0.0;
Transform_elem( *transform, 0, 3 ) = 0.0;
Transform_elem( *transform, 1, 0 ) = 0.0;
Transform_elem( *transform, 1, 1 ) = 1.0;
Transform_elem( *transform, 1, 2 ) = 0.0;
Transform_elem( *transform, 1, 3 ) = 0.0;
Transform_elem( *transform, 2, 0 ) = 0.0;
Transform_elem( *transform, 2, 1 ) = 0.0;
Transform_elem( *transform, 2, 2 ) = 1.0;
Transform_elem( *transform, 2, 3 ) = 0.0;
Transform_elem( *transform, 3, 0 ) = 0.0;
Transform_elem( *transform, 3, 1 ) = 0.0;
Transform_elem( *transform, 3, 2 ) = 0.0;
Transform_elem( *transform, 3, 3 ) = 1.0;
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : close_to_identity
@INPUT : transform
@OUTPUT :
@RETURNS : TRUE if transform is close to identity
@DESCRIPTION:
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI BOOLEAN close_to_identity(
Transform *transform )
{
#define TOLERANCE 0.001
BOOLEAN close;
Real expected_val;
int i, j;
close = TRUE;
for_less( i, 0, 4 )
{
for_less( j, 0, 4 )
{
if( i == j )
expected_val = 1.0;
else
expected_val = 0.0;
if( Transform_elem(*transform,i,j) < expected_val - TOLERANCE ||
Transform_elem(*transform,i,j) > expected_val + TOLERANCE )
{
close = FALSE;
}
}
}
return( close );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : get_transform_origin
@INPUT : transform
@OUTPUT : origin
@RETURNS :
@DESCRIPTION: Passes back the origin of the transform, i.e., where the
point (0,0,0) would be transformed to.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void get_transform_origin(
Transform *transform,
Point *origin )
{
fill_Point( *origin,
Transform_elem(*transform,0,3),
Transform_elem(*transform,1,3),
Transform_elem(*transform,2,3) );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : set_transform_origin
@INPUT : origin
@OUTPUT : transform
@RETURNS :
@DESCRIPTION: Sets the origin of the transform, i.e., where the
point (0,0,0) would be transformed to.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void set_transform_origin(
Transform *transform,
Point *origin )
{
Transform_elem(*transform,0,3) = (Transform_elem_type) Point_x(*origin);
Transform_elem(*transform,1,3) = (Transform_elem_type) Point_y(*origin);
Transform_elem(*transform,2,3) = (Transform_elem_type) Point_z(*origin);
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : get_transform_origin_real
@INPUT : transform
@OUTPUT : origin
@RETURNS :
@DESCRIPTION: Passes back the origin of the transform, i.e., where the
point (0,0,0) would be transformed to.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : May 20, 1997 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void get_transform_origin_real(
Transform *transform,
Real origin[] )
{
origin[X] = Transform_elem(*transform,0,3);
origin[Y] = Transform_elem(*transform,1,3);
origin[Z] = Transform_elem(*transform,2,3);
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : get_transform_x_axis
@INPUT : transform
@OUTPUT : x_axis
@RETURNS :
@DESCRIPTION: Passes back the x axis of the transform, i.e., the vector
to which the vector (1,0,0) would be transformed.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void get_transform_x_axis(
Transform *transform,
Vector *x_axis )
{
fill_Vector( *x_axis,
Transform_elem(*transform,0,0),
Transform_elem(*transform,1,0),
Transform_elem(*transform,2,0) );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : get_transform_x_axis_real
@INPUT : transform
@OUTPUT : x_axis
@RETURNS :
@DESCRIPTION: Passes back the x axis of the transform, i.e., the vector
to which the vector (1,0,0) would be transformed.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : May 20, 1997 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void get_transform_x_axis_real(
Transform *transform,
Real x_axis[] )
{
x_axis[X] = Transform_elem(*transform,0,0);
x_axis[Y] = Transform_elem(*transform,1,0);
x_axis[Z] = Transform_elem(*transform,2,0);
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : set_transform_x_axis
@INPUT : x_axis
@OUTPUT : transform
@RETURNS :
@DESCRIPTION: Sets the x axis of the transform, i.e., the vector
to which the vector (1,0,0) would be transformed.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void set_transform_x_axis(
Transform *transform,
Vector *x_axis )
{
Transform_elem(*transform,0,0) = (Transform_elem_type) Vector_x(*x_axis);
Transform_elem(*transform,1,0) = (Transform_elem_type) Vector_y(*x_axis);
Transform_elem(*transform,2,0) = (Transform_elem_type) Vector_z(*x_axis);
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : set_transform_x_axis_real
@INPUT : x_axis
@OUTPUT : transform
@RETURNS :
@DESCRIPTION: Sets the x axis of the transform, i.e., the vector
to which the vector (1,0,0) would be transformed.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : May 20, 1997 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void set_transform_x_axis_real(
Transform *transform,
Real x_axis[] )
{
Transform_elem(*transform,0,0) = (Transform_elem_type) x_axis[X];
Transform_elem(*transform,1,0) = (Transform_elem_type) x_axis[Y];
Transform_elem(*transform,2,0) = (Transform_elem_type) x_axis[Z];
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : get_transform_y_axis
@INPUT : transform
@OUTPUT : y_axis
@RETURNS :
@DESCRIPTION: Passes back the y axis of the transform, i.e., the vector
to which the vector (0,1,0) would be transformed.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void get_transform_y_axis(
Transform *transform,
Vector *y_axis )
{
fill_Vector( *y_axis,
Transform_elem(*transform,0,1),
Transform_elem(*transform,1,1),
Transform_elem(*transform,2,1) );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : get_transform_y_axis_real
@INPUT : transform
@OUTPUT : y_axis
@RETURNS :
@DESCRIPTION: Passes back the y axis of the transform, i.e., the vector
to which the vector (0,1,0) would be transformed.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : May 20, 1997 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void get_transform_y_axis_real(
Transform *transform,
Real y_axis[] )
{
y_axis[X] = Transform_elem(*transform,0,1);
y_axis[Y] = Transform_elem(*transform,1,1);
y_axis[Z] = Transform_elem(*transform,2,1);
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : set_transform_y_axis
@INPUT : y_axis
@OUTPUT : transform
@RETURNS :
@DESCRIPTION: Sets the y axis of the transform, i.e., the vector
to which the vector (0,1,0) would be transformed.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void set_transform_y_axis(
Transform *transform,
Vector *y_axis )
{
Transform_elem(*transform,0,1) = (Transform_elem_type) Vector_x(*y_axis);
Transform_elem(*transform,1,1) = (Transform_elem_type) Vector_y(*y_axis);
Transform_elem(*transform,2,1) = (Transform_elem_type) Vector_z(*y_axis);
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : set_transform_y_axis_real
@INPUT : y_axis
@OUTPUT : transform
@RETURNS :
@DESCRIPTION: Sets the y axis of the transform, i.e., the vector
to which the vector (0,1,0) would be transformed.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : May 20, 1997 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void set_transform_y_axis_real(
Transform *transform,
Real y_axis[] )
{
Transform_elem(*transform,0,1) = (Transform_elem_type) y_axis[X];
Transform_elem(*transform,1,1) = (Transform_elem_type) y_axis[Y];
Transform_elem(*transform,2,1) = (Transform_elem_type) y_axis[Z];
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : get_transform_z_axis
@INPUT : transform
@OUTPUT : z_axis
@RETURNS :
@DESCRIPTION: Passes back the z axis of the transform, i.e., the vector
to which the vector (0,0,1) would be transformed.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void get_transform_z_axis(
Transform *transform,
Vector *z_axis )
{
fill_Vector( *z_axis,
Transform_elem(*transform,0,2),
Transform_elem(*transform,1,2),
Transform_elem(*transform,2,2) );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : get_transform_z_axis_real
@INPUT : transform
@OUTPUT : z_axis
@RETURNS :
@DESCRIPTION: Passes back the z axis of the transform, i.e., the vector
to which the vector (0,0,1) would be transformed.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : May 20, 1997 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void get_transform_z_axis_real(
Transform *transform,
Real z_axis[] )
{
z_axis[X] = Transform_elem(*transform,0,2);
z_axis[Y] = Transform_elem(*transform,1,2);
z_axis[Z] = Transform_elem(*transform,2,2);
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : set_transform_z_axis
@INPUT : z_axis
@OUTPUT : transform
@RETURNS :
@DESCRIPTION: Sets the z axis of the transform, i.e., the vector
to which the vector (0,0,1) would be transformed.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void set_transform_z_axis(
Transform *transform,
Vector *z_axis )
{
Transform_elem(*transform,0,2) = (Transform_elem_type) Vector_x(*z_axis);
Transform_elem(*transform,1,2) = (Transform_elem_type) Vector_y(*z_axis);
Transform_elem(*transform,2,2) = (Transform_elem_type) Vector_z(*z_axis);
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : set_transform_z_axis_real
@INPUT : z_axis
@OUTPUT : transform
@RETURNS :
@DESCRIPTION: Sets the z axis of the transform, i.e., the vector
to which the vector (0,0,1) would be transformed.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : May 20, 1997 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void set_transform_z_axis_real(
Transform *transform,
Real z_axis[] )
{
Transform_elem(*transform,0,2) = (Transform_elem_type) z_axis[X];
Transform_elem(*transform,1,2) = (Transform_elem_type) z_axis[Y];
Transform_elem(*transform,2,2) = (Transform_elem_type) z_axis[Z];
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : make_change_to_bases_transform
@INPUT : origin
x_axis
y_axis
z_axis
@OUTPUT : transform
@RETURNS :
@DESCRIPTION: Creates a transform that translates the point (0,0,0) to the
specified origin. The point (1,0,0) is transformed to the
specified origin plus the specified x_axis.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void make_change_to_bases_transform(
Point *origin,
Vector *x_axis,
Vector *y_axis,
Vector *z_axis,
Transform *transform )
{
Transform_elem( *transform,0,0 ) = (Transform_elem_type)Vector_x( *x_axis );
Transform_elem( *transform,0,1 ) = (Transform_elem_type)Vector_x( *y_axis );
Transform_elem( *transform,0,2 ) = (Transform_elem_type)Vector_x( *z_axis );
Transform_elem( *transform,0,3 ) = (Transform_elem_type)Point_x( *origin );
Transform_elem( *transform,1,0 ) = (Transform_elem_type)Vector_y( *x_axis );
Transform_elem( *transform,1,1 ) = (Transform_elem_type)Vector_y( *y_axis );
Transform_elem( *transform,1,2 ) = (Transform_elem_type)Vector_y( *z_axis );
Transform_elem( *transform,1,3 ) = (Transform_elem_type)Point_y( *origin );
Transform_elem( *transform,2,0 ) = (Transform_elem_type)Vector_z( *x_axis );
Transform_elem( *transform,2,1 ) = (Transform_elem_type)Vector_z( *y_axis );
Transform_elem( *transform,2,2 ) = (Transform_elem_type)Vector_z( *z_axis );
Transform_elem( *transform,2,3 ) = (Transform_elem_type)Point_z( *origin );
Transform_elem( *transform,3,0 ) = 0.0;
Transform_elem( *transform,3,1 ) = 0.0;
Transform_elem( *transform,3,2 ) = 0.0;
Transform_elem( *transform,3,3 ) = 1.0;
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : make_change_from_bases_transform
@INPUT : origin
x_axis
y_axis
z_axis
@OUTPUT :
@RETURNS :
@DESCRIPTION: Makes a change of bases transform, so that points are transformed
to be relative to the given axes. For instance the origin is
transformed by the change of bases transform to be point (0,0,0).
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void make_change_from_bases_transform(
Point *origin,
Vector *x_axis,
Vector *y_axis,
Vector *z_axis,
Transform *transform )
{
Transform_elem(*transform,0,0) = (Transform_elem_type)Vector_x( *x_axis );
Transform_elem(*transform,0,1) = (Transform_elem_type)Vector_y( *x_axis );
Transform_elem(*transform,0,2) = (Transform_elem_type)Vector_z( *x_axis );
Transform_elem(*transform,0,3) = (Transform_elem_type)
- DOT_POINT_VECTOR( *origin, *x_axis );
Transform_elem(*transform,1,0) = (Transform_elem_type)Vector_x( *y_axis );
Transform_elem(*transform,1,1) = (Transform_elem_type)Vector_y( *y_axis );
Transform_elem(*transform,1,2) = (Transform_elem_type)Vector_z( *y_axis );
Transform_elem(*transform,1,3) = (Transform_elem_type)
- DOT_POINT_VECTOR( *origin, *y_axis );
Transform_elem(*transform,2,0) = (Transform_elem_type)Vector_x( *z_axis );
Transform_elem(*transform,2,1) = (Transform_elem_type)Vector_y( *z_axis );
Transform_elem(*transform,2,2) = (Transform_elem_type)Vector_z( *z_axis );
Transform_elem(*transform,2,3) = (Transform_elem_type)
- DOT_POINT_VECTOR( *origin, *z_axis );
Transform_elem(*transform,3,0) = 0.0;
Transform_elem(*transform,3,1) = 0.0;
Transform_elem(*transform,3,2) = 0.0;
Transform_elem(*transform,3,3) = 1.0;
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : concat_transforms
@INPUT : t1
t2
@OUTPUT : result
@RETURNS :
@DESCRIPTION: Concatenates the two transforms returning the result in the
argument, 'result'. Correctly handles the case where the
result transform is also one of the operands. Transforming
a point by the 'result' transform will give the same point
as first transforming the point by 't1', then by 't2'.
@METHOD : Multiplies result = t2 * t1
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void concat_transforms(
Transform *result,
Transform *t1,
Transform *t2 )
{
int i, j, k;
Real sum;
BOOLEAN result_is_also_an_arg;
Transform tmp, *t;
/*--- check if the result transform is same as one of the arguments */
if( result == t1 || result == t2 )
{
result_is_also_an_arg = TRUE;
t = &tmp;
}
else
{
result_is_also_an_arg = FALSE;
t = result;
}
/*--- perform multiplication */
for_less( i, 0, 4 )
{
for_less( j, 0, 4 )
{
sum = 0.0;
for_less( k, 0, 4 )
{
sum += Transform_elem( *t2, i, k ) *
Transform_elem( *t1, k, j );
}
Transform_elem( *t, i, j ) = sum;
}
}
if( result_is_also_an_arg )
*result = tmp;
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : homogenous_transform_point
@INPUT : transform
x
y
z
w
@OUTPUT : x_trans
y_trans
z_trans
@RETURNS :
@DESCRIPTION: Transforms the point (x,y,z,w) by the homogenous transform
matrix, resulting in (x_trans,y_trans,z_trans).
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
static void homogenous_transform_point(
Transform *transform,
Real x,
Real y,
Real z,
Real w,
Real *x_trans,
Real *y_trans,
Real *z_trans )
{
Real w_trans;
*x_trans = Transform_elem(*transform,0,0) * x +
Transform_elem(*transform,0,1) * y +
Transform_elem(*transform,0,2) * z +
Transform_elem(*transform,0,3) * w;
*y_trans = Transform_elem(*transform,1,0) * x +
Transform_elem(*transform,1,1) * y +
Transform_elem(*transform,1,2) * z +
Transform_elem(*transform,1,3) * w;
*z_trans = Transform_elem(*transform,2,0) * x +
Transform_elem(*transform,2,1) * y +
Transform_elem(*transform,2,2) * z +
Transform_elem(*transform,2,3) * w;
w_trans = Transform_elem(*transform,3,0) * x +
Transform_elem(*transform,3,1) * y +
Transform_elem(*transform,3,2) * z +
Transform_elem(*transform,3,3) * w;
if( w_trans != 0.0 && w_trans != 1.0 )
{
*x_trans /= w_trans;
*y_trans /= w_trans;
*z_trans /= w_trans;
}
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : transform_point
@INPUT : transform
x
y
z
@OUTPUT : x_trans
y_trans
z_trans
@RETURNS :
@DESCRIPTION: Transforms the point (x,y,z) by the transform matrix, resulting
in (x_trans,y_trans,z_trans).
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void transform_point(
Transform *transform,
Real x,
Real y,
Real z,
Real *x_trans,
Real *y_trans,
Real *z_trans )
{
homogenous_transform_point( transform, x, y, z, 1.0,
x_trans, y_trans, z_trans );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : transform_vector
@INPUT : transform
x
y
z
@OUTPUT : x_trans
y_trans
z_trans
@RETURNS :
@DESCRIPTION: Transforms the vector by the specified transform.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void transform_vector(
Transform *transform,
Real x,
Real y,
Real z,
Real *x_trans,
Real *y_trans,
Real *z_trans )
{
homogenous_transform_point( transform, x, y, z, 0.0,
x_trans, y_trans, z_trans );
}
syntax highlighted by Code2HTML, v. 0.9.1