MOAB: Mesh Oriented datABase  (version 5.2.1)
LVQDTargetCalculator.cpp
Go to the documentation of this file.
00001 /* *****************************************************************
00002     MESQUITE -- The Mesh Quality Improvement Toolkit
00003 
00004     Copyright 2006 Sandia National Laboratories.  Developed at the
00005     University of Wisconsin--Madison under SNL contract number
00006     624796.  The U.S. Government and the University of Wisconsin
00007     retain certain rights to 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     This library is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017     Lesser General Public License for more details.
00018 
00019     You should have received a copy of the GNU Lesser General Public License
00020     (lgpl.txt) along with this library; if not, write to the Free Software
00021     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 
00023     (2006) kraftche@cae.wisc.edu
00024 
00025   ***************************************************************** */
00026 
00027 /** \file LVQDTargetCalculator.cpp
00028  *  \brief
00029  *  \author Jason Kraftcheck
00030  */
00031 
00032 #include "Mesquite.hpp"
00033 #include "LVQDTargetCalculator.hpp"
00034 #include "MsqMatrix.hpp"
00035 #include "MsqError.hpp"
00036 #include <algorithm>
00037 #include <assert.h>
00038 
00039 namespace MBMesquite
00040 {
00041 
00042 int LVQDTargetCalculator::add_source( TargetCalculator* source )
00043 {
00044     if( !source ) return -1;
00045     int idx = std::find( uniqueGuides, uniqueGuides + numUniqueGuides, source ) - uniqueGuides;
00046     if( idx == numUniqueGuides )
00047     {
00048         assert( idx < 4 );
00049         uniqueGuides[idx] = source;
00050         ++numUniqueGuides;
00051     }
00052     return idx;
00053 }
00054 
00055 LVQDTargetCalculator::LVQDTargetCalculator( TargetCalculator* lambda_source, TargetCalculator* V_source,
00056                                             TargetCalculator* Q_source, TargetCalculator* delta_source )
00057     : numUniqueGuides( 0 )
00058 {
00059     lambdaIdx = add_source( lambda_source );
00060     vIdx      = add_source( V_source );
00061     qIdx      = add_source( Q_source );
00062     deltaIdx  = add_source( delta_source );
00063 }
00064 
00065 LVQDTargetCalculator::~LVQDTargetCalculator() {}
00066 
00067 bool LVQDTargetCalculator::have_surface_orient() const
00068 {
00069     return ( vIdx >= 0 );
00070 }
00071 
00072 bool LVQDTargetCalculator::get_3D_target( PatchData& pd, size_t element, Sample sample, MsqMatrix< 3, 3 >& W_out,
00073                                           MsqError& err )
00074 {
00075     double lambda[4];
00076     MsqMatrix< 3, 3 > V[4], Q[4], delta[4], W;
00077     bool valid;
00078 
00079     for( int i = 0; i < numUniqueGuides; ++i )
00080     {
00081         valid = uniqueGuides[i]->get_3D_target( pd, element, sample, W, err );
00082         if( MSQ_CHKERR( err ) || !valid ) return false;
00083         valid = factor_3D( W, lambda[i], V[i], Q[i], delta[i], err );
00084         if( MSQ_CHKERR( err ) || !valid ) return false;
00085     }
00086 
00087     if( vIdx >= 0 )
00088     {
00089         W_out = V[vIdx];
00090         if( lambdaIdx >= 0 ) W_out *= lambda[lambdaIdx];
00091         if( qIdx >= 0 ) W_out = W_out * Q[qIdx];
00092         if( deltaIdx >= 0 ) W_out = W_out * delta[deltaIdx];
00093     }
00094     else if( qIdx >= 0 )
00095     {
00096         W_out = Q[qIdx];
00097         if( lambdaIdx >= 0 ) W_out *= lambda[lambdaIdx];
00098         if( deltaIdx >= 0 ) W_out = W_out * delta[deltaIdx];
00099     }
00100     else if( deltaIdx >= 0 )
00101     {
00102         W_out = delta[deltaIdx];
00103         if( lambdaIdx >= 0 ) W_out *= lambda[lambdaIdx];
00104     }
00105     else if( lambdaIdx >= 0 )
00106     {
00107         W_out = MsqMatrix< 3, 3 >( lambda[lambdaIdx] );
00108     }
00109     else
00110     {
00111         W_out = MsqMatrix< 3, 3 >( 1.0 );
00112     }
00113 
00114     return true;
00115 }
00116 
00117 bool LVQDTargetCalculator::evaluate_guide_2D( PatchData& pd, size_t element, Sample sample, int idx, double& lambda,
00118                                               MsqMatrix< 3, 2 >& V, MsqMatrix< 2, 2 >& Q, MsqMatrix< 2, 2 >& delta,
00119                                               MsqError& err )
00120 {
00121     bool valid;
00122     if( uniqueGuides[idx]->have_surface_orient() )
00123     {
00124         MsqMatrix< 3, 2 > W;
00125         valid = uniqueGuides[idx]->get_surface_target( pd, element, sample, W, err );
00126         if( MSQ_CHKERR( err ) || !valid ) return false;
00127         valid = factor_surface( W, lambda, V, Q, delta, err );
00128         if( MSQ_CHKERR( err ) || !valid ) return false;
00129     }
00130     else
00131     {
00132         MsqMatrix< 2, 2 > W;
00133         valid = uniqueGuides[idx]->get_2D_target( pd, element, sample, W, err );
00134         if( MSQ_CHKERR( err ) || !valid ) return false;
00135         MsqMatrix< 2, 2 > junk;
00136         valid = factor_2D( W, lambda, junk, Q, delta, err );
00137         if( MSQ_CHKERR( err ) || !valid ) return false;
00138         V = MsqMatrix< 3, 2 >( 1.0 );
00139     }
00140     return true;
00141 }
00142 
00143 bool LVQDTargetCalculator::get_2D_target( PatchData& pd, size_t element, Sample sample, MsqMatrix< 2, 2 >& W_out,
00144                                           MsqError& err )
00145 {
00146     double lambda[4];
00147     MsqMatrix< 3, 2 > V[4];
00148     MsqMatrix< 2, 2 > W, Q[4], delta[4];
00149     bool valid;
00150 
00151     if( have_surface_orient() )
00152     {
00153         MSQ_SETERR( err )( "Incorrect surface mesh target type", MsqError::INTERNAL_ERROR );
00154         return false;
00155     }
00156 
00157     for( int i = 0; i < numUniqueGuides; ++i )
00158     {
00159         valid = evaluate_guide_2D( pd, element, sample, i, lambda[i], V[i], Q[i], delta[i], err );
00160         if( MSQ_CHKERR( err ) || !valid ) return false;
00161     }
00162 
00163     if( qIdx >= 0 )
00164     {
00165         W_out = Q[qIdx];
00166         if( lambdaIdx >= 0 ) W_out *= lambda[lambdaIdx];
00167         if( deltaIdx >= 0 ) W_out = W_out * delta[deltaIdx];
00168     }
00169     else if( deltaIdx >= 0 )
00170     {
00171         W_out = delta[deltaIdx];
00172         if( lambdaIdx >= 0 ) W_out *= lambda[lambdaIdx];
00173     }
00174     else if( lambdaIdx >= 0 )
00175     {
00176         W_out = MsqMatrix< 2, 2 >( lambda[lambdaIdx] );
00177     }
00178     else
00179     {
00180         W_out = MsqMatrix< 2, 2 >( 1.0 );
00181     }
00182 
00183     return true;
00184 }
00185 
00186 bool LVQDTargetCalculator::get_surface_target( PatchData& pd, size_t element, Sample sample, MsqMatrix< 3, 2 >& W_out,
00187                                                MsqError& err )
00188 {
00189     double lambda[4];
00190     MsqMatrix< 3, 2 > V[4], W;
00191     MsqMatrix< 2, 2 > Q[4], delta[4], junk, W2;
00192     bool valid;
00193 
00194     if( !have_surface_orient() )
00195     {
00196         MSQ_SETERR( err )( "Incorrect surface mesh target type", MsqError::INTERNAL_ERROR );
00197         return false;
00198     }
00199 
00200     for( int i = 0; i < numUniqueGuides; ++i )
00201     {
00202         valid = evaluate_guide_2D( pd, element, sample, i, lambda[i], V[i], Q[i], delta[i], err );
00203         if( MSQ_CHKERR( err ) || !valid ) return false;
00204     }
00205 
00206     if( vIdx >= 0 )
00207     {
00208         W_out = V[vIdx];
00209         if( lambdaIdx >= 0 ) W_out *= lambda[lambdaIdx];
00210         if( qIdx >= 0 ) W_out = W_out * Q[qIdx];
00211         if( deltaIdx >= 0 ) W_out = W_out * delta[deltaIdx];
00212     }
00213     else if( qIdx >= 0 )
00214     {
00215         W_out( 0, 0 ) = Q[qIdx]( 0, 0 );
00216         W_out( 0, 1 ) = Q[qIdx]( 0, 1 );
00217         W_out( 1, 0 ) = Q[qIdx]( 1, 0 );
00218         W_out( 1, 1 ) = Q[qIdx]( 1, 1 );
00219         W_out( 2, 0 ) = 0.0;
00220         W_out( 2, 1 ) = 0.0;
00221         if( lambdaIdx >= 0 ) W_out *= lambda[lambdaIdx];
00222         if( deltaIdx >= 0 ) W_out = W_out * delta[deltaIdx];
00223     }
00224     else if( deltaIdx >= 0 )
00225     {
00226         W_out( 0, 0 ) = delta[deltaIdx]( 0, 0 );
00227         W_out( 0, 1 ) = delta[deltaIdx]( 0, 1 );
00228         W_out( 1, 0 ) = delta[deltaIdx]( 1, 0 );
00229         W_out( 1, 1 ) = delta[deltaIdx]( 1, 1 );
00230         W_out( 2, 0 ) = 0.0;
00231         W_out( 2, 1 ) = 0.0;
00232         if( lambdaIdx >= 0 ) W_out *= lambda[lambdaIdx];
00233     }
00234     else if( lambdaIdx >= 0 )
00235     {
00236         W_out = MsqMatrix< 3, 2 >( lambda[lambdaIdx] );
00237     }
00238     else
00239     {
00240         W_out = MsqMatrix< 3, 2 >( 1.0 );
00241     }
00242 
00243     return true;
00244 }
00245 
00246 }  // namespace MBMesquite
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines