MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 #include "SimplexTemplateRefiner.hpp" 00002 00003 #include "EdgeSizeEvaluator.hpp" 00004 #include "RefinerTagManager.hpp" 00005 00006 #include "moab/Interface.hpp" 00007 00008 #include <iostream> 00009 #include <stack> 00010 00011 // Static arrays holding parametric coordinates of element vertices 00012 static double MBVertexParametric[] = { 0., 0., 0. }; 00013 static double MBEdgeParametric[] = { 0., 0., 0., 1., 0., 0. }; 00014 static double MBTriParametric[] = { 0., 0., 0., 1., 0., 0., 0., 1., 0. }; 00015 static double MBTetParametric[] = { 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 1. }; 00016 00017 #ifdef MB_DEBUG_TESSELLATOR 00018 #define MB_TESSELLATOR_INCR_CASE_COUNT( cs ) this->case_counts[cs]++ 00019 #define MB_TESSELLATOR_INCR_SUBCASE_COUNT( cs, sc ) this->subcase_counts[cs][sc]++ 00020 #else // MB_DEBUG_TESSELLATOR 00021 #define MB_TESSELLATOR_INCR_CASE_COUNT( cs ) 00022 #define MB_TESSELLATOR_INCR_SUBCASE_COUNT( cs, sc ) 00023 #endif // MB_DEBUG_TESSELLATOR 00024 00025 namespace moab 00026 { 00027 00028 /// Construct a template refiner. 00029 SimplexTemplateRefiner::SimplexTemplateRefiner() 00030 { 00031 this->tag_manager = 0; 00032 this->tag_assigner = new SimplexTemplateTagAssigner( this ); 00033 this->corner_coords.resize( 6 * 8 ); // Hex has 8 verts w/ 6 coordinates each 00034 this->corner_tags.resize( 8 ); // Hex has 8 verts (this is a pointer, not the actual tag data) 00035 this->corner_handles.resize( 8 ); // Hex has 8 verts (this is a pointer, not actual hash data) 00036 this->input_is_output = false; // Until we know better 00037 } 00038 00039 /// Empty destructor for good form. 00040 SimplexTemplateRefiner::~SimplexTemplateRefiner() 00041 { 00042 delete this->tag_assigner; 00043 } 00044 00045 /**\brief Stream a single mesh entity through the refiner. 00046 */ 00047 bool SimplexTemplateRefiner::refine_entity( EntityType etyp, EntityHandle entity ) 00048 { 00049 this->reset_heap_pointers(); 00050 bool rval = true; 00051 const EntityHandle* conn; 00052 int num_nodes; 00053 Interface* imesh = this->tag_manager->get_input_mesh(); 00054 if( imesh->get_connectivity( entity, conn, num_nodes ) != MB_SUCCESS ) 00055 { 00056 return false; 00057 } 00058 this->corner_coords.resize( 6 * num_nodes ); 00059 this->corner_tags.resize( num_nodes ); 00060 this->corner_handles.resize( num_nodes ); 00061 00062 // Have to make num_nodes calls to get_coords() because we need xyz interleaved with rst coords. 00063 Tag tag_handle; 00064 int tag_offset; 00065 void* tag_data; 00066 for( int n = 0; n < num_nodes; ++n ) 00067 { 00068 if( imesh->get_coords( &conn[n], 1, &corner_coords[6 * n + 3] ) != MB_SUCCESS ) 00069 { 00070 return false; 00071 } 00072 tag_data = this->heap_tag_storage(); 00073 for( int i = 0; i < this->tag_manager->get_number_of_vertex_tags(); ++i ) 00074 { 00075 this->tag_manager->get_input_vertex_tag( i, tag_handle, tag_offset ); 00076 if( imesh->tag_get_data( tag_handle, &conn[n], 1, (char*)tag_data + tag_offset ) != MB_SUCCESS ) 00077 { 00078 return false; 00079 } 00080 } 00081 if( this->input_is_output ) 00082 { 00083 this->corner_handles[n] = conn[n]; 00084 } 00085 else 00086 { 00087 this->corner_handles[n] = this->output_functor->map_vertex( conn[n], &corner_coords[6 * n], tag_data ); 00088 #if 0 00089 std::cout << "#+# " << this->corner_handles[n] << " < " 00090 << corner_coords[ 6 * n + 3 ] << ", " 00091 << corner_coords[ 6 * n + 4 ] << ", " 00092 << corner_coords[ 6 * n + 5 ] << ">\n"; 00093 #endif // 0 00094 } 00095 this->corner_tags[n] = tag_data; 00096 } 00097 00098 switch( etyp ) 00099 { 00100 case MBVERTEX: 00101 this->assign_parametric_coordinates( 1, MBVertexParametric, &this->corner_coords[0] ); 00102 this->refine_0_simplex( &this->corner_coords[0], this->corner_tags[0], this->corner_handles[0] ); 00103 rval = false; 00104 break; 00105 case MBEDGE: 00106 this->assign_parametric_coordinates( 2, MBEdgeParametric, &this->corner_coords[0] ); 00107 rval = this->refine_1_simplex( this->maximum_number_of_subdivisions, &this->corner_coords[0], 00108 this->corner_tags[0], this->corner_handles[0], &this->corner_coords[6], 00109 this->corner_tags[1], this->corner_handles[1] ); 00110 break; 00111 case MBTRI: 00112 this->assign_parametric_coordinates( 3, MBTriParametric, &this->corner_coords[0] ); 00113 rval = this->refine_2_simplex( this->maximum_number_of_subdivisions, 7, &this->corner_coords[0], 00114 this->corner_tags[0], this->corner_handles[0], &this->corner_coords[6], 00115 this->corner_tags[1], this->corner_handles[1], &this->corner_coords[12], 00116 this->corner_tags[2], this->corner_handles[2] ); 00117 break; 00118 case MBQUAD: 00119 std::cerr << "Quadrilaterals not handled yet\n"; 00120 rval = false; 00121 break; 00122 case MBPOLYGON: 00123 std::cerr << "Polygons not handled yet\n"; 00124 rval = false; 00125 break; 00126 case MBTET: 00127 this->assign_parametric_coordinates( 4, MBTetParametric, &this->corner_coords[0] ); 00128 rval = this->refine_3_simplex( this->maximum_number_of_subdivisions, &this->corner_coords[0], 00129 this->corner_tags[0], this->corner_handles[0], &this->corner_coords[6], 00130 this->corner_tags[1], this->corner_handles[1], &this->corner_coords[12], 00131 this->corner_tags[2], this->corner_handles[2], &this->corner_coords[18], 00132 this->corner_tags[3], this->corner_handles[3] ); 00133 break; 00134 case MBPYRAMID: 00135 std::cerr << "Pyramid schemes not handled yet\n"; 00136 rval = false; 00137 break; 00138 case MBPRISM: 00139 std::cerr << "Prisms not handled yet\n"; 00140 rval = false; 00141 break; 00142 case MBKNIFE: 00143 std::cerr << "Knifahedra not handled yet\n"; 00144 rval = false; 00145 break; 00146 case MBHEX: 00147 std::cerr << "Hexahedra not handled yet\n"; 00148 rval = false; 00149 break; 00150 case MBPOLYHEDRON: 00151 std::cerr << "Polyhedra not handled yet\n"; 00152 rval = false; 00153 break; 00154 case MBENTITYSET: 00155 std::cerr << "How should entity sets be handled? We might iterate over its entries or " 00156 "skip it." 00157 "Must coordinate with MeshRefiner's loop over entities...\n"; 00158 rval = false; 00159 break; 00160 case MBMAXTYPE: 00161 rval = false; 00162 break; 00163 } 00164 return rval; 00165 } 00166 00167 /**\brief Set the function object used to decide which tag values an edge or face midpoint is 00168 * assigned. 00169 * 00170 * This will change the tag assigner's edge size evaluator to match the refiner's. 00171 * @param[in] ta The new tag assigner. This must be non-NULL. 00172 * @retval True if the tag assigner was changed and false otherwise. 00173 */ 00174 bool SimplexTemplateRefiner::set_tag_assigner( SimplexTemplateTagAssigner* ta ) 00175 { 00176 if( !ta || ta == this->tag_assigner ) return false; 00177 00178 this->tag_assigner = ta; 00179 return true; 00180 } 00181 00182 /**\brief Set the function object used to decide whether an edge is subdivided or not. 00183 */ 00184 bool SimplexTemplateRefiner::prepare( RefinerTagManager* tmgr, EntityRefinerOutputFunctor* ofunc ) 00185 { 00186 this->tag_manager = tmgr; 00187 this->tag_assigner->set_tag_manager( tmgr ); 00188 this->input_is_output = ( this->tag_manager->get_input_mesh() == this->tag_manager->get_output_mesh() ); 00189 // this->tag_assigner->set_edge_size_evaluator( this->edge_size_evaluator ); 00190 return this->EntityRefiner::prepare( tmgr, ofunc ); 00191 } 00192 00193 /**\fn unsigned long SimplexTemplateRefiner::get_heap_size_bound( int max_recursions ) const 00194 *\brief Bound on the number of new vertices used to allocate the heap. 00195 * 00196 * This bound is based on a hexahedron that is divided into 48 tetrahedra (a point is added to 00197 * the center of each face so that compatible boundaries are guaranteed on neighboring hexahedra), 00198 * each of which has 4 edges. 00199 */ 00200 00201 /**\brief "Refine" a vertex by passing it through to the output. 00202 * 00203 * FIXME: There is some question as to whether this should pass vertices through 00204 * since there does not appear to be a distinction between vertices as points 00205 * in space and vertices as degrees-of-freedom in a mesh (i.e. a vertex that is 00206 * treated as a lumped-parameter model). 00207 */ 00208 void SimplexTemplateRefiner::refine_0_simplex( const double* v0, const void* t0, EntityHandle h0 ) 00209 { 00210 // Ignore these arguments... the caller is responsible for calling the output functor to ensure 00211 // the vertex exists on the output. 00212 (void)v0; 00213 (void)t0; 00214 00215 ( *this->output_functor )( h0 ); 00216 ( *this->output_functor )( MBVERTEX ); 00217 } 00218 00219 /**\brief Refine an edge. 00220 */ 00221 bool SimplexTemplateRefiner::refine_1_simplex( int max_depth, 00222 const double* v0, 00223 const void* t0, 00224 EntityHandle h0, 00225 const double* v1, 00226 const void* t1, 00227 EntityHandle h1 ) 00228 { 00229 int edge_code = 0; 00230 00231 double* midptc; 00232 void* midptt; 00233 // NB: If support for multiple recursive subdivisions (without a merge in between) is required, 00234 // this will have to change as it assumes that h0 and h1 have only a single entry. 00235 EntityHandle midpth = 0; 00236 00237 if( max_depth-- > 0 ) 00238 { 00239 midptc = this->heap_coord_storage(); 00240 midptt = this->heap_tag_storage(); 00241 int i; 00242 // make valgrind happy 00243 // vtkstd::fill( midpt0, midpt0 + 6, 0. ); 00244 for( i = 0; i < 6; i++ ) 00245 midptc[i] = ( v0[i] + v1[i] ) / 2.; 00246 00247 ( *this->tag_assigner )( v0, t0, h0, midptc, midptt, v1, t1, h1 ); 00248 if( this->edge_size_evaluator->evaluate_edge( v0, t0, midptc, midptt, v1, t1 ) ) 00249 { 00250 edge_code = 1; 00251 midpth = ( *this->output_functor )( h0, h1, midptc, midptt ); 00252 } 00253 } 00254 00255 switch( edge_code ) 00256 { 00257 // No edges to subdivide 00258 case 0: 00259 ( *this->output_functor )( h0 ); 00260 ( *this->output_functor )( h1 ); 00261 ( *this->output_functor )( MBEDGE ); 00262 break; 00263 00264 // One edge to subdivide 00265 case 1: 00266 this->refine_1_simplex( max_depth, v0, t0, h0, midptc, midptt, midpth ); 00267 this->refine_1_simplex( max_depth, midptc, midptt, midpth, v1, t1, h1 ); 00268 break; 00269 } 00270 00271 return ( 0 == edge_code ) ? false : true; 00272 } 00273 00274 /**\brief Refine a triangle. 00275 */ 00276 bool SimplexTemplateRefiner::refine_2_simplex( int max_depth, 00277 int move, 00278 const double* v0, 00279 const void* t0, 00280 EntityHandle h0, 00281 const double* v1, 00282 const void* t1, 00283 EntityHandle h1, 00284 const double* v2, 00285 const void* t2, 00286 EntityHandle h2 ) 00287 { 00288 int edge_code = 0; 00289 00290 double* midpt0c; 00291 double* midpt1c; 00292 double* midpt2c; 00293 void* midpt0t; 00294 void* midpt1t; 00295 void* midpt2t; 00296 EntityHandle midpt0h = 0; 00297 EntityHandle midpt1h = 0; 00298 EntityHandle midpt2h = 0; 00299 00300 if( max_depth-- > 0 ) 00301 { 00302 int i; 00303 midpt0c = this->heap_coord_storage(); 00304 midpt1c = this->heap_coord_storage(); 00305 midpt2c = this->heap_coord_storage(); 00306 midpt0t = this->heap_tag_storage(); 00307 midpt1t = this->heap_tag_storage(); 00308 midpt2t = this->heap_tag_storage(); 00309 midpt0h = 0; 00310 midpt1h = 0; 00311 midpt2h = 0; 00312 for( i = 0; i < 6; ++i ) 00313 { 00314 midpt0c[i] = ( v0[i] + v1[i] ) / 2.; 00315 midpt1c[i] = ( v1[i] + v2[i] ) / 2.; 00316 midpt2c[i] = ( v2[i] + v0[i] ) / 2.; 00317 } 00318 ( *this->tag_assigner )( v0, t0, h0, midpt0c, midpt0t, v1, t1, h1 ); 00319 ( *this->tag_assigner )( v1, t1, h1, midpt1c, midpt1t, v2, t2, h2 ); 00320 ( *this->tag_assigner )( v2, t2, h2, midpt2c, midpt2t, v0, t0, h0 ); 00321 if( ( move & 1 ) && this->edge_size_evaluator->evaluate_edge( v0, t0, midpt0c, midpt0t, v1, t1 ) ) 00322 { 00323 edge_code += 1; 00324 midpt0h = ( *this->output_functor )( h0, h1, midpt0c, midpt0t ); 00325 } 00326 if( ( move & 2 ) && this->edge_size_evaluator->evaluate_edge( v1, t1, midpt1c, midpt1t, v2, t2 ) ) 00327 { 00328 edge_code += 2; 00329 midpt1h = ( *this->output_functor )( h1, h2, midpt1c, midpt1t ); 00330 } 00331 if( ( move & 4 ) && this->edge_size_evaluator->evaluate_edge( v2, t2, midpt2c, midpt2t, v0, t0 ) ) 00332 { 00333 edge_code += 4; 00334 midpt2h = ( *this->output_functor )( h2, h0, midpt2c, midpt2t ); 00335 } 00336 } 00337 00338 switch( edge_code ) 00339 { 00340 // No edges to subdivide 00341 case 0: 00342 ( *this->output_functor )( h0 ); 00343 ( *this->output_functor )( h1 ); 00344 ( *this->output_functor )( h2 ); 00345 ( *this->output_functor )( MBTRI ); 00346 break; 00347 00348 // One edge to subdivide 00349 case 1: 00350 this->refine_2_simplex( max_depth, move | 2, v0, t0, h0, midpt0c, midpt0t, midpt0h, v2, t2, h2 ); 00351 this->refine_2_simplex( max_depth, move | 4, midpt0c, midpt0t, midpt0h, v1, t1, h1, v2, t2, h2 ); 00352 break; 00353 case 2: 00354 this->refine_2_simplex( max_depth, move | 4, v0, t0, h0, v1, t1, h1, midpt1c, midpt1t, midpt1h ); 00355 this->refine_2_simplex( max_depth, move | 1, v0, t0, h0, midpt1c, midpt1t, midpt1h, v2, t2, h2 ); 00356 break; 00357 case 4: 00358 this->refine_2_simplex( max_depth, move | 2, v0, t0, h0, v1, t1, h1, midpt2c, midpt2t, midpt2h ); 00359 this->refine_2_simplex( max_depth, move | 1, midpt2c, midpt2t, midpt2h, v1, t1, h1, v2, t2, h2 ); 00360 break; 00361 00362 // Two edges to subdivide 00363 case 3: 00364 this->refine_2_simplex( max_depth, move | 4, midpt0c, midpt0t, midpt0h, v1, t1, h1, midpt1c, midpt1t, 00365 midpt1h ); 00366 if( this->compare_Hopf_cross_string_dist( v2, midpt0c, v0, midpt1c ) ) 00367 { 00368 this->refine_2_simplex( max_depth, move | 5, midpt0c, midpt0t, midpt0h, midpt1c, midpt1t, midpt1h, v2, 00369 t2, h2 ); 00370 this->refine_2_simplex( max_depth, move | 2, v0, t0, h0, midpt0c, midpt0t, midpt0h, v2, t2, h2 ); 00371 } 00372 else 00373 { 00374 this->refine_2_simplex( max_depth, move | 6, v0, t0, h0, midpt0c, midpt0t, midpt0h, midpt1c, midpt1t, 00375 midpt1h ); 00376 this->refine_2_simplex( max_depth, move | 1, v0, t0, h0, midpt1c, midpt1t, midpt1h, v2, t2, h2 ); 00377 } 00378 break; 00379 case 5: 00380 this->refine_2_simplex( max_depth, move | 2, v0, t0, h0, midpt0c, midpt0t, midpt0h, midpt2c, midpt2t, 00381 midpt2h ); 00382 if( this->compare_Hopf_cross_string_dist( v2, midpt0c, v1, midpt2c ) ) 00383 { 00384 this->refine_2_simplex( max_depth, move | 4, midpt0c, midpt0t, midpt0h, v1, t1, h1, v2, t2, h2 ); 00385 this->refine_2_simplex( max_depth, move | 3, midpt2c, midpt2t, midpt2h, midpt0c, midpt0t, midpt0h, v2, 00386 t2, h2 ); 00387 } 00388 else 00389 { 00390 this->refine_2_simplex( max_depth, move | 6, midpt0c, midpt0t, midpt0h, v1, t1, h1, midpt2c, midpt2t, 00391 midpt2h ); 00392 this->refine_2_simplex( max_depth, move | 1, midpt2c, midpt2t, midpt2h, v1, t1, h1, v2, t2, h2 ); 00393 } 00394 break; 00395 case 6: 00396 this->refine_2_simplex( max_depth, move | 1, midpt2c, midpt2t, midpt2h, midpt1c, midpt1t, midpt1h, v2, t2, 00397 h2 ); 00398 if( this->compare_Hopf_cross_string_dist( v0, midpt1c, v1, midpt2c ) ) 00399 { 00400 this->refine_2_simplex( max_depth, move | 3, v0, t0, h0, midpt1c, midpt1t, midpt1h, midpt2c, midpt2t, 00401 midpt2h ); 00402 this->refine_2_simplex( max_depth, move | 4, v0, t0, h0, v1, t1, h1, midpt1c, midpt1t, midpt1h ); 00403 } 00404 else 00405 { 00406 this->refine_2_simplex( max_depth, move | 2, v0, t0, h0, v1, t1, h1, midpt2c, midpt2t, midpt2h ); 00407 this->refine_2_simplex( max_depth, move | 5, midpt2c, midpt2t, midpt2h, v1, t1, h1, midpt1c, midpt1t, 00408 midpt1h ); 00409 } 00410 break; 00411 00412 // Three edges to subdivide 00413 case 7: 00414 this->refine_2_simplex( max_depth, 7, midpt0c, midpt0t, midpt0h, midpt1c, midpt1t, midpt1h, midpt2c, 00415 midpt2t, midpt2h ); 00416 this->refine_2_simplex( max_depth, move | 2, v0, t0, h0, midpt0c, midpt0t, midpt0h, midpt2c, midpt2t, 00417 midpt2h ); 00418 this->refine_2_simplex( max_depth, move | 4, midpt0c, midpt0t, midpt0h, v1, t1, h1, midpt1c, midpt1t, 00419 midpt1h ); 00420 this->refine_2_simplex( max_depth, move | 1, midpt2c, midpt2t, midpt2h, midpt1c, midpt1t, midpt1h, v2, t2, 00421 h2 ); 00422 break; 00423 } 00424 00425 return true; 00426 } 00427 00428 /**\brief Refine a tetrahedron. 00429 */ 00430 bool SimplexTemplateRefiner::refine_3_simplex( int max_depth, 00431 double* v0, 00432 void* t0, 00433 EntityHandle h0, 00434 double* v1, 00435 void* t1, 00436 EntityHandle h1, 00437 double* v2, 00438 void* t2, 00439 EntityHandle h2, 00440 double* v3, 00441 void* t3, 00442 EntityHandle h3 ) 00443 { 00444 int edge_code = 0; 00445 00446 double* midpt0c; 00447 double* midpt1c; 00448 double* midpt2c; 00449 double* midpt3c; 00450 double* midpt4c; 00451 double* midpt5c; 00452 00453 void* midpt0t; 00454 void* midpt1t; 00455 void* midpt2t; 00456 void* midpt3t; 00457 void* midpt4t; 00458 void* midpt5t; 00459 00460 EntityHandle midpt0h = 0; 00461 EntityHandle midpt1h = 0; 00462 EntityHandle midpt2h = 0; 00463 EntityHandle midpt3h = 0; 00464 EntityHandle midpt4h = 0; 00465 EntityHandle midpt5h = 0; 00466 00467 if( max_depth-- > 0 ) 00468 { 00469 midpt0c = this->heap_coord_storage(); 00470 midpt1c = this->heap_coord_storage(); 00471 midpt2c = this->heap_coord_storage(); 00472 midpt3c = this->heap_coord_storage(); 00473 midpt4c = this->heap_coord_storage(); 00474 midpt5c = this->heap_coord_storage(); 00475 00476 midpt0t = this->heap_tag_storage(); 00477 midpt1t = this->heap_tag_storage(); 00478 midpt2t = this->heap_tag_storage(); 00479 midpt3t = this->heap_tag_storage(); 00480 midpt4t = this->heap_tag_storage(); 00481 midpt5t = this->heap_tag_storage(); 00482 00483 for( int i = 0; i < 6; ++i ) 00484 { 00485 midpt0c[i] = ( v0[i] + v1[i] ) * .5; 00486 midpt1c[i] = ( v1[i] + v2[i] ) * .5; 00487 midpt2c[i] = ( v2[i] + v0[i] ) * .5; 00488 midpt3c[i] = ( v0[i] + v3[i] ) * .5; 00489 midpt4c[i] = ( v1[i] + v3[i] ) * .5; 00490 midpt5c[i] = ( v2[i] + v3[i] ) * .5; 00491 } 00492 00493 ( *this->tag_assigner )( v0, t0, h0, midpt0c, midpt0t, v1, t1, h1 ); 00494 ( *this->tag_assigner )( v1, t1, h1, midpt1c, midpt1t, v2, t2, h2 ); 00495 ( *this->tag_assigner )( v2, t2, h2, midpt2c, midpt2t, v0, t0, h0 ); 00496 ( *this->tag_assigner )( v0, t0, h0, midpt3c, midpt3t, v3, t3, h3 ); 00497 ( *this->tag_assigner )( v1, t1, h1, midpt4c, midpt4t, v3, t3, h3 ); 00498 ( *this->tag_assigner )( v2, t2, h2, midpt5c, midpt5t, v3, t3, h3 ); 00499 00500 if( this->edge_size_evaluator->evaluate_edge( v0, t0, midpt0c, midpt0t, v1, t1 ) ) 00501 { 00502 edge_code |= 1; 00503 midpt0h = ( *this->output_functor )( h0, h1, midpt0c, midpt0t ); 00504 } 00505 if( this->edge_size_evaluator->evaluate_edge( v1, t1, midpt1c, midpt1t, v2, t2 ) ) 00506 { 00507 edge_code |= 2; 00508 midpt1h = ( *this->output_functor )( h1, h2, midpt1c, midpt1t ); 00509 } 00510 if( this->edge_size_evaluator->evaluate_edge( v2, t2, midpt2c, midpt2t, v0, t0 ) ) 00511 { 00512 edge_code |= 4; 00513 midpt2h = ( *this->output_functor )( h2, h0, midpt2c, midpt2t ); 00514 } 00515 if( this->edge_size_evaluator->evaluate_edge( v0, t0, midpt3c, midpt3t, v3, t3 ) ) 00516 { 00517 edge_code |= 8; 00518 midpt3h = ( *this->output_functor )( h0, h3, midpt3c, midpt3t ); 00519 } 00520 if( this->edge_size_evaluator->evaluate_edge( v1, t1, midpt4c, midpt4t, v3, t3 ) ) 00521 { 00522 edge_code |= 16; 00523 midpt4h = ( *this->output_functor )( h1, h3, midpt4c, midpt4t ); 00524 } 00525 if( this->edge_size_evaluator->evaluate_edge( v2, t2, midpt5c, midpt5t, v3, t3 ) ) 00526 { 00527 edge_code |= 32; 00528 midpt5h = ( *this->output_functor )( h2, h3, midpt5c, midpt5t ); 00529 } 00530 } 00531 00532 double edge_length2[6]; 00533 for( int ei = 0; ei < 6; ++ei ) 00534 edge_length2[ei] = 0.; 00535 00536 for( int c = 0; c < 3; ++c ) 00537 { 00538 double tmp; 00539 tmp = v1[c] - v0[c]; 00540 edge_length2[0] += tmp * tmp; 00541 tmp = v2[c] - v1[c]; 00542 edge_length2[1] += tmp * tmp; 00543 tmp = v2[c] - v0[c]; 00544 edge_length2[2] += tmp * tmp; 00545 tmp = v3[c] - v0[c]; 00546 edge_length2[3] += tmp * tmp; 00547 tmp = v3[c] - v1[c]; 00548 edge_length2[4] += tmp * tmp; 00549 tmp = v3[c] - v2[c]; 00550 edge_length2[5] += tmp * tmp; 00551 } 00552 00553 if( 0 == edge_code ) 00554 { 00555 // No edges to subdivide 00556 ( *this->output_functor )( h0 ); 00557 ( *this->output_functor )( h1 ); 00558 ( *this->output_functor )( h2 ); 00559 ( *this->output_functor )( h3 ); 00560 ( *this->output_functor )( MBTET ); 00561 00562 return false; 00563 } 00564 00565 double* facept0c; 00566 double* facept1c; 00567 double* facept2c; 00568 double* facept3c; 00569 facept0c = this->heap_coord_storage(); 00570 facept1c = this->heap_coord_storage(); 00571 facept2c = this->heap_coord_storage(); 00572 facept3c = this->heap_coord_storage(); 00573 double* vertex_coords[14] = { v0, v1, v2, v3, midpt0c, midpt1c, midpt2c, 00574 midpt3c, midpt4c, midpt5c, facept0c, facept1c, facept2c, facept3c }; 00575 00576 void* facept0t = this->heap_tag_storage(); 00577 void* facept1t = this->heap_tag_storage(); 00578 void* facept2t = this->heap_tag_storage(); 00579 void* facept3t = this->heap_tag_storage(); 00580 void* vertex_tags[14] = { t0, t1, t2, t3, midpt0t, midpt1t, midpt2t, 00581 midpt3t, midpt4t, midpt5t, facept0t, facept1t, facept2t, facept3t }; 00582 00583 EntityHandle vertex_hash[14] = { h0, h1, h2, h3, midpt0h, midpt1h, midpt2h, midpt3h, midpt4h, midpt5h, 0, 0, 0, 0 }; 00584 00585 // Generate tetrahedra that are compatible except when edge 00586 // lengths are equal on indeterminately subdivided faces. 00587 double* permuted_coords[14]; 00588 void* permuted_tags[14]; 00589 EntityHandle permuted_hash[14]; 00590 double permlen[6]; // permuted edge lengths 00591 int C = SimplexTemplateRefiner::template_index[edge_code][0]; 00592 int P = SimplexTemplateRefiner::template_index[edge_code][1]; 00593 00594 // 1. Permute the tetrahedron into our canonical configuration 00595 for( int i = 0; i < 14; ++i ) 00596 { 00597 permuted_coords[i] = vertex_coords[SimplexTemplateRefiner::permutations_from_index[P][i]]; 00598 permuted_tags[i] = vertex_tags[SimplexTemplateRefiner::permutations_from_index[P][i]]; 00599 permuted_hash[i] = vertex_hash[SimplexTemplateRefiner::permutations_from_index[P][i]]; 00600 } 00601 00602 for( int i = 4; i < 10; ++i ) 00603 { 00604 // permute edge lengths too 00605 permlen[i - 4] = edge_length2[SimplexTemplateRefiner::permutations_from_index[P][i] - 4]; 00606 } 00607 00608 int comparison_bits; 00609 std::stack< int* > output_tets; 00610 std::stack< int* > output_perm; 00611 std::stack< int > output_sign; 00612 00613 // cout << "Case " << C << " Permutation " << P << endl; 00614 // 2. Generate tetrahedra based on the configuration. 00615 // Note that case 0 is handled above (edgeCode == 0). 00616 00617 switch( C ) 00618 { 00619 case 1: // Ruprecht-Müller Case 1 00620 MB_TESSELLATOR_INCR_CASE_COUNT( 0 ); 00621 output_tets.push( SimplexTemplateRefiner::templates + 0 ); 00622 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00623 output_sign.push( 1 ); 00624 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 0, 0 ); 00625 break; 00626 case 2: // Ruprecht-Müller Case 2a 00627 comparison_bits = ( permlen[0] <= permlen[1] ? 1 : 0 ) | ( permlen[0] >= permlen[1] ? 2 : 0 ) | 0; 00628 if( ( comparison_bits & 3 ) == 3 ) 00629 { 00630 // Compute face point and tag 00631 for( int i = 0; i < 6; ++i ) 00632 { 00633 permuted_coords[10][i] = 00634 ( permuted_coords[0][i] + permuted_coords[2][i] ) * .375 + permuted_coords[1][i] * .25; 00635 } 00636 ( *this->tag_assigner )( permuted_tags[0], permuted_tags[2], permuted_tags[1], permuted_tags[10] ); 00637 permuted_hash[10] = ( *this->output_functor )( permuted_hash[0], permuted_hash[2], permuted_hash[1], 00638 permuted_coords[10], permuted_tags[10] ); 00639 } 00640 MB_TESSELLATOR_INCR_CASE_COUNT( 1 ); 00641 output_tets.push( SimplexTemplateRefiner::templates + 9 ); 00642 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00643 output_sign.push( 1 ); 00644 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 1, 0 ); 00645 switch( comparison_bits ) 00646 { 00647 case 2: // 0>1 00648 output_tets.push( SimplexTemplateRefiner::templates + 14 ); 00649 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00650 output_sign.push( 1 ); 00651 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 1, 1 ); 00652 break; 00653 case 1: // 1>0 00654 output_tets.push( SimplexTemplateRefiner::templates + 14 ); 00655 output_perm.push( SimplexTemplateRefiner::permutations_from_index[13] ); 00656 output_sign.push( -1 ); 00657 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 1, 2 ); 00658 break; 00659 case 3: // 0=1 00660 output_tets.push( SimplexTemplateRefiner::templates + 23 ); 00661 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00662 output_sign.push( 1 ); 00663 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 1, 3 ); 00664 break; 00665 } 00666 break; 00667 case 3: // Ruprecht-Müller Case 2b 00668 MB_TESSELLATOR_INCR_CASE_COUNT( 2 ); 00669 output_tets.push( SimplexTemplateRefiner::templates + 40 ); 00670 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00671 output_sign.push( 1 ); 00672 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 2, 0 ); 00673 break; 00674 case 4: // Ruprecht-Müller Case 3a 00675 comparison_bits = ( permlen[0] <= permlen[3] ? 1 : 0 ) | ( permlen[0] >= permlen[3] ? 2 : 0 ) | 00676 ( permlen[2] <= permlen[3] ? 4 : 0 ) | ( permlen[2] >= permlen[3] ? 8 : 0 ) | 00677 ( permlen[0] <= permlen[2] ? 16 : 0 ) | ( permlen[0] >= permlen[2] ? 32 : 0 ) | 0; 00678 if( ( comparison_bits & 3 ) == 3 ) 00679 { 00680 // Compute face point and tag 00681 for( int i = 0; i < 6; ++i ) 00682 { 00683 permuted_coords[11][i] = 00684 ( permuted_coords[1][i] + permuted_coords[3][i] ) * .375 + permuted_coords[0][i] * .25; 00685 } 00686 ( *this->tag_assigner )( permuted_tags[1], permuted_tags[3], permuted_tags[0], permuted_tags[11] ); 00687 permuted_hash[11] = ( *this->output_functor )( permuted_hash[1], permuted_hash[3], permuted_hash[0], 00688 permuted_coords[11], permuted_tags[11] ); 00689 } 00690 if( ( comparison_bits & 12 ) == 12 ) 00691 { 00692 // Compute face point and tag 00693 for( int i = 0; i < 6; ++i ) 00694 { 00695 permuted_coords[13][i] = 00696 ( permuted_coords[2][i] + permuted_coords[3][i] ) * .375 + permuted_coords[0][i] * .25; 00697 } 00698 ( *this->tag_assigner )( permuted_tags[2], permuted_tags[3], permuted_tags[0], permuted_tags[13] ); 00699 permuted_hash[13] = ( *this->output_functor )( permuted_hash[2], permuted_hash[3], permuted_hash[0], 00700 permuted_coords[13], permuted_tags[13] ); 00701 } 00702 if( ( comparison_bits & 48 ) == 48 ) 00703 { 00704 // Compute face point and tag 00705 for( int i = 0; i < 6; ++i ) 00706 { 00707 permuted_coords[10][i] = 00708 ( permuted_coords[1][i] + permuted_coords[2][i] ) * .375 + permuted_coords[0][i] * .25; 00709 } 00710 ( *this->tag_assigner )( permuted_tags[1], permuted_tags[2], permuted_tags[0], permuted_tags[10] ); 00711 permuted_hash[10] = ( *this->output_functor )( permuted_hash[1], permuted_hash[2], permuted_hash[0], 00712 permuted_coords[10], permuted_tags[10] ); 00713 } 00714 MB_TESSELLATOR_INCR_CASE_COUNT( 3 ); 00715 output_tets.push( SimplexTemplateRefiner::templates + 57 ); 00716 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00717 output_sign.push( 1 ); 00718 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 3, 0 ); 00719 switch( comparison_bits ) 00720 { 00721 case 42: // 0>2>3<0 00722 output_tets.push( SimplexTemplateRefiner::templates + 62 ); 00723 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00724 output_sign.push( 1 ); 00725 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 3, 1 ); 00726 break; 00727 case 25: // 2>3>0<2 00728 output_tets.push( SimplexTemplateRefiner::templates + 62 ); 00729 output_perm.push( SimplexTemplateRefiner::permutations_from_index[11] ); 00730 output_sign.push( 1 ); 00731 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 3, 2 ); 00732 break; 00733 case 37: // 3>0>2<3 00734 output_tets.push( SimplexTemplateRefiner::templates + 62 ); 00735 output_perm.push( SimplexTemplateRefiner::permutations_from_index[3] ); 00736 output_sign.push( 1 ); 00737 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 3, 3 ); 00738 break; 00739 case 21: // 3>2>0<3 00740 output_tets.push( SimplexTemplateRefiner::templates + 62 ); 00741 output_perm.push( SimplexTemplateRefiner::permutations_from_index[22] ); 00742 output_sign.push( -1 ); 00743 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 3, 4 ); 00744 break; 00745 case 26: // 2>0>3<2 00746 output_tets.push( SimplexTemplateRefiner::templates + 62 ); 00747 output_perm.push( SimplexTemplateRefiner::permutations_from_index[12] ); 00748 output_sign.push( -1 ); 00749 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 3, 5 ); 00750 break; 00751 case 38: // 0>3>2<0 00752 output_tets.push( SimplexTemplateRefiner::templates + 62 ); 00753 output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] ); 00754 output_sign.push( -1 ); 00755 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 3, 6 ); 00756 break; 00757 case 58: // 0=2>3<0 00758 output_tets.push( SimplexTemplateRefiner::templates + 75 ); 00759 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00760 output_sign.push( 1 ); 00761 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 3, 7 ); 00762 break; 00763 case 29: // 2=3>0<2 00764 output_tets.push( SimplexTemplateRefiner::templates + 75 ); 00765 output_perm.push( SimplexTemplateRefiner::permutations_from_index[11] ); 00766 output_sign.push( 1 ); 00767 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 3, 8 ); 00768 break; 00769 case 39: // 0=3>2<0 00770 output_tets.push( SimplexTemplateRefiner::templates + 75 ); 00771 output_perm.push( SimplexTemplateRefiner::permutations_from_index[3] ); 00772 output_sign.push( 1 ); 00773 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 3, 9 ); 00774 break; 00775 case 53: // 3>0=2<3 00776 output_tets.push( SimplexTemplateRefiner::templates + 96 ); 00777 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00778 output_sign.push( 1 ); 00779 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 3, 10 ); 00780 break; 00781 case 46: // 0>2=3<0 00782 output_tets.push( SimplexTemplateRefiner::templates + 96 ); 00783 output_perm.push( SimplexTemplateRefiner::permutations_from_index[11] ); 00784 output_sign.push( 1 ); 00785 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 3, 11 ); 00786 break; 00787 case 27: // 2>0=3<2 00788 output_tets.push( SimplexTemplateRefiner::templates + 96 ); 00789 output_perm.push( SimplexTemplateRefiner::permutations_from_index[3] ); 00790 output_sign.push( 1 ); 00791 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 3, 12 ); 00792 break; 00793 case 63: // 0=2=3=0 00794 output_tets.push( SimplexTemplateRefiner::templates + 117 ); 00795 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00796 output_sign.push( 1 ); 00797 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 3, 13 ); 00798 break; 00799 } 00800 break; 00801 case 5: // Ruprecht-Müller Case 3b 00802 MB_TESSELLATOR_INCR_CASE_COUNT( 4 ); 00803 output_tets.push( SimplexTemplateRefiner::templates + 162 ); 00804 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00805 output_sign.push( 1 ); 00806 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 4, 0 ); 00807 break; 00808 case 6: // Ruprecht-Müller Case 3c 00809 comparison_bits = ( permlen[0] <= permlen[1] ? 1 : 0 ) | ( permlen[0] >= permlen[1] ? 2 : 0 ) | 00810 ( permlen[0] <= permlen[3] ? 4 : 0 ) | ( permlen[0] >= permlen[3] ? 8 : 0 ) | 0; 00811 if( ( comparison_bits & 3 ) == 3 ) 00812 { 00813 // Compute face point and tag 00814 for( int i = 0; i < 6; ++i ) 00815 { 00816 permuted_coords[10][i] = 00817 ( permuted_coords[0][i] + permuted_coords[2][i] ) * .375 + permuted_coords[1][i] * .25; 00818 } 00819 ( *this->tag_assigner )( permuted_tags[0], permuted_tags[2], permuted_tags[1], permuted_tags[10] ); 00820 permuted_hash[10] = ( *this->output_functor )( permuted_hash[0], permuted_hash[2], permuted_hash[1], 00821 permuted_coords[10], permuted_tags[10] ); 00822 } 00823 if( ( comparison_bits & 12 ) == 12 ) 00824 { 00825 // Compute face point and tag 00826 for( int i = 0; i < 6; ++i ) 00827 { 00828 permuted_coords[11][i] = 00829 ( permuted_coords[1][i] + permuted_coords[3][i] ) * .375 + permuted_coords[0][i] * .25; 00830 } 00831 ( *this->tag_assigner )( permuted_tags[1], permuted_tags[3], permuted_tags[0], permuted_tags[11] ); 00832 permuted_hash[11] = ( *this->output_functor )( permuted_hash[1], permuted_hash[3], permuted_hash[0], 00833 permuted_coords[11], permuted_tags[11] ); 00834 } 00835 MB_TESSELLATOR_INCR_CASE_COUNT( 5 ); 00836 switch( comparison_bits ) 00837 { 00838 case 10: // 0>1,0>3 00839 output_tets.push( SimplexTemplateRefiner::templates + 179 ); 00840 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00841 output_sign.push( 1 ); 00842 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 5, 0 ); 00843 break; 00844 case 5: // 1>0,3>0 00845 output_tets.push( SimplexTemplateRefiner::templates + 200 ); 00846 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00847 output_sign.push( 1 ); 00848 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 5, 1 ); 00849 break; 00850 case 6: // 0>1,3>0 00851 output_tets.push( SimplexTemplateRefiner::templates + 221 ); 00852 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00853 output_sign.push( 1 ); 00854 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 5, 2 ); 00855 break; 00856 case 9: // 1>0,0>3 00857 output_tets.push( SimplexTemplateRefiner::templates + 242 ); 00858 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00859 output_sign.push( 1 ); 00860 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 5, 3 ); 00861 break; 00862 case 11: // 0=1,0>3 00863 output_tets.push( SimplexTemplateRefiner::templates + 263 ); 00864 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00865 output_sign.push( 1 ); 00866 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 5, 4 ); 00867 break; 00868 case 14: // 0=3,0>1 00869 output_tets.push( SimplexTemplateRefiner::templates + 263 ); 00870 output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] ); 00871 output_sign.push( 1 ); 00872 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 5, 5 ); 00873 break; 00874 case 7: // 3>0,0=1 00875 output_tets.push( SimplexTemplateRefiner::templates + 292 ); 00876 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00877 output_sign.push( 1 ); 00878 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 5, 6 ); 00879 break; 00880 case 13: // 1>0,0=3 00881 output_tets.push( SimplexTemplateRefiner::templates + 292 ); 00882 output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] ); 00883 output_sign.push( 1 ); 00884 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 5, 7 ); 00885 break; 00886 case 15: // 0=1,0=3 00887 output_tets.push( SimplexTemplateRefiner::templates + 321 ); 00888 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00889 output_sign.push( 1 ); 00890 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 5, 8 ); 00891 break; 00892 } 00893 break; 00894 case 7: // Ruprecht-Müller Case 3d 00895 comparison_bits = ( permlen[0] <= permlen[2] ? 1 : 0 ) | ( permlen[0] >= permlen[2] ? 2 : 0 ) | 00896 ( permlen[0] <= permlen[4] ? 4 : 0 ) | ( permlen[0] >= permlen[4] ? 8 : 0 ) | 0; 00897 if( ( comparison_bits & 3 ) == 3 ) 00898 { 00899 // Compute face point and tag 00900 for( int i = 0; i < 6; ++i ) 00901 { 00902 permuted_coords[10][i] = 00903 ( permuted_coords[1][i] + permuted_coords[2][i] ) * .375 + permuted_coords[0][i] * .25; 00904 } 00905 ( *this->tag_assigner )( permuted_tags[1], permuted_tags[2], permuted_tags[0], permuted_tags[10] ); 00906 permuted_hash[10] = ( *this->output_functor )( permuted_hash[1], permuted_hash[2], permuted_hash[0], 00907 permuted_coords[10], permuted_tags[10] ); 00908 } 00909 if( ( comparison_bits & 12 ) == 12 ) 00910 { 00911 // Compute face point and tag 00912 for( int i = 0; i < 6; ++i ) 00913 { 00914 permuted_coords[11][i] = 00915 ( permuted_coords[0][i] + permuted_coords[3][i] ) * .375 + permuted_coords[1][i] * .25; 00916 } 00917 ( *this->tag_assigner )( permuted_tags[0], permuted_tags[3], permuted_tags[1], permuted_tags[11] ); 00918 permuted_hash[11] = ( *this->output_functor )( permuted_hash[0], permuted_hash[3], permuted_hash[1], 00919 permuted_coords[11], permuted_tags[11] ); 00920 } 00921 MB_TESSELLATOR_INCR_CASE_COUNT( 6 ); 00922 switch( comparison_bits ) 00923 { 00924 case 10: // 0>4,0>2 00925 output_tets.push( SimplexTemplateRefiner::templates + 362 ); 00926 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00927 output_sign.push( 1 ); 00928 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 6, 0 ); 00929 break; 00930 case 5: // 4>0,2>0 00931 output_tets.push( SimplexTemplateRefiner::templates + 383 ); 00932 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00933 output_sign.push( 1 ); 00934 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 6, 1 ); 00935 break; 00936 case 9: // 0>4,2>0 00937 output_tets.push( SimplexTemplateRefiner::templates + 404 ); 00938 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00939 output_sign.push( 1 ); 00940 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 6, 2 ); 00941 break; 00942 case 6: // 4>0,0>2 00943 output_tets.push( SimplexTemplateRefiner::templates + 425 ); 00944 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00945 output_sign.push( 1 ); 00946 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 6, 3 ); 00947 break; 00948 case 14: // 0=4,0>2 00949 output_tets.push( SimplexTemplateRefiner::templates + 446 ); 00950 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00951 output_sign.push( 1 ); 00952 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 6, 4 ); 00953 break; 00954 case 11: // 0=2,0>4 00955 output_tets.push( SimplexTemplateRefiner::templates + 446 ); 00956 output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] ); 00957 output_sign.push( 1 ); 00958 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 6, 5 ); 00959 break; 00960 case 13: // 2>0,0=4 00961 output_tets.push( SimplexTemplateRefiner::templates + 475 ); 00962 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00963 output_sign.push( 1 ); 00964 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 6, 6 ); 00965 break; 00966 case 7: // 4>0,0=2 00967 output_tets.push( SimplexTemplateRefiner::templates + 475 ); 00968 output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] ); 00969 output_sign.push( 1 ); 00970 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 6, 7 ); 00971 break; 00972 case 15: // 0=4,0=2 00973 output_tets.push( SimplexTemplateRefiner::templates + 504 ); 00974 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 00975 output_sign.push( 1 ); 00976 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 6, 8 ); 00977 break; 00978 } 00979 break; 00980 case 8: // Ruprecht-Müller Case 4a 00981 comparison_bits = ( permlen[4] <= permlen[5] ? 1 : 0 ) | ( permlen[4] >= permlen[5] ? 2 : 0 ) | 00982 ( permlen[3] <= permlen[4] ? 4 : 0 ) | ( permlen[3] >= permlen[4] ? 8 : 0 ) | 0; 00983 if( ( comparison_bits & 3 ) == 3 ) 00984 { 00985 // Compute face point and tag 00986 for( int i = 0; i < 6; ++i ) 00987 { 00988 permuted_coords[12][i] = 00989 ( permuted_coords[1][i] + permuted_coords[2][i] ) * .375 + permuted_coords[3][i] * .25; 00990 } 00991 ( *this->tag_assigner )( permuted_tags[1], permuted_tags[2], permuted_tags[3], permuted_tags[12] ); 00992 permuted_hash[12] = ( *this->output_functor )( permuted_hash[1], permuted_hash[2], permuted_hash[3], 00993 permuted_coords[12], permuted_tags[12] ); 00994 } 00995 if( ( comparison_bits & 12 ) == 12 ) 00996 { 00997 // Compute face point and tag 00998 for( int i = 0; i < 6; ++i ) 00999 { 01000 permuted_coords[11][i] = 01001 ( permuted_coords[0][i] + permuted_coords[1][i] ) * .375 + permuted_coords[3][i] * .25; 01002 } 01003 ( *this->tag_assigner )( permuted_tags[0], permuted_tags[1], permuted_tags[3], permuted_tags[11] ); 01004 permuted_hash[11] = ( *this->output_functor )( permuted_hash[0], permuted_hash[1], permuted_hash[3], 01005 permuted_coords[11], permuted_tags[11] ); 01006 } 01007 MB_TESSELLATOR_INCR_CASE_COUNT( 7 ); 01008 output_tets.push( SimplexTemplateRefiner::templates + 545 ); 01009 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01010 output_sign.push( 1 ); 01011 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 7, 0 ); 01012 switch( comparison_bits ) 01013 { 01014 case 5: // 5>4>3 01015 output_tets.push( SimplexTemplateRefiner::templates + 554 ); 01016 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01017 output_sign.push( 1 ); 01018 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 7, 1 ); 01019 break; 01020 case 10: // 3>4>5 01021 output_tets.push( SimplexTemplateRefiner::templates + 554 ); 01022 output_perm.push( SimplexTemplateRefiner::permutations_from_index[13] ); 01023 output_sign.push( -1 ); 01024 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 7, 2 ); 01025 break; 01026 case 6: // 3<4>5 01027 output_tets.push( SimplexTemplateRefiner::templates + 571 ); 01028 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01029 output_sign.push( 1 ); 01030 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 7, 3 ); 01031 break; 01032 case 9: // 3>4<5 01033 output_tets.push( SimplexTemplateRefiner::templates + 588 ); 01034 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01035 output_sign.push( 1 ); 01036 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 7, 4 ); 01037 break; 01038 case 14: // 3=4>5 01039 output_tets.push( SimplexTemplateRefiner::templates + 605 ); 01040 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01041 output_sign.push( 1 ); 01042 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 7, 5 ); 01043 break; 01044 case 7: // 4=5,4>3 01045 output_tets.push( SimplexTemplateRefiner::templates + 605 ); 01046 output_perm.push( SimplexTemplateRefiner::permutations_from_index[13] ); 01047 output_sign.push( -1 ); 01048 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 7, 6 ); 01049 break; 01050 case 13: // 5>4,3=4 01051 output_tets.push( SimplexTemplateRefiner::templates + 630 ); 01052 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01053 output_sign.push( 1 ); 01054 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 7, 7 ); 01055 break; 01056 case 11: // 3>4=5 01057 output_tets.push( SimplexTemplateRefiner::templates + 630 ); 01058 output_perm.push( SimplexTemplateRefiner::permutations_from_index[13] ); 01059 output_sign.push( -1 ); 01060 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 7, 8 ); 01061 break; 01062 case 15: // 3=4=5 01063 output_tets.push( SimplexTemplateRefiner::templates + 655 ); 01064 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01065 output_sign.push( 1 ); 01066 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 7, 9 ); 01067 break; 01068 } 01069 break; 01070 case 9: // Ruprecht-Müller Case 4b 01071 comparison_bits = ( permlen[1] <= permlen[2] ? 1 : 0 ) | ( permlen[1] >= permlen[2] ? 2 : 0 ) | 01072 ( permlen[2] <= permlen[3] ? 4 : 0 ) | ( permlen[2] >= permlen[3] ? 8 : 0 ) | 01073 ( permlen[3] <= permlen[4] ? 16 : 0 ) | ( permlen[3] >= permlen[4] ? 32 : 0 ) | 01074 ( permlen[1] <= permlen[4] ? 64 : 0 ) | ( permlen[1] >= permlen[4] ? 128 : 0 ) | 0; 01075 if( ( comparison_bits & 3 ) == 3 ) 01076 { 01077 // Compute face point and tag 01078 for( int i = 0; i < 6; ++i ) 01079 { 01080 permuted_coords[10][i] = 01081 ( permuted_coords[1][i] + permuted_coords[0][i] ) * .375 + permuted_coords[2][i] * .25; 01082 } 01083 ( *this->tag_assigner )( permuted_tags[1], permuted_tags[0], permuted_tags[2], permuted_tags[10] ); 01084 permuted_hash[10] = ( *this->output_functor )( permuted_hash[1], permuted_hash[0], permuted_hash[2], 01085 permuted_coords[10], permuted_tags[10] ); 01086 } 01087 if( ( comparison_bits & 12 ) == 12 ) 01088 { 01089 // Compute face point and tag 01090 for( int i = 0; i < 6; ++i ) 01091 { 01092 permuted_coords[13][i] = 01093 ( permuted_coords[2][i] + permuted_coords[3][i] ) * .375 + permuted_coords[0][i] * .25; 01094 } 01095 ( *this->tag_assigner )( permuted_tags[2], permuted_tags[3], permuted_tags[0], permuted_tags[13] ); 01096 permuted_hash[13] = ( *this->output_functor )( permuted_hash[2], permuted_hash[3], permuted_hash[0], 01097 permuted_coords[13], permuted_tags[13] ); 01098 } 01099 if( ( comparison_bits & 48 ) == 48 ) 01100 { 01101 // Compute face point and tag 01102 for( int i = 0; i < 6; ++i ) 01103 { 01104 permuted_coords[11][i] = 01105 ( permuted_coords[0][i] + permuted_coords[1][i] ) * .375 + permuted_coords[3][i] * .25; 01106 } 01107 ( *this->tag_assigner )( permuted_tags[0], permuted_tags[1], permuted_tags[3], permuted_tags[11] ); 01108 permuted_hash[11] = ( *this->output_functor )( permuted_hash[0], permuted_hash[1], permuted_hash[3], 01109 permuted_coords[11], permuted_tags[11] ); 01110 } 01111 if( ( comparison_bits & 192 ) == 192 ) 01112 { 01113 // Compute face point and tag 01114 for( int i = 0; i < 6; ++i ) 01115 { 01116 permuted_coords[12][i] = 01117 ( permuted_coords[2][i] + permuted_coords[3][i] ) * .375 + permuted_coords[1][i] * .25; 01118 } 01119 ( *this->tag_assigner )( permuted_tags[2], permuted_tags[3], permuted_tags[1], permuted_tags[12] ); 01120 permuted_hash[12] = ( *this->output_functor )( permuted_hash[2], permuted_hash[3], permuted_hash[1], 01121 permuted_coords[12], permuted_tags[12] ); 01122 } 01123 MB_TESSELLATOR_INCR_CASE_COUNT( 8 ); 01124 switch( comparison_bits ) 01125 { 01126 case 85: // 2>1,3>2,4>3,4>1 01127 output_tets.push( SimplexTemplateRefiner::templates + 688 ); 01128 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01129 output_sign.push( 1 ); 01130 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 0 ); 01131 break; 01132 case 102: // 1>2,3>2,3>4,4>1 01133 output_tets.push( SimplexTemplateRefiner::templates + 688 ); 01134 output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] ); 01135 output_sign.push( -1 ); 01136 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 1 ); 01137 break; 01138 case 170: // 1>2,2>3,3>4,1>4 01139 output_tets.push( SimplexTemplateRefiner::templates + 688 ); 01140 output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] ); 01141 output_sign.push( -1 ); 01142 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 2 ); 01143 break; 01144 case 153: // 2>1,2>3,4>3,1>4 01145 output_tets.push( SimplexTemplateRefiner::templates + 688 ); 01146 output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] ); 01147 output_sign.push( 1 ); 01148 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 3 ); 01149 break; 01150 case 90: // 1>2,2>3,4>3,4>1 01151 output_tets.push( SimplexTemplateRefiner::templates + 688 ); 01152 output_perm.push( SimplexTemplateRefiner::permutations_from_index[9] ); 01153 output_sign.push( 1 ); 01154 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 4 ); 01155 break; 01156 case 105: // 2>1,2>3,3>4,4>1 01157 output_tets.push( SimplexTemplateRefiner::templates + 688 ); 01158 output_perm.push( SimplexTemplateRefiner::permutations_from_index[7] ); 01159 output_sign.push( 1 ); 01160 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 5 ); 01161 break; 01162 case 165: // 2>1,3>2,3>4,1>4 01163 output_tets.push( SimplexTemplateRefiner::templates + 688 ); 01164 output_perm.push( SimplexTemplateRefiner::permutations_from_index[19] ); 01165 output_sign.push( -1 ); 01166 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 6 ); 01167 break; 01168 case 150: // 1>2,3>2,4>3,1>4 01169 output_tets.push( SimplexTemplateRefiner::templates + 688 ); 01170 output_perm.push( SimplexTemplateRefiner::permutations_from_index[23] ); 01171 output_sign.push( -1 ); 01172 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 7 ); 01173 break; 01174 case 101: // 2>1,3>2,3>4,4>1 01175 { 01176 int alternates[] = { 713, 738, -1 }; 01177 output_tets.push( SimplexTemplateRefiner::templates + 01178 this->best_tets( alternates, permuted_coords, 0, 1 ) ); 01179 } 01180 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01181 output_sign.push( 1 ); 01182 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 8 ); 01183 break; 01184 case 86: // 1>2,3>2,4>3,4>1 01185 { 01186 int alternates[] = { 713, 738, -1 }; 01187 output_tets.push( SimplexTemplateRefiner::templates + 01188 this->best_tets( alternates, permuted_coords, 14, -1 ) ); 01189 } 01190 output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] ); 01191 output_sign.push( -1 ); 01192 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 9 ); 01193 break; 01194 case 154: // 1>2,2>3,4>3,1>4 01195 { 01196 int alternates[] = { 713, 738, -1 }; 01197 output_tets.push( SimplexTemplateRefiner::templates + 01198 this->best_tets( alternates, permuted_coords, 5, 1 ) ); 01199 } 01200 output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] ); 01201 output_sign.push( 1 ); 01202 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 10 ); 01203 break; 01204 case 169: // 2>1,2>3,3>4,1>4 01205 { 01206 int alternates[] = { 713, 738, -1 }; 01207 output_tets.push( SimplexTemplateRefiner::templates + 01208 this->best_tets( alternates, permuted_coords, 15, -1 ) ); 01209 } 01210 output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] ); 01211 output_sign.push( -1 ); 01212 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 11 ); 01213 break; 01214 case 89: // 2>1,2>3,4>3,4>1 01215 output_tets.push( SimplexTemplateRefiner::templates + 763 ); 01216 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01217 output_sign.push( 1 ); 01218 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 12 ); 01219 break; 01220 case 166: // 1>2,3>2,3>4,1>4 01221 output_tets.push( SimplexTemplateRefiner::templates + 763 ); 01222 output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] ); 01223 output_sign.push( -1 ); 01224 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 13 ); 01225 break; 01226 case 103: // 1=2,3>2,3>4,4>1 01227 output_tets.push( SimplexTemplateRefiner::templates + 788 ); 01228 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01229 output_sign.push( 1 ); 01230 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 14 ); 01231 break; 01232 case 87: // 1=2,3>2,4>3,4>1 01233 output_tets.push( SimplexTemplateRefiner::templates + 788 ); 01234 output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] ); 01235 output_sign.push( -1 ); 01236 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 15 ); 01237 break; 01238 case 185: // 2>1,2>3,3=4,1>4 01239 output_tets.push( SimplexTemplateRefiner::templates + 788 ); 01240 output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] ); 01241 output_sign.push( -1 ); 01242 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 16 ); 01243 break; 01244 case 186: // 1>2,2>3,3=4,1>4 01245 output_tets.push( SimplexTemplateRefiner::templates + 788 ); 01246 output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] ); 01247 output_sign.push( 1 ); 01248 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 17 ); 01249 break; 01250 case 158: // 1>2,2=3,4>3,1>4 01251 output_tets.push( SimplexTemplateRefiner::templates + 788 ); 01252 output_perm.push( SimplexTemplateRefiner::permutations_from_index[9] ); 01253 output_sign.push( 1 ); 01254 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 18 ); 01255 break; 01256 case 229: // 2>1,3>2,3>4,1=4 01257 output_tets.push( SimplexTemplateRefiner::templates + 788 ); 01258 output_perm.push( SimplexTemplateRefiner::permutations_from_index[7] ); 01259 output_sign.push( 1 ); 01260 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 19 ); 01261 break; 01262 case 233: // 2>1,2>3,3>4,1=4 01263 output_tets.push( SimplexTemplateRefiner::templates + 788 ); 01264 output_perm.push( SimplexTemplateRefiner::permutations_from_index[19] ); 01265 output_sign.push( -1 ); 01266 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 20 ); 01267 break; 01268 case 94: // 1>2,2=3,4>3,4>1 01269 output_tets.push( SimplexTemplateRefiner::templates + 788 ); 01270 output_perm.push( SimplexTemplateRefiner::permutations_from_index[23] ); 01271 output_sign.push( -1 ); 01272 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 21 ); 01273 break; 01274 case 155: // 1=2,2>3,4>3,1>4 01275 output_tets.push( SimplexTemplateRefiner::templates + 825 ); 01276 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01277 output_sign.push( 1 ); 01278 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 22 ); 01279 break; 01280 case 171: // 1=2,2>3,3>4,1>4 01281 output_tets.push( SimplexTemplateRefiner::templates + 825 ); 01282 output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] ); 01283 output_sign.push( -1 ); 01284 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 23 ); 01285 break; 01286 case 118: // 1>2,3>2,3=4,4>1 01287 output_tets.push( SimplexTemplateRefiner::templates + 825 ); 01288 output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] ); 01289 output_sign.push( -1 ); 01290 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 24 ); 01291 break; 01292 case 117: // 2>1,3>2,3=4,4>1 01293 output_tets.push( SimplexTemplateRefiner::templates + 825 ); 01294 output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] ); 01295 output_sign.push( 1 ); 01296 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 25 ); 01297 break; 01298 case 109: // 2>1,2=3,3>4,4>1 01299 output_tets.push( SimplexTemplateRefiner::templates + 825 ); 01300 output_perm.push( SimplexTemplateRefiner::permutations_from_index[9] ); 01301 output_sign.push( 1 ); 01302 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 26 ); 01303 break; 01304 case 218: // 1>2,2>3,4>3,1=4 01305 output_tets.push( SimplexTemplateRefiner::templates + 825 ); 01306 output_perm.push( SimplexTemplateRefiner::permutations_from_index[7] ); 01307 output_sign.push( 1 ); 01308 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 27 ); 01309 break; 01310 case 214: // 1>2,3>2,4>3,1=4 01311 output_tets.push( SimplexTemplateRefiner::templates + 825 ); 01312 output_perm.push( SimplexTemplateRefiner::permutations_from_index[19] ); 01313 output_sign.push( -1 ); 01314 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 28 ); 01315 break; 01316 case 173: // 2>1,2=3,3>4,1>4 01317 output_tets.push( SimplexTemplateRefiner::templates + 825 ); 01318 output_perm.push( SimplexTemplateRefiner::permutations_from_index[23] ); 01319 output_sign.push( -1 ); 01320 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 29 ); 01321 break; 01322 case 91: // 1=2,2>3,4>3,4>1 01323 output_tets.push( SimplexTemplateRefiner::templates + 862 ); 01324 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01325 output_sign.push( 1 ); 01326 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 30 ); 01327 break; 01328 case 167: // 1=2,3>2,3>4,1>4 01329 output_tets.push( SimplexTemplateRefiner::templates + 862 ); 01330 output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] ); 01331 output_sign.push( -1 ); 01332 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 31 ); 01333 break; 01334 case 182: // 1>2,3>2,3=4,1>4 01335 output_tets.push( SimplexTemplateRefiner::templates + 862 ); 01336 output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] ); 01337 output_sign.push( -1 ); 01338 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 32 ); 01339 break; 01340 case 121: // 2>1,2>3,3=4,4>1 01341 output_tets.push( SimplexTemplateRefiner::templates + 862 ); 01342 output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] ); 01343 output_sign.push( 1 ); 01344 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 33 ); 01345 break; 01346 case 93: // 2>1,2=3,4>3,4>1 01347 output_tets.push( SimplexTemplateRefiner::templates + 862 ); 01348 output_perm.push( SimplexTemplateRefiner::permutations_from_index[9] ); 01349 output_sign.push( 1 ); 01350 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 34 ); 01351 break; 01352 case 217: // 2>1,2>3,4>3,1=4 01353 output_tets.push( SimplexTemplateRefiner::templates + 862 ); 01354 output_perm.push( SimplexTemplateRefiner::permutations_from_index[7] ); 01355 output_sign.push( 1 ); 01356 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 35 ); 01357 break; 01358 case 230: // 1>2,3>2,3>4,1=4 01359 output_tets.push( SimplexTemplateRefiner::templates + 862 ); 01360 output_perm.push( SimplexTemplateRefiner::permutations_from_index[19] ); 01361 output_sign.push( -1 ); 01362 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 36 ); 01363 break; 01364 case 174: // 1>2,2=3,3>4,1>4 01365 output_tets.push( SimplexTemplateRefiner::templates + 862 ); 01366 output_perm.push( SimplexTemplateRefiner::permutations_from_index[23] ); 01367 output_sign.push( -1 ); 01368 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 37 ); 01369 break; 01370 case 119: // 1=2,3>2,3=4,4>1 01371 output_tets.push( SimplexTemplateRefiner::templates + 899 ); 01372 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01373 output_sign.push( 1 ); 01374 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 38 ); 01375 break; 01376 case 187: // 1=2>3=4,1>4 01377 output_tets.push( SimplexTemplateRefiner::templates + 899 ); 01378 output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] ); 01379 output_sign.push( -1 ); 01380 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 39 ); 01381 break; 01382 case 222: // 1>2,2=3,4>3,1=4 01383 output_tets.push( SimplexTemplateRefiner::templates + 899 ); 01384 output_perm.push( SimplexTemplateRefiner::permutations_from_index[9] ); 01385 output_sign.push( 1 ); 01386 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 40 ); 01387 break; 01388 case 237: // 2>1,2=3,3>4,1=4 01389 output_tets.push( SimplexTemplateRefiner::templates + 899 ); 01390 output_perm.push( SimplexTemplateRefiner::permutations_from_index[7] ); 01391 output_sign.push( 1 ); 01392 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 41 ); 01393 break; 01394 case 95: // 4>1=2=3,4>3 01395 output_tets.push( SimplexTemplateRefiner::templates + 944 ); 01396 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01397 output_sign.push( 1 ); 01398 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 42 ); 01399 break; 01400 case 231: // 1=2,3>2,3>4,1=4 01401 output_tets.push( SimplexTemplateRefiner::templates + 944 ); 01402 output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] ); 01403 output_sign.push( -1 ); 01404 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 43 ); 01405 break; 01406 case 190: // 1>2=3=4,1>4 01407 output_tets.push( SimplexTemplateRefiner::templates + 944 ); 01408 output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] ); 01409 output_sign.push( -1 ); 01410 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 44 ); 01411 break; 01412 case 249: // 2>1,2>3,3=4,1=4 01413 output_tets.push( SimplexTemplateRefiner::templates + 944 ); 01414 output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] ); 01415 output_sign.push( 1 ); 01416 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 45 ); 01417 break; 01418 case 175: // 1=2=3>4,1>4 01419 output_tets.push( SimplexTemplateRefiner::templates + 993 ); 01420 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01421 output_sign.push( 1 ); 01422 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 46 ); 01423 break; 01424 case 219: // 1=2>3,4>3,1=4 01425 output_tets.push( SimplexTemplateRefiner::templates + 993 ); 01426 output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] ); 01427 output_sign.push( -1 ); 01428 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 47 ); 01429 break; 01430 case 125: // 2>1,2=3=4>1 01431 output_tets.push( SimplexTemplateRefiner::templates + 993 ); 01432 output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] ); 01433 output_sign.push( -1 ); 01434 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 48 ); 01435 break; 01436 case 246: // 1>2,3>2,3=4=1 01437 output_tets.push( SimplexTemplateRefiner::templates + 993 ); 01438 output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] ); 01439 output_sign.push( 1 ); 01440 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 49 ); 01441 break; 01442 case 255: // 1=2=3=4=1 01443 output_tets.push( SimplexTemplateRefiner::templates + 1042 ); 01444 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01445 output_sign.push( 1 ); 01446 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 8, 50 ); 01447 break; 01448 } 01449 break; 01450 case 10: // Ruprecht-Müller Case 5 01451 comparison_bits = ( permlen[1] <= permlen[2] ? 1 : 0 ) | ( permlen[1] >= permlen[2] ? 2 : 0 ) | 01452 ( permlen[3] <= permlen[4] ? 4 : 0 ) | ( permlen[3] >= permlen[4] ? 8 : 0 ) | 0; 01453 if( ( comparison_bits & 3 ) == 3 ) 01454 { 01455 // Compute face point and tag 01456 for( int i = 0; i < 6; ++i ) 01457 { 01458 permuted_coords[10][i] = 01459 ( permuted_coords[1][i] + permuted_coords[0][i] ) * .375 + permuted_coords[2][i] * .25; 01460 } 01461 ( *this->tag_assigner )( permuted_tags[1], permuted_tags[0], permuted_tags[2], permuted_tags[10] ); 01462 permuted_hash[10] = ( *this->output_functor )( permuted_hash[1], permuted_hash[0], permuted_hash[2], 01463 permuted_coords[10], permuted_tags[10] ); 01464 } 01465 if( ( comparison_bits & 12 ) == 12 ) 01466 { 01467 // Compute face point and tag 01468 for( int i = 0; i < 6; ++i ) 01469 { 01470 permuted_coords[11][i] = 01471 ( permuted_coords[0][i] + permuted_coords[1][i] ) * .375 + permuted_coords[3][i] * .25; 01472 } 01473 ( *this->tag_assigner )( permuted_tags[0], permuted_tags[1], permuted_tags[3], permuted_tags[11] ); 01474 permuted_hash[11] = ( *this->output_functor )( permuted_hash[0], permuted_hash[1], permuted_hash[3], 01475 permuted_coords[11], permuted_tags[11] ); 01476 } 01477 MB_TESSELLATOR_INCR_CASE_COUNT( 9 ); 01478 output_tets.push( SimplexTemplateRefiner::templates + 1107 ); 01479 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01480 output_sign.push( 1 ); 01481 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 9, 0 ); 01482 switch( comparison_bits ) 01483 { 01484 case 10: // 1>2,3>4 01485 output_tets.push( SimplexTemplateRefiner::templates + 1116 ); 01486 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01487 output_sign.push( 1 ); 01488 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 9, 1 ); 01489 break; 01490 case 5: // 2>1,4>3 01491 output_tets.push( SimplexTemplateRefiner::templates + 1116 ); 01492 output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] ); 01493 output_sign.push( -1 ); 01494 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 9, 2 ); 01495 break; 01496 case 6: // 1>2,4>3 01497 { 01498 int alternates[] = { 1137, 1158, -1 }; 01499 output_tets.push( SimplexTemplateRefiner::templates + 01500 this->best_tets( alternates, permuted_coords, 0, 1 ) ); 01501 } 01502 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01503 output_sign.push( 1 ); 01504 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 9, 3 ); 01505 break; 01506 case 9: // 2>1,3>4 01507 { 01508 int alternates[] = { 1137, 1158, -1 }; 01509 output_tets.push( SimplexTemplateRefiner::templates + 01510 this->best_tets( alternates, permuted_coords, 14, -1 ) ); 01511 } 01512 output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] ); 01513 output_sign.push( -1 ); 01514 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 9, 4 ); 01515 break; 01516 case 11: // 1=2,3>4 01517 { 01518 int alternates[] = { 1179, 1212, 1245, -1 }; 01519 output_tets.push( SimplexTemplateRefiner::templates + 01520 this->best_tets( alternates, permuted_coords, 0, 1 ) ); 01521 } 01522 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01523 output_sign.push( 1 ); 01524 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 9, 5 ); 01525 break; 01526 case 7: // 1=2,4>3 01527 { 01528 int alternates[] = { 1179, 1212, 1245, -1 }; 01529 output_tets.push( SimplexTemplateRefiner::templates + 01530 this->best_tets( alternates, permuted_coords, 14, -1 ) ); 01531 } 01532 output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] ); 01533 output_sign.push( -1 ); 01534 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 9, 6 ); 01535 break; 01536 case 14: // 3=4,1>2 01537 { 01538 int alternates[] = { 1179, 1212, 1245, -1 }; 01539 output_tets.push( SimplexTemplateRefiner::templates + 01540 this->best_tets( alternates, permuted_coords, 5, 1 ) ); 01541 } 01542 output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] ); 01543 output_sign.push( 1 ); 01544 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 9, 7 ); 01545 break; 01546 case 13: // 3=4,2>1 01547 { 01548 int alternates[] = { 1179, 1212, 1245, -1 }; 01549 output_tets.push( SimplexTemplateRefiner::templates + 01550 this->best_tets( alternates, permuted_coords, 15, -1 ) ); 01551 } 01552 output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] ); 01553 output_sign.push( -1 ); 01554 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 9, 8 ); 01555 break; 01556 case 15: // 1=2,3=4 01557 output_tets.push( SimplexTemplateRefiner::templates + 1278 ); 01558 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01559 output_sign.push( 1 ); 01560 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 9, 9 ); 01561 break; 01562 } 01563 break; 01564 case 11: // Ruprecht-Müller Case 6 01565 MB_TESSELLATOR_INCR_CASE_COUNT( 10 ); 01566 output_tets.push( SimplexTemplateRefiner::templates + 1319 ); 01567 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01568 output_sign.push( 1 ); 01569 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 10, 0 ); 01570 { 01571 int alternates[] = { 1336, 1353, 1370, -1 }; 01572 output_tets.push( SimplexTemplateRefiner::templates + 01573 this->best_tets( alternates, permuted_coords, 0, 1 ) ); 01574 } 01575 output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] ); 01576 output_sign.push( 1 ); 01577 MB_TESSELLATOR_INCR_SUBCASE_COUNT( 10, 1 ); 01578 break; 01579 } 01580 01581 int* tets; 01582 int ntets; 01583 int* perm; 01584 int sgn; 01585 #ifdef MB_DEBUG_TESSELLATOR 01586 if( output_tets.empty() ) 01587 { 01588 cout << "Argh! Case " << C << " Perm " << P << " has no output!" << endl; 01589 } 01590 #endif // MB_DEBUG_TESSELLATOR 01591 while( !output_tets.empty() ) 01592 { 01593 tets = output_tets.top(); 01594 ntets = *tets; 01595 tets++; 01596 perm = output_perm.top(); 01597 sgn = output_sign.top(); 01598 01599 output_tets.pop(); 01600 output_perm.pop(); 01601 output_sign.pop(); 01602 01603 int t; 01604 if( sgn > 0 ) 01605 { 01606 for( t = 0; t < ntets; ++t ) 01607 { 01608 this->refine_3_simplex( max_depth, permuted_coords[perm[tets[0]]], permuted_tags[perm[tets[0]]], 01609 permuted_hash[perm[tets[0]]], permuted_coords[perm[tets[1]]], 01610 permuted_tags[perm[tets[1]]], permuted_hash[perm[tets[1]]], 01611 permuted_coords[perm[tets[2]]], permuted_tags[perm[tets[2]]], 01612 permuted_hash[perm[tets[2]]], permuted_coords[perm[tets[3]]], 01613 permuted_tags[perm[tets[3]]], permuted_hash[perm[tets[3]]] ); 01614 tets += 4; 01615 } 01616 } 01617 else 01618 { 01619 // we have an inverted tet... reverse the first 2 vertices 01620 // so the orientation is positive. 01621 for( t = 0; t < ntets; ++t ) 01622 { 01623 this->refine_3_simplex( max_depth, permuted_coords[perm[tets[1]]], permuted_tags[perm[tets[1]]], 01624 permuted_hash[perm[tets[1]]], permuted_coords[perm[tets[0]]], 01625 permuted_tags[perm[tets[0]]], permuted_hash[perm[tets[0]]], 01626 permuted_coords[perm[tets[2]]], permuted_tags[perm[tets[2]]], 01627 permuted_hash[perm[tets[2]]], permuted_coords[perm[tets[3]]], 01628 permuted_tags[perm[tets[3]]], permuted_hash[perm[tets[3]]] ); 01629 tets += 4; 01630 } 01631 } 01632 } 01633 01634 return true; 01635 } 01636 01637 /**\brief This is used by refine_entity to assign parametric coordinates to corners of each element. 01638 */ 01639 void SimplexTemplateRefiner::assign_parametric_coordinates( int num_nodes, const double* src, double* tgt ) 01640 { 01641 for( int i = 0; i < num_nodes; ++i, src += 3, tgt += 6 ) 01642 for( int j = 0; j < 3; ++j ) 01643 tgt[j] = src[j]; 01644 } 01645 01646 /**\brief Returns true if || a0a1 || < || b0b1 || 01647 * 01648 * We use this to test which triangulation has the best 01649 * aspect ratio when there are 2 to choose from. 01650 */ 01651 bool SimplexTemplateRefiner::compare_Hopf_cross_string_dist( const double* a0, 01652 const double* a1, 01653 const double* b0, 01654 const double* b1 ) 01655 { 01656 double sq_mag_a = 0.; 01657 double sq_mag_b = 0.; 01658 for( int i = 0; i < 3; ++i ) 01659 { 01660 double tmp; 01661 tmp = a0[i] - a1[i]; 01662 sq_mag_a += tmp * tmp; 01663 tmp = b0[i] - b1[i]; 01664 sq_mag_b += tmp * tmp; 01665 } 01666 return sq_mag_a < sq_mag_b; 01667 } 01668 01669 /* 01670 * The array below is indexed by the edge code for a tetrahedron. 01671 * Looking up a row with a tet's edge code will return C and P. 01672 * C is a configuration number and P is a permutation index. 01673 * 01674 * C is based on the case number from Ruprecht and 01675 * Müller's (1998) paper on adaptive tetrahedra. (The case 01676 * numbers are shown to the left of the row in the column 01677 * labeled case. The only difference is that we introduce 01678 * a case 3d which is part of case 3c in the paper.) 01679 * 01680 * P is an index into the permutations_from_index array below, 01681 * and is used to transform the current tetrahedron into 01682 * the canonical configuration associated with C. 01683 * 01684 * The 6-digit binary number to the left (which is shown in 01685 * the horribly UNconventional LSB->MSB order) is the edge 01686 * code for the row. The 6 digits correspond to the 6 edges 01687 * of the tetrahedron; a '0' implies no subdivision while 01688 * a '1' implies subdivision should occur. The ordering of 01689 * the bits is 01690 * 01691 * Edge 0-1, Edge 1-2, Edge 2-0, Edge 0-3, Edge 1-3, Edge 2-3, 01692 * 01693 * where the numbers are vertices of the tetrahedron 0-1-2-3. 01694 * Note that Tet 0-1-2-3 must be positive (i.e., the plane 01695 * specified by Triangle 0-1-2 must have a normal pointing 01696 * towards vertex 3, and Triangle 0-1-2's normal must be 01697 * calculated using the cross-product (Edge 0-1) x (Edge 0-2)). 01698 * 01699 * =========== 01700 * References: 01701 * (Ruprect and Müller, 1998) A Scheme for Edge-based Adaptive 01702 * Tetrahedron Subdivision, Mathematical Visualization (eds. 01703 * Hege and Polthier), pp. 61--70. Springer-Verlag. 1998. 01704 */ 01705 int SimplexTemplateRefiner::template_index[64][2] = { 01706 /* code case C P */ 01707 /* 000000 0 0 */ { 0, 0 }, 01708 /* 100000 1 1 */ { 1, 0 }, 01709 /* 010000 2 1 */ { 1, 1 }, 01710 /* 110000 3 2a */ { 2, 0 }, 01711 /* 001000 4 1 */ { 1, 2 }, 01712 /* 101000 5 2a */ { 2, 2 }, 01713 /* 011000 6 2a */ { 2, 1 }, 01714 /* 111000 7 3b */ { 5, 11 }, 01715 /* 000100 8 1 */ { 1, 10 }, 01716 /* 100100 9 2a */ { 2, 5 }, 01717 /* 010100 10 2b */ { 3, 1 }, 01718 /* 110100 11 3c */ { 6, 0 }, 01719 /* 001100 12 2a */ { 2, 10 }, 01720 /* 101100 13 3a */ { 4, 0 }, 01721 /* 011100 14 3d */ { 7, 2 }, 01722 /* 111100 15 4a */ { 8, 6 }, 01723 /* 000010 16 1 */ { 1, 6 }, 01724 /* 100010 17 2a */ { 2, 4 }, 01725 /* 010010 18 2a */ { 2, 8 }, 01726 /* 110010 19 3a */ { 4, 1 }, 01727 /* 001010 20 2b */ { 3, 2 }, 01728 /* 101010 21 3d */ { 7, 0 }, 01729 /* 011010 22 3c */ { 6, 1 }, 01730 /* 111010 23 4a */ { 8, 9 }, 01731 /* 000110 24 2a */ { 2, 3 }, 01732 /* 100110 25 3b */ { 5, 0 }, 01733 /* 010110 26 3d */ { 7, 4 }, 01734 /* 110110 27 4a */ { 8, 11 }, 01735 /* 001110 28 3c */ { 6, 10 }, 01736 /* 101110 29 4a */ { 8, 7 }, 01737 /* 011110 30 4b */ { 9, 0 }, 01738 /* 111110 31 5 */ { 10, 7 }, 01739 /* 000001 32 1 */ { 1, 7 }, 01740 /* 100001 33 2b */ { 3, 0 }, 01741 /* 010001 34 2a */ { 2, 7 }, 01742 /* 110001 35 3d */ { 7, 1 }, 01743 /* 001001 36 2a */ { 2, 11 }, 01744 /* 101001 37 3c */ { 6, 2 }, 01745 /* 011001 38 3a */ { 4, 2 }, 01746 /* 111001 39 4a */ { 8, 3 }, 01747 /* 000101 40 2a */ { 2, 9 }, 01748 /* 100101 41 3d */ { 7, 10 }, 01749 /* 010101 42 3c */ { 6, 7 }, 01750 /* 110101 43 4b */ { 9, 2 }, 01751 /* 001101 44 3b */ { 5, 7 }, 01752 /* 101101 45 4a */ { 8, 8 }, 01753 /* 011101 46 4a */ { 8, 4 }, 01754 /* 111101 47 5 */ { 10, 6 }, 01755 /* 000011 48 2a */ { 2, 6 }, 01756 /* 100011 49 3c */ { 6, 4 }, 01757 /* 010011 50 3b */ { 5, 1 }, 01758 /* 110011 51 4a */ { 8, 10 }, 01759 /* 001011 52 3d */ { 7, 7 }, 01760 /* 101011 53 4b */ { 9, 1 }, 01761 /* 011011 54 4a */ { 8, 5 }, 01762 /* 111011 55 5 */ { 10, 10 }, 01763 /* 000111 56 3a */ { 4, 10 }, 01764 /* 100111 57 4a */ { 8, 1 }, 01765 /* 010111 58 4a */ { 8, 2 }, 01766 /* 110111 59 5 */ { 10, 2 }, 01767 /* 001111 60 4a */ { 8, 0 }, 01768 /* 101111 61 5 */ { 10, 1 }, 01769 /* 011111 62 5 */ { 10, 0 }, 01770 /* 111111 63 6 */ { 11, 0 }, 01771 }; 01772 01773 /* Does this mean anything? If so, then you are either 01774 * superstitious or much more clever than I (or both?). 01775 */ 01776 /* permutation index, P: 0 1 2 3 4 5 6 7 8 9 10 11 */ 01777 /* number of references: 12 9 9 3 4 2 5 6 2 3 7 2 */ 01778 01779 /* 01780 * The array below is a list of all the _positive_ 01781 * permutations of Tetrahedron 0-1-2-3. Given a 01782 * permutation index, it returns a row of 14 values: 01783 * these are the vertex numbers of the permuted 01784 * tetrahedron. The first 4 values are the permuted 01785 * corner indices, the next 6 values are the 01786 * permuted edge midpoint indices, and the final 01787 * entries reference mid-face points inserted 01788 * to maintain a compatible tetrahedralization. 01789 * 01790 * There are 24 entries, 6 for each of the 4 faces of 01791 * the tetrahedron. 01792 */ 01793 int SimplexTemplateRefiner::permutations_from_index[24][14] = { 01794 /* corners midpoints face points */ 01795 /* POSITIVE ARRANGEMENTS */ 01796 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }, /* Face 0-1-2 */ 01797 { 1, 2, 0, 3, 5, 6, 4, 8, 9, 7, 10, 12, 13, 11 }, 01798 { 2, 0, 1, 3, 6, 4, 5, 9, 7, 8, 10, 13, 11, 12 }, 01799 01800 { 0, 3, 1, 2, 7, 8, 4, 6, 9, 5, 11, 13, 12, 10 }, /* Face 0-3-1 */ 01801 { 3, 1, 0, 2, 8, 4, 7, 9, 5, 6, 11, 12, 10, 13 }, 01802 { 1, 0, 3, 2, 4, 7, 8, 5, 6, 9, 11, 10, 13, 12 }, 01803 01804 { 1, 3, 2, 0, 8, 9, 5, 4, 7, 6, 12, 11, 13, 10 }, /* Face 1-3-2 */ 01805 { 3, 2, 1, 0, 9, 5, 8, 7, 6, 4, 12, 13, 10, 11 }, 01806 { 2, 1, 3, 0, 5, 8, 9, 6, 4, 7, 12, 10, 11, 13 }, 01807 01808 { 2, 3, 0, 1, 9, 7, 6, 5, 8, 4, 13, 12, 11, 10 }, /* Face 2-3-0 */ 01809 { 3, 0, 2, 1, 7, 6, 9, 8, 4, 5, 13, 11, 10, 12 }, 01810 { 0, 2, 3, 1, 6, 9, 7, 4, 5, 8, 13, 10, 12, 11 }, 01811 01812 /* NEGATIVE ARRANGEMENTS */ 01813 { 0, 2, 1, 3, 6, 5, 4, 7, 9, 8, 10, 13, 12, 11 }, /* Face 0-1-2 */ 01814 { 2, 1, 0, 3, 5, 4, 6, 9, 8, 7, 10, 12, 11, 13 }, 01815 { 1, 0, 2, 3, 4, 6, 5, 8, 7, 9, 10, 11, 13, 12 }, 01816 01817 { 0, 1, 3, 2, 4, 8, 7, 6, 5, 9, 11, 10, 12, 13 }, /* Face 0-3-1 */ 01818 { 1, 3, 0, 2, 8, 7, 4, 5, 9, 6, 11, 12, 13, 10 }, 01819 { 3, 0, 1, 2, 7, 4, 8, 9, 6, 5, 11, 13, 10, 12 }, 01820 01821 { 1, 2, 3, 0, 5, 9, 8, 4, 6, 7, 12, 10, 13, 11 }, /* Face 1-3-2 */ 01822 { 2, 3, 1, 0, 9, 8, 5, 6, 7, 4, 12, 13, 11, 10 }, 01823 { 3, 1, 2, 0, 8, 5, 9, 7, 4, 6, 12, 11, 10, 13 }, 01824 01825 { 2, 0, 3, 1, 6, 7, 9, 5, 4, 8, 13, 10, 11, 12 }, /* Face 2-3-0 */ 01826 { 0, 3, 2, 1, 7, 9, 6, 4, 8, 5, 13, 11, 12, 10 }, 01827 { 3, 2, 0, 1, 9, 6, 7, 8, 5, 4, 13, 12, 10, 11 } }; 01828 01829 /* 01830 * Below is a list of output tetrahedra. The array is 01831 * generated by TessellatorGenerator.py 01832 * which also generates the code that references it. 01833 * Each set of tetrahedra begins with a single integer 01834 * that is the number of tetrahedra for that particular 01835 * case. It is followed by 5 integers for each output 01836 * tetrahedron; the first four numbers on each row are 01837 * indices of the output tetrahedron. The final number 01838 * is a bit vector specifying which edges of the 01839 * tetrahedron are internal to the parent tetrahedron 01840 * being decomposed. 01841 * 01842 * Multiple lists of output tetrahedra may be 01843 * combined to create the tessellation of a single 01844 * input tetrahedron. 01845 */ 01846 01847 int SimplexTemplateRefiner::templates[] = { 01848 // case 1_0 01849 2, 01850 0, 01851 4, 01852 2, 01853 3, 01854 4, 01855 1, 01856 2, 01857 3, 01858 01859 // case 2a_0 01860 1, 01861 3, 01862 4, 01863 5, 01864 1, 01865 01866 // case 2a, 0>1 01867 2, 01868 0, 01869 4, 01870 2, 01871 3, 01872 4, 01873 5, 01874 2, 01875 3, 01876 01877 // case 2a, 0=1 01878 4, 01879 10, 01880 3, 01881 0, 01882 4, 01883 10, 01884 3, 01885 4, 01886 5, 01887 10, 01888 3, 01889 5, 01890 2, 01891 10, 01892 3, 01893 2, 01894 0, 01895 01896 // case 2b_0 01897 4, 01898 0, 01899 4, 01900 9, 01901 3, 01902 4, 01903 1, 01904 9, 01905 3, 01906 0, 01907 4, 01908 2, 01909 9, 01910 4, 01911 1, 01912 2, 01913 9, 01914 01915 // case 3a_0 01916 1, 01917 4, 01918 7, 01919 6, 01920 0, 01921 01922 // case 3a, 0>2>3<0 01923 3, 01924 1, 01925 3, 01926 2, 01927 4, 01928 4, 01929 6, 01930 3, 01931 2, 01932 4, 01933 6, 01934 7, 01935 3, 01936 01937 // case 3a, 0=2>3<0 01938 5, 01939 4, 01940 6, 01941 7, 01942 3, 01943 10, 01944 1, 01945 2, 01946 3, 01947 10, 01948 2, 01949 6, 01950 3, 01951 10, 01952 6, 01953 4, 01954 3, 01955 10, 01956 4, 01957 1, 01958 3, 01959 01960 // case 3a, 3>0=2<3 01961 5, 01962 1, 01963 3, 01964 2, 01965 7, 01966 10, 01967 1, 01968 2, 01969 7, 01970 10, 01971 2, 01972 6, 01973 7, 01974 10, 01975 6, 01976 4, 01977 7, 01978 10, 01979 4, 01980 1, 01981 7, 01982 01983 // case 3a, 0=2=3=0 01984 11, 01985 2, 01986 6, 01987 10, 01988 13, 01989 3, 01990 7, 01991 13, 01992 11, 01993 4, 01994 1, 01995 10, 01996 11, 01997 11, 01998 6, 01999 10, 02000 4, 02001 11, 02002 6, 02003 13, 02004 10, 02005 11, 02006 6, 02007 7, 02008 13, 02009 11, 02010 6, 02011 4, 02012 7, 02013 2, 02014 10, 02015 11, 02016 13, 02017 1, 02018 10, 02019 11, 02020 2, 02021 2, 02022 11, 02023 3, 02024 13, 02025 3, 02026 2, 02027 1, 02028 11, 02029 02030 // case 3b_0 02031 4, 02032 0, 02033 7, 02034 4, 02035 2, 02036 4, 02037 7, 02038 8, 02039 2, 02040 4, 02041 8, 02042 1, 02043 2, 02044 7, 02045 3, 02046 8, 02047 2, 02048 02049 // case 3c, 0>1,0>3 02050 5, 02051 4, 02052 2, 02053 7, 02054 5, 02055 4, 02056 2, 02057 0, 02058 7, 02059 4, 02060 3, 02061 1, 02062 5, 02063 4, 02064 3, 02065 5, 02066 7, 02067 3, 02068 5, 02069 7, 02070 2, 02071 02072 // case 3c, 1>0,3>0 02073 5, 02074 0, 02075 5, 02076 2, 02077 7, 02078 0, 02079 5, 02080 7, 02081 4, 02082 7, 02083 1, 02084 4, 02085 5, 02086 7, 02087 1, 02088 5, 02089 3, 02090 3, 02091 5, 02092 7, 02093 2, 02094 02095 // case 3c, 0>1,3>0 02096 5, 02097 4, 02098 2, 02099 7, 02100 5, 02101 4, 02102 2, 02103 0, 02104 7, 02105 7, 02106 1, 02107 4, 02108 5, 02109 7, 02110 1, 02111 5, 02112 3, 02113 3, 02114 5, 02115 7, 02116 2, 02117 02118 // case 3c, 1>0,0>3 02119 5, 02120 0, 02121 5, 02122 2, 02123 7, 02124 0, 02125 5, 02126 7, 02127 4, 02128 4, 02129 3, 02130 1, 02131 5, 02132 4, 02133 3, 02134 5, 02135 7, 02136 3, 02137 5, 02138 7, 02139 2, 02140 02141 // case 3c, 0=1,0>3 02142 7, 02143 4, 02144 1, 02145 5, 02146 3, 02147 10, 02148 0, 02149 4, 02150 7, 02151 10, 02152 2, 02153 0, 02154 7, 02155 10, 02156 7, 02157 4, 02158 3, 02159 10, 02160 2, 02161 7, 02162 3, 02163 10, 02164 5, 02165 2, 02166 3, 02167 10, 02168 4, 02169 5, 02170 3, 02171 02172 // case 3c, 3>0,0=1 02173 7, 02174 7, 02175 1, 02176 5, 02177 3, 02178 7, 02179 5, 02180 2, 02181 3, 02182 10, 02183 0, 02184 4, 02185 7, 02186 10, 02187 2, 02188 0, 02189 7, 02190 10, 02191 5, 02192 2, 02193 7, 02194 10, 02195 4, 02196 5, 02197 7, 02198 1, 02199 5, 02200 4, 02201 7, 02202 02203 // case 3c, 0=1,0=3 02204 10, 02205 4, 02206 1, 02207 5, 02208 11, 02209 11, 02210 1, 02211 5, 02212 3, 02213 10, 02214 0, 02215 4, 02216 7, 02217 10, 02218 2, 02219 0, 02220 7, 02221 10, 02222 5, 02223 2, 02224 3, 02225 10, 02226 2, 02227 7, 02228 3, 02229 10, 02230 7, 02231 4, 02232 11, 02233 10, 02234 7, 02235 11, 02236 3, 02237 10, 02238 4, 02239 5, 02240 11, 02241 10, 02242 11, 02243 5, 02244 3, 02245 02246 // case 3d, 0>4,0>2 02247 5, 02248 4, 02249 3, 02250 6, 02251 0, 02252 4, 02253 3, 02254 8, 02255 6, 02256 4, 02257 2, 02258 8, 02259 1, 02260 4, 02261 2, 02262 6, 02263 8, 02264 2, 02265 3, 02266 6, 02267 8, 02268 02269 // case 3d, 4>0,2>0 02270 5, 02271 8, 02272 0, 02273 6, 02274 4, 02275 8, 02276 0, 02277 3, 02278 6, 02279 6, 02280 1, 02281 8, 02282 4, 02283 6, 02284 1, 02285 2, 02286 8, 02287 2, 02288 3, 02289 6, 02290 8, 02291 02292 // case 3d, 0>4,2>0 02293 5, 02294 4, 02295 3, 02296 6, 02297 0, 02298 4, 02299 3, 02300 8, 02301 6, 02302 6, 02303 1, 02304 8, 02305 4, 02306 6, 02307 1, 02308 2, 02309 8, 02310 2, 02311 3, 02312 6, 02313 8, 02314 02315 // case 3d, 4>0,0>2 02316 5, 02317 8, 02318 0, 02319 6, 02320 4, 02321 8, 02322 0, 02323 3, 02324 6, 02325 4, 02326 2, 02327 8, 02328 1, 02329 4, 02330 2, 02331 6, 02332 8, 02333 2, 02334 3, 02335 6, 02336 8, 02337 02338 // case 3d, 0=4,0>2 02339 7, 02340 4, 02341 1, 02342 2, 02343 8, 02344 11, 02345 4, 02346 0, 02347 6, 02348 11, 02349 0, 02350 3, 02351 6, 02352 11, 02353 2, 02354 4, 02355 6, 02356 11, 02357 3, 02358 2, 02359 6, 02360 11, 02361 3, 02362 8, 02363 2, 02364 11, 02365 8, 02366 4, 02367 2, 02368 02369 // case 3d, 2>0,0=4 02370 7, 02371 6, 02372 2, 02373 8, 02374 1, 02375 6, 02376 8, 02377 2, 02378 3, 02379 11, 02380 4, 02381 0, 02382 6, 02383 11, 02384 0, 02385 3, 02386 6, 02387 8, 02388 11, 02389 3, 02390 6, 02391 8, 02392 4, 02393 11, 02394 6, 02395 1, 02396 6, 02397 4, 02398 8, 02399 02400 // case 3d, 0=4,0=2 02401 10, 02402 4, 02403 1, 02404 10, 02405 8, 02406 10, 02407 2, 02408 8, 02409 1, 02410 11, 02411 4, 02412 0, 02413 6, 02414 11, 02415 0, 02416 3, 02417 6, 02418 11, 02419 3, 02420 8, 02421 2, 02422 11, 02423 3, 02424 2, 02425 6, 02426 11, 02427 10, 02428 4, 02429 6, 02430 11, 02431 10, 02432 6, 02433 2, 02434 8, 02435 4, 02436 11, 02437 10, 02438 11, 02439 10, 02440 2, 02441 8, 02442 02443 // case 4a_0 02444 2, 02445 7, 02446 8, 02447 9, 02448 3, 02449 7, 02450 9, 02451 8, 02452 6, 02453 02454 // case 4a, 5>4>3 02455 4, 02456 8, 02457 0, 02458 6, 02459 1, 02460 8, 02461 0, 02462 7, 02463 6, 02464 9, 02465 1, 02466 6, 02467 2, 02468 9, 02469 1, 02470 8, 02471 6, 02472 02473 // case 4a, 3<4>5 02474 4, 02475 8, 02476 0, 02477 6, 02478 1, 02479 8, 02480 0, 02481 7, 02482 6, 02483 8, 02484 2, 02485 6, 02486 9, 02487 8, 02488 2, 02489 1, 02490 6, 02491 02492 // case 4a, 3>4<5 02493 4, 02494 6, 02495 9, 02496 8, 02497 1, 02498 6, 02499 9, 02500 1, 02501 2, 02502 6, 02503 7, 02504 0, 02505 1, 02506 6, 02507 7, 02508 1, 02509 8, 02510 02511 // case 4a, 3=4>5 02512 6, 02513 6, 02514 7, 02515 0, 02516 11, 02517 6, 02518 0, 02519 1, 02520 11, 02521 6, 02522 7, 02523 11, 02524 8, 02525 6, 02526 11, 02527 1, 02528 8, 02529 1, 02530 2, 02531 6, 02532 8, 02533 2, 02534 6, 02535 8, 02536 9, 02537 02538 // case 4a, 5>4,3=4 02539 6, 02540 6, 02541 7, 02542 0, 02543 11, 02544 6, 02545 0, 02546 1, 02547 11, 02548 6, 02549 7, 02550 11, 02551 8, 02552 6, 02553 11, 02554 1, 02555 8, 02556 1, 02557 2, 02558 6, 02559 9, 02560 1, 02561 6, 02562 8, 02563 9, 02564 02565 // case 4a, 3=4=5 02566 8, 02567 6, 02568 7, 02569 0, 02570 11, 02571 6, 02572 0, 02573 1, 02574 11, 02575 6, 02576 7, 02577 11, 02578 8, 02579 6, 02580 11, 02581 1, 02582 8, 02583 6, 02584 1, 02585 2, 02586 12, 02587 6, 02588 2, 02589 9, 02590 12, 02591 6, 02592 9, 02593 8, 02594 12, 02595 6, 02596 8, 02597 1, 02598 12, 02599 02600 // case 4b, 2>1,3>2,4>3,4>1 02601 6, 02602 6, 02603 8, 02604 1, 02605 5, 02606 6, 02607 8, 02608 0, 02609 1, 02610 6, 02611 8, 02612 7, 02613 0, 02614 6, 02615 8, 02616 2, 02617 7, 02618 7, 02619 8, 02620 2, 02621 3, 02622 6, 02623 8, 02624 5, 02625 2, 02626 02627 // case 4b, 2>1,3>2,3>4,4>1 02628 6, 02629 6, 02630 8, 02631 1, 02632 5, 02633 6, 02634 8, 02635 7, 02636 1, 02637 6, 02638 7, 02639 0, 02640 1, 02641 8, 02642 7, 02643 3, 02644 2, 02645 6, 02646 8, 02647 5, 02648 2, 02649 6, 02650 8, 02651 2, 02652 7, 02653 02654 // case 4b, 2>1,3>2,3>4,4>1, a 02655 6, 02656 7, 02657 8, 02658 1, 02659 5, 02660 6, 02661 5, 02662 7, 02663 1, 02664 6, 02665 7, 02666 0, 02667 1, 02668 8, 02669 7, 02670 3, 02671 2, 02672 7, 02673 8, 02674 5, 02675 2, 02676 6, 02677 5, 02678 2, 02679 7, 02680 02681 // case 4b, 2>1,2>3,4>3,4>1 02682 6, 02683 6, 02684 8, 02685 5, 02686 2, 02687 6, 02688 8, 02689 2, 02690 3, 02691 6, 02692 8, 02693 3, 02694 7, 02695 6, 02696 8, 02697 7, 02698 0, 02699 6, 02700 8, 02701 0, 02702 1, 02703 6, 02704 8, 02705 1, 02706 5, 02707 02708 // case 4b, 1=2,3>2,3>4,4>1 02709 9, 02710 10, 02711 6, 02712 0, 02713 7, 02714 10, 02715 1, 02716 5, 02717 8, 02718 10, 02719 0, 02720 1, 02721 7, 02722 10, 02723 7, 02724 1, 02725 8, 02726 6, 02727 7, 02728 10, 02729 8, 02730 6, 02731 10, 02732 5, 02733 8, 02734 6, 02735 2, 02736 7, 02737 8, 02738 6, 02739 5, 02740 2, 02741 8, 02742 7, 02743 8, 02744 2, 02745 3, 02746 02747 // case 4b, 1=2,2>3,4>3,1>4 02748 9, 02749 10, 02750 6, 02751 0, 02752 7, 02753 10, 02754 1, 02755 5, 02756 8, 02757 10, 02758 0, 02759 1, 02760 8, 02761 10, 02762 7, 02763 0, 02764 8, 02765 6, 02766 7, 02767 10, 02768 8, 02769 6, 02770 10, 02771 5, 02772 8, 02773 6, 02774 3, 02775 7, 02776 8, 02777 6, 02778 5, 02779 3, 02780 8, 02781 6, 02782 5, 02783 2, 02784 3, 02785 02786 // case 4b, 1=2,2>3,4>3,4>1 02787 9, 02788 10, 02789 6, 02790 0, 02791 7, 02792 10, 02793 1, 02794 5, 02795 8, 02796 10, 02797 0, 02798 1, 02799 8, 02800 10, 02801 7, 02802 0, 02803 8, 02804 6, 02805 7, 02806 10, 02807 8, 02808 6, 02809 10, 02810 5, 02811 8, 02812 6, 02813 3, 02814 7, 02815 8, 02816 6, 02817 5, 02818 2, 02819 8, 02820 6, 02821 2, 02822 3, 02823 8, 02824 02825 // case 4b, 1=2,3>2,3=4,4>1 02826 11, 02827 10, 02828 6, 02829 0, 02830 7, 02831 10, 02832 1, 02833 5, 02834 8, 02835 10, 02836 0, 02837 1, 02838 11, 02839 10, 02840 11, 02841 1, 02842 8, 02843 10, 02844 0, 02845 11, 02846 7, 02847 10, 02848 7, 02849 11, 02850 8, 02851 6, 02852 7, 02853 10, 02854 8, 02855 6, 02856 10, 02857 5, 02858 8, 02859 6, 02860 2, 02861 7, 02862 8, 02863 6, 02864 5, 02865 2, 02866 8, 02867 7, 02868 8, 02869 2, 02870 3, 02871 02872 // case 4b, 4>1=2=3,4>3 02873 12, 02874 10, 02875 6, 02876 0, 02877 7, 02878 10, 02879 1, 02880 5, 02881 8, 02882 10, 02883 0, 02884 1, 02885 8, 02886 10, 02887 7, 02888 0, 02889 8, 02890 13, 02891 6, 02892 2, 02893 5, 02894 13, 02895 3, 02896 7, 02897 8, 02898 13, 02899 2, 02900 3, 02901 8, 02902 13, 02903 2, 02904 8, 02905 5, 02906 6, 02907 7, 02908 10, 02909 8, 02910 6, 02911 10, 02912 5, 02913 8, 02914 6, 02915 13, 02916 7, 02917 8, 02918 6, 02919 5, 02920 13, 02921 8, 02922 02923 // case 4b, 1=2=3>4,1>4 02924 12, 02925 10, 02926 6, 02927 0, 02928 7, 02929 10, 02930 1, 02931 5, 02932 8, 02933 10, 02934 0, 02935 1, 02936 7, 02937 10, 02938 7, 02939 1, 02940 8, 02941 13, 02942 6, 02943 2, 02944 5, 02945 13, 02946 3, 02947 7, 02948 8, 02949 13, 02950 2, 02951 3, 02952 5, 02953 13, 02954 3, 02955 8, 02956 5, 02957 6, 02958 7, 02959 10, 02960 8, 02961 6, 02962 10, 02963 5, 02964 8, 02965 6, 02966 13, 02967 7, 02968 8, 02969 6, 02970 5, 02971 13, 02972 8, 02973 02974 // case 4b, 1=2=3=4=1 02975 16, 02976 10, 02977 6, 02978 0, 02979 7, 02980 10, 02981 1, 02982 5, 02983 8, 02984 10, 02985 0, 02986 1, 02987 11, 02988 10, 02989 11, 02990 1, 02991 8, 02992 10, 02993 0, 02994 11, 02995 7, 02996 10, 02997 7, 02998 11, 02999 8, 03000 13, 03001 6, 03002 2, 03003 5, 03004 13, 03005 3, 03006 7, 03007 8, 03008 13, 03009 2, 03010 3, 03011 12, 03012 13, 03013 2, 03014 12, 03015 5, 03016 13, 03017 12, 03018 3, 03019 8, 03020 13, 03021 12, 03022 5, 03023 8, 03024 6, 03025 7, 03026 10, 03027 8, 03028 6, 03029 10, 03030 5, 03031 8, 03032 6, 03033 5, 03034 13, 03035 8, 03036 6, 03037 13, 03038 7, 03039 8, 03040 03041 // case 5_0 03042 2, 03043 7, 03044 8, 03045 9, 03046 3, 03047 6, 03048 5, 03049 2, 03050 9, 03051 03052 // case 5, 1>2,3>4 03053 5, 03054 5, 03055 7, 03056 1, 03057 8, 03058 5, 03059 7, 03060 0, 03061 1, 03062 5, 03063 7, 03064 6, 03065 0, 03066 5, 03067 7, 03068 9, 03069 6, 03070 5, 03071 7, 03072 8, 03073 9, 03074 03075 // case 5, 1>2,4>3 03076 5, 03077 0, 03078 5, 03079 6, 03080 7, 03081 0, 03082 5, 03083 7, 03084 8, 03085 0, 03086 5, 03087 8, 03088 1, 03089 5, 03090 7, 03091 9, 03092 6, 03093 5, 03094 7, 03095 8, 03096 9, 03097 03098 // case 5, 1>2,4>3, a 03099 5, 03100 0, 03101 5, 03102 6, 03103 8, 03104 0, 03105 6, 03106 7, 03107 8, 03108 0, 03109 5, 03110 8, 03111 1, 03112 5, 03113 8, 03114 9, 03115 6, 03116 6, 03117 7, 03118 8, 03119 9, 03120 03121 // case 5, 1=2,3>4 03122 8, 03123 10, 03124 6, 03125 0, 03126 7, 03127 10, 03128 1, 03129 5, 03130 8, 03131 10, 03132 0, 03133 1, 03134 7, 03135 10, 03136 7, 03137 1, 03138 8, 03139 10, 03140 8, 03141 5, 03142 9, 03143 10, 03144 6, 03145 7, 03146 9, 03147 10, 03148 7, 03149 8, 03150 9, 03151 10, 03152 5, 03153 6, 03154 9, 03155 03156 // case 5, 1=2,3>4, a 03157 8, 03158 10, 03159 6, 03160 0, 03161 7, 03162 10, 03163 1, 03164 5, 03165 8, 03166 10, 03167 0, 03168 1, 03169 7, 03170 10, 03171 7, 03172 1, 03173 8, 03174 7, 03175 8, 03176 5, 03177 9, 03178 10, 03179 6, 03180 7, 03181 5, 03182 10, 03183 7, 03184 8, 03185 5, 03186 5, 03187 9, 03188 6, 03189 7, 03190 03191 // case 5, 1=2,3>4, b 03192 8, 03193 10, 03194 6, 03195 0, 03196 7, 03197 10, 03198 1, 03199 5, 03200 8, 03201 10, 03202 0, 03203 1, 03204 7, 03205 10, 03206 7, 03207 1, 03208 8, 03209 6, 03210 8, 03211 5, 03212 9, 03213 10, 03214 6, 03215 7, 03216 8, 03217 10, 03218 6, 03219 8, 03220 5, 03221 8, 03222 9, 03223 6, 03224 7, 03225 03226 // case 5, 1=2,3=4 03227 10, 03228 10, 03229 6, 03230 0, 03231 7, 03232 10, 03233 1, 03234 5, 03235 8, 03236 10, 03237 0, 03238 1, 03239 11, 03240 10, 03241 11, 03242 1, 03243 8, 03244 10, 03245 0, 03246 11, 03247 7, 03248 10, 03249 7, 03250 11, 03251 8, 03252 10, 03253 8, 03254 5, 03255 9, 03256 10, 03257 6, 03258 7, 03259 9, 03260 10, 03261 7, 03262 8, 03263 9, 03264 10, 03265 5, 03266 6, 03267 9, 03268 03269 // case 6_0 03270 4, 03271 7, 03272 8, 03273 9, 03274 3, 03275 6, 03276 5, 03277 2, 03278 9, 03279 4, 03280 1, 03281 5, 03282 8, 03283 0, 03284 4, 03285 6, 03286 7, 03287 03288 // case 6_1 03289 4, 03290 6, 03291 4, 03292 5, 03293 8, 03294 6, 03295 5, 03296 9, 03297 8, 03298 6, 03299 9, 03300 7, 03301 8, 03302 6, 03303 7, 03304 4, 03305 8, 03306 03307 // case 6_1, a 03308 4, 03309 5, 03310 8, 03311 9, 03312 7, 03313 5, 03314 9, 03315 6, 03316 7, 03317 5, 03318 6, 03319 4, 03320 7, 03321 5, 03322 4, 03323 8, 03324 7, 03325 03326 // case 6_1, b 03327 4, 03328 4, 03329 5, 03330 6, 03331 9, 03332 4, 03333 6, 03334 7, 03335 9, 03336 4, 03337 7, 03338 8, 03339 9, 03340 4, 03341 8, 03342 5, 03343 9, 03344 03345 }; 03346 03347 } // namespace moab