MOAB: Mesh Oriented datABase
(version 5.4.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) [email protected] 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 <cassert> 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, 00056 TargetCalculator* V_source, 00057 TargetCalculator* Q_source, 00058 TargetCalculator* delta_source ) 00059 : numUniqueGuides( 0 ) 00060 { 00061 lambdaIdx = add_source( lambda_source ); 00062 vIdx = add_source( V_source ); 00063 qIdx = add_source( Q_source ); 00064 deltaIdx = add_source( delta_source ); 00065 } 00066 00067 LVQDTargetCalculator::~LVQDTargetCalculator() {} 00068 00069 bool LVQDTargetCalculator::have_surface_orient() const 00070 { 00071 return ( vIdx >= 0 ); 00072 } 00073 00074 bool LVQDTargetCalculator::get_3D_target( PatchData& pd, 00075 size_t element, 00076 Sample sample, 00077 MsqMatrix< 3, 3 >& W_out, 00078 MsqError& err ) 00079 { 00080 double lambda[4]; 00081 MsqMatrix< 3, 3 > V[4], Q[4], delta[4], W; 00082 bool valid; 00083 00084 for( int i = 0; i < numUniqueGuides; ++i ) 00085 { 00086 valid = uniqueGuides[i]->get_3D_target( pd, element, sample, W, err ); 00087 if( MSQ_CHKERR( err ) || !valid ) return false; 00088 valid = factor_3D( W, lambda[i], V[i], Q[i], delta[i], err ); 00089 if( MSQ_CHKERR( err ) || !valid ) return false; 00090 } 00091 00092 if( vIdx >= 0 ) 00093 { 00094 W_out = V[vIdx]; 00095 if( lambdaIdx >= 0 ) W_out *= lambda[lambdaIdx]; 00096 if( qIdx >= 0 ) W_out = W_out * Q[qIdx]; 00097 if( deltaIdx >= 0 ) W_out = W_out * delta[deltaIdx]; 00098 } 00099 else if( qIdx >= 0 ) 00100 { 00101 W_out = Q[qIdx]; 00102 if( lambdaIdx >= 0 ) W_out *= lambda[lambdaIdx]; 00103 if( deltaIdx >= 0 ) W_out = W_out * delta[deltaIdx]; 00104 } 00105 else if( deltaIdx >= 0 ) 00106 { 00107 W_out = delta[deltaIdx]; 00108 if( lambdaIdx >= 0 ) W_out *= lambda[lambdaIdx]; 00109 } 00110 else if( lambdaIdx >= 0 ) 00111 { 00112 W_out = MsqMatrix< 3, 3 >( lambda[lambdaIdx] ); 00113 } 00114 else 00115 { 00116 W_out = MsqMatrix< 3, 3 >( 1.0 ); 00117 } 00118 00119 return true; 00120 } 00121 00122 bool LVQDTargetCalculator::evaluate_guide_2D( PatchData& pd, 00123 size_t element, 00124 Sample sample, 00125 int idx, 00126 double& lambda, 00127 MsqMatrix< 3, 2 >& V, 00128 MsqMatrix< 2, 2 >& Q, 00129 MsqMatrix< 2, 2 >& delta, 00130 MsqError& err ) 00131 { 00132 bool valid; 00133 if( uniqueGuides[idx]->have_surface_orient() ) 00134 { 00135 MsqMatrix< 3, 2 > W; 00136 valid = uniqueGuides[idx]->get_surface_target( pd, element, sample, W, err ); 00137 if( MSQ_CHKERR( err ) || !valid ) return false; 00138 valid = factor_surface( W, lambda, V, Q, delta, err ); 00139 if( MSQ_CHKERR( err ) || !valid ) return false; 00140 } 00141 else 00142 { 00143 MsqMatrix< 2, 2 > W; 00144 valid = uniqueGuides[idx]->get_2D_target( pd, element, sample, W, err ); 00145 if( MSQ_CHKERR( err ) || !valid ) return false; 00146 MsqMatrix< 2, 2 > junk; 00147 valid = factor_2D( W, lambda, junk, Q, delta, err ); 00148 if( MSQ_CHKERR( err ) || !valid ) return false; 00149 V = MsqMatrix< 3, 2 >( 1.0 ); 00150 } 00151 return true; 00152 } 00153 00154 bool LVQDTargetCalculator::get_2D_target( PatchData& pd, 00155 size_t element, 00156 Sample sample, 00157 MsqMatrix< 2, 2 >& W_out, 00158 MsqError& err ) 00159 { 00160 double lambda[4]; 00161 MsqMatrix< 3, 2 > V[4]; 00162 MsqMatrix< 2, 2 > W, Q[4], delta[4]; 00163 bool valid; 00164 00165 if( have_surface_orient() ) 00166 { 00167 MSQ_SETERR( err )( "Incorrect surface mesh target type", MsqError::INTERNAL_ERROR ); 00168 return false; 00169 } 00170 00171 for( int i = 0; i < numUniqueGuides; ++i ) 00172 { 00173 valid = evaluate_guide_2D( pd, element, sample, i, lambda[i], V[i], Q[i], delta[i], err ); 00174 if( MSQ_CHKERR( err ) || !valid ) return false; 00175 } 00176 00177 if( qIdx >= 0 ) 00178 { 00179 W_out = Q[qIdx]; 00180 if( lambdaIdx >= 0 ) W_out *= lambda[lambdaIdx]; 00181 if( deltaIdx >= 0 ) W_out = W_out * delta[deltaIdx]; 00182 } 00183 else if( deltaIdx >= 0 ) 00184 { 00185 W_out = delta[deltaIdx]; 00186 if( lambdaIdx >= 0 ) W_out *= lambda[lambdaIdx]; 00187 } 00188 else if( lambdaIdx >= 0 ) 00189 { 00190 W_out = MsqMatrix< 2, 2 >( lambda[lambdaIdx] ); 00191 } 00192 else 00193 { 00194 W_out = MsqMatrix< 2, 2 >( 1.0 ); 00195 } 00196 00197 return true; 00198 } 00199 00200 bool LVQDTargetCalculator::get_surface_target( PatchData& pd, 00201 size_t element, 00202 Sample sample, 00203 MsqMatrix< 3, 2 >& W_out, 00204 MsqError& err ) 00205 { 00206 double lambda[4]; 00207 MsqMatrix< 3, 2 > V[4], W; 00208 MsqMatrix< 2, 2 > Q[4], delta[4], junk, W2; 00209 bool valid; 00210 00211 if( !have_surface_orient() ) 00212 { 00213 MSQ_SETERR( err )( "Incorrect surface mesh target type", MsqError::INTERNAL_ERROR ); 00214 return false; 00215 } 00216 00217 for( int i = 0; i < numUniqueGuides; ++i ) 00218 { 00219 valid = evaluate_guide_2D( pd, element, sample, i, lambda[i], V[i], Q[i], delta[i], err ); 00220 if( MSQ_CHKERR( err ) || !valid ) return false; 00221 } 00222 00223 if( vIdx >= 0 ) 00224 { 00225 W_out = V[vIdx]; 00226 if( lambdaIdx >= 0 ) W_out *= lambda[lambdaIdx]; 00227 if( qIdx >= 0 ) W_out = W_out * Q[qIdx]; 00228 if( deltaIdx >= 0 ) W_out = W_out * delta[deltaIdx]; 00229 } 00230 else if( qIdx >= 0 ) 00231 { 00232 W_out( 0, 0 ) = Q[qIdx]( 0, 0 ); 00233 W_out( 0, 1 ) = Q[qIdx]( 0, 1 ); 00234 W_out( 1, 0 ) = Q[qIdx]( 1, 0 ); 00235 W_out( 1, 1 ) = Q[qIdx]( 1, 1 ); 00236 W_out( 2, 0 ) = 0.0; 00237 W_out( 2, 1 ) = 0.0; 00238 if( lambdaIdx >= 0 ) W_out *= lambda[lambdaIdx]; 00239 if( deltaIdx >= 0 ) W_out = W_out * delta[deltaIdx]; 00240 } 00241 else if( deltaIdx >= 0 ) 00242 { 00243 W_out( 0, 0 ) = delta[deltaIdx]( 0, 0 ); 00244 W_out( 0, 1 ) = delta[deltaIdx]( 0, 1 ); 00245 W_out( 1, 0 ) = delta[deltaIdx]( 1, 0 ); 00246 W_out( 1, 1 ) = delta[deltaIdx]( 1, 1 ); 00247 W_out( 2, 0 ) = 0.0; 00248 W_out( 2, 1 ) = 0.0; 00249 if( lambdaIdx >= 0 ) W_out *= lambda[lambdaIdx]; 00250 } 00251 else if( lambdaIdx >= 0 ) 00252 { 00253 W_out = MsqMatrix< 3, 2 >( lambda[lambdaIdx] ); 00254 } 00255 else 00256 { 00257 W_out = MsqMatrix< 3, 2 >( 1.0 ); 00258 } 00259 00260 return true; 00261 } 00262 00263 } // namespace MBMesquite