![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /**
00002 * MOAB, a Mesh-Oriented datABase, is a software component for creating,
00003 * storing and accessing finite element mesh data.
00004 *
00005 * Copyright 2004 Sandia Corporation. Under the terms of Contract
00006 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
00007 * retains certain rights in this software.
00008 *
00009 * This library is free software; you can redistribute it and/or
00010 * modify it under the terms of the GNU Lesser General Public
00011 * License as published by the Free Software Foundation; either
00012 * version 2.1 of the License, or (at your option) any later version.
00013 *
00014 */
00015
00016 #include "moab/HomXform.hpp"
00017 #include
00018
00019 namespace moab
00020 {
00021
00022 HomCoord HomCoord::unitv[3] = { HomCoord( 1, 0, 0 ), HomCoord( 0, 1, 0 ), HomCoord( 0, 0, 1 ) };
00023 HomCoord HomCoord::IDENTITY( 1, 1, 1 );
00024
00025 HomCoord& HomCoord::getUnitv( int c )
00026 {
00027 return unitv[c];
00028 }
00029
00030 int dum[] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
00031 HomXform HomXform::IDENTITY( dum );
00032
00033 void HomXform::three_pt_xform( const HomCoord& p1,
00034 const HomCoord& q1,
00035 const HomCoord& p2,
00036 const HomCoord& q2,
00037 const HomCoord& p3,
00038 const HomCoord& q3 )
00039 {
00040 // pmin and pmax are min and max bounding box corners which are mapped to
00041 // qmin and qmax, resp. qmin and qmax are not necessarily min/max corners,
00042 // since the mapping can change the orientation of the box in the q reference
00043 // frame. Re-interpreting the min/max bounding box corners does not change
00044 // the mapping.
00045
00046 // change that: base on three points for now (figure out whether we can
00047 // just use two later); three points are assumed to define an orthogonal
00048 // system such that (p2-p1)%(p3-p1) = 0
00049
00050 // use the three point rule to compute the mapping, from Mortensen,
00051 // "Geometric Modeling". If p1, p2, p3 and q1, q2, q3 are three points in
00052 // the two coordinate systems, the three pt rule is:
00053 //
00054 // v1 = p2 - p1
00055 // v2 = p3 - p1
00056 // v3 = v1 x v2
00057 // w1-w3 similar, with q1-q3
00058 // V = matrix with v1-v3 as rows
00059 // W similar, with w1-w3
00060 // R = V^-1 * W
00061 // t = q1 - p1 * W
00062 // Form transform matrix M from R, t
00063
00064 // check to see whether unity transform applies
00065 if( p1 == q1 && p2 == q2 && p3 == q3 )
00066 {
00067 *this = HomXform::IDENTITY;
00068 return;
00069 }
00070
00071 // first, construct 3 pts from input
00072 HomCoord v1 = p2 - p1;
00073 assert( v1.i() != 0 || v1.j() != 0 || v1.k() != 0 );
00074 HomCoord v2 = p3 - p1;
00075 HomCoord v3 = v1 * v2;
00076
00077 if( v3.length_squared() == 0 )
00078 {
00079 // 1d coordinate system; set one of v2's coordinates such that
00080 // it's orthogonal to v1
00081 if( v1.i() == 0 )
00082 v2.set( 1, 0, 0 );
00083 else if( v1.j() == 0 )
00084 v2.set( 0, 1, 0 );
00085 else if( v1.k() == 0 )
00086 v2.set( 0, 0, 1 );
00087 else
00088 assert( false );
00089 v3 = v1 * v2;
00090 assert( v3.length_squared() != 0 );
00091 }
00092 // assert to make sure they're each orthogonal
00093 assert( v1 % v2 == 0 && v1 % v3 == 0 && v2 % v3 == 0 );
00094 v1.normalize();
00095 v2.normalize();
00096 v3.normalize();
00097 // Make sure h is set to zero here, since it'll mess up things if it's one
00098 v1.homCoord[3] = v2.homCoord[3] = v3.homCoord[3] = 0;
00099
00100 HomCoord w1 = q2 - q1;
00101 assert( w1.i() != 0 || w1.j() != 0 || w1.k() != 0 );
00102 HomCoord w2 = q3 - q1;
00103 HomCoord w3 = w1 * w2;
00104
00105 if( w3.length_squared() == 0 )
00106 {
00107 // 1d coordinate system; set one of w2's coordinates such that
00108 // it's orthogonal to w1
00109 if( w1.i() == 0 )
00110 w2.set( 1, 0, 0 );
00111 else if( w1.j() == 0 )
00112 w2.set( 0, 1, 0 );
00113 else if( w1.k() == 0 )
00114 w2.set( 0, 0, 1 );
00115 else
00116 assert( false );
00117 w3 = w1 * w2;
00118 assert( w3.length_squared() != 0 );
00119 }
00120 // assert to make sure they're each orthogonal
00121 assert( w1 % w2 == 0 && w1 % w3 == 0 && w2 % w3 == 0 );
00122 w1.normalize();
00123 w2.normalize();
00124 w3.normalize();
00125 // Make sure h is set to zero here, since it'll mess up things if it's one
00126 w1.homCoord[3] = w2.homCoord[3] = w3.homCoord[3] = 0;
00127
00128 // form v^-1 as transpose (ok for orthogonal vectors); put directly into
00129 // transform matrix, since it's eventually going to become R
00130 *this = HomXform( v1.i(), v2.i(), v3.i(), 0, v1.j(), v2.j(), v3.j(), 0, v1.k(), v2.k(), v3.k(), 0, 0, 0, 0, 1 );
00131
00132 // multiply by w to get R
00133 *this *= HomXform( w1.i(), w1.j(), w1.k(), 0, w2.i(), w2.j(), w2.k(), 0, w3.i(), w3.j(), w3.k(), 0, 0, 0, 0, 1 );
00134
00135 // compute t and put into last row
00136 HomCoord t = q1 - p1 * *this;
00137 ( *this ).XFORM( 3, 0 ) = t.i();
00138 ( *this ).XFORM( 3, 1 ) = t.j();
00139 ( *this ).XFORM( 3, 2 ) = t.k();
00140
00141 // M should transform p to q
00142 assert( ( q1 == p1 * *this ) && ( q2 == p2 * *this ) && ( q3 == p3 * *this ) );
00143 }
00144
00145 } // namespace moab