MOAB: Mesh Oriented datABase
(version 5.2.1)
|
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