Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /** 00002 * MOAB, a Mesh-Oriented datABase, is a software component for creating, 00003 * storing and accessing finite element mesh data. 00004 * 00005 * Copyright 2004 Sandia Corporation. Under the terms of Contract 00006 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 00007 * retains certain rights in this software. 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 */ 00015 00016 #ifdef WIN32 00017 // turn off warnings that say they debugging identifier has been truncated 00018 // this warning comes up when using some STL containers 00019 #pragma warning( disable : 4786 ) 00020 #endif 00021 00022 #define MOAB_MPE_LOG "moab.mpe" 00023 00024 #include <iostream> 00025 #include <sstream> 00026 #include <vector> 00027 #include <string> 00028 #include <algorithm> 00029 #include "moab/Core.hpp" 00030 #include "MeshSetSequence.hpp" 00031 #include "ElementSequence.hpp" 00032 #include "VertexSequence.hpp" 00033 #include <cassert> 00034 #include "AEntityFactory.hpp" 00035 #include "ReadUtil.hpp" 00036 #include "WriteUtil.hpp" 00037 #include "moab/CN.hpp" 00038 #include "moab/HigherOrderFactory.hpp" 00039 #include "SequenceManager.hpp" 00040 #include "moab/Error.hpp" 00041 #include "moab/ReaderWriterSet.hpp" 00042 #include "moab/ReaderIface.hpp" 00043 #include "moab/WriterIface.hpp" 00044 #include "moab/ScdInterface.hpp" 00045 #include "moab/SetIterator.hpp" 00046 00047 #include "BitTag.hpp" 00048 #include "DenseTag.hpp" 00049 #include "MeshTag.hpp" 00050 #include "SparseTag.hpp" 00051 #include "VarLenDenseTag.hpp" 00052 #include "VarLenSparseTag.hpp" 00053 00054 #include <sys/stat.h> 00055 #include <cerrno> 00056 #include <cstring> 00057 00058 #ifdef MOAB_HAVE_AHF 00059 #include "moab/HalfFacetRep.hpp" 00060 #endif 00061 00062 #ifdef MOAB_HAVE_MPI 00063 /* Leave ParallelComm.hpp before mpi.h or MPICH2 will fail 00064 * because its C++ headers do not like SEEK_* macros. 00065 */ 00066 #include "moab/ParallelComm.hpp" 00067 #include "moab_mpi.h" 00068 #include "ReadParallel.hpp" 00069 #endif 00070 00071 #ifdef MOAB_HAVE_HDF5 00072 #ifdef MOAB_HAVE_HDF5_PARALLEL 00073 #include "WriteHDF5Parallel.hpp" 00074 typedef moab::WriteHDF5Parallel DefaultWriter; 00075 #define DefaultWriterName "WriteHDF5Parallel" 00076 #else 00077 #include "WriteHDF5.hpp" 00078 typedef moab::WriteHDF5 DefaultWriter; 00079 #define DefaultWriterName "WriteHDF5" 00080 #endif 00081 #elif defined( MOAB_HAVE_NETCDF ) 00082 #include "WriteNCDF.hpp" 00083 typedef moab::WriteNCDF DefaultWriter; 00084 #define DefaultWriterName "WriteNCDF" 00085 #else 00086 #include "WriteVtk.hpp" 00087 typedef moab::WriteVtk DefaultWriter; 00088 #define DefaultWriterName "WriteVtk" 00089 #endif 00090 #include "MBTagConventions.hpp" 00091 #include "ExoIIUtil.hpp" 00092 #include "EntitySequence.hpp" 00093 #include "moab/FileOptions.hpp" 00094 #ifdef LINUX 00095 #include <dlfcn.h> 00096 #include <dirent.h> 00097 #endif 00098 00099 #ifdef MOAB_HAVE_MPI 00100 #include "moab_mpe.h" 00101 #endif 00102 00103 // MOAB used to use a NULL handle list and a zero handle count 00104 // to indicate that tag functions are to operate on the global/mesh 00105 // value of the tag. For the 3.0 release MOAB also accepted a handle 00106 // with a value of 0 to indicate the same. Now we want to drop the 00107 // old NULL list method because a) it is one less special case that 00108 // must be handled in the tag get/set paths and b) it aviods unexpected 00109 // segfaults when applications requested tag data with an empty list 00110 // of handles. 00111 // 00112 // Define this constant to revert to the old behavior, but also print 00113 // a warning. 00114 #define ALLOW_NULL_FOR_MESH_TAG 00115 // 00116 // Define this to print an error and abort() when a NULL handle list 00117 // is passed. This is intended as an interim solution to help catch 00118 // spots in code that haven't been updated for the change. 00119 #undef DISALLOW_EMPTY_HANDLE_LIST_FOR_TAGS 00120 // 00121 // The eventual goal is to define neither of the above, eliminating the 00122 // check and allowing applications to safely request tag data for no 00123 // entities. 00124 00125 static void warn_null_array_mesh_tag() 00126 { 00127 std::cerr << "WARNING: Accepting empty array to indicate mesh tag" << std::endl; 00128 } 00129 00130 #ifdef ALLOW_NULL_FOR_MESH_TAG 00131 #define CHECK_MESH_NULL \ 00132 EntityHandle root = 0; \ 00133 if( NULL == entity_handles && 0 == num_entities ) \ 00134 { \ 00135 entity_handles = &root; \ 00136 num_entities = 1; \ 00137 warn_null_array_mesh_tag(); \ 00138 } 00139 #elif defined( DISALLOW_EMPTY_HANDLE_LIST_FOR_TAGS ) 00140 #define CHECK_MESH_NULL \ 00141 if( NULL == entity_handles ) \ 00142 { \ 00143 std::cerr << "ERROR: Deprecated NULL handle list at " __FILE__ ":" << __LINE__ << std::endl; \ 00144 abort(); \ 00145 } 00146 #else 00147 #define CHECK_MESH_NULL 00148 #endif 00149 00150 namespace moab 00151 { 00152 00153 using namespace std; 00154 00155 static inline const MeshSet* get_mesh_set( const SequenceManager* sm, EntityHandle h ) 00156 { 00157 const EntitySequence* seq; 00158 if( MBENTITYSET != TYPE_FROM_HANDLE( h ) || MB_SUCCESS != sm->find( h, seq ) ) return 0; 00159 return reinterpret_cast< const MeshSetSequence* >( seq )->get_set( h ); 00160 } 00161 00162 static inline MeshSet* get_mesh_set( SequenceManager* sm, EntityHandle h ) 00163 { 00164 EntitySequence* seq; 00165 if( MBENTITYSET != TYPE_FROM_HANDLE( h ) || MB_SUCCESS != sm->find( h, seq ) ) return 0; 00166 return reinterpret_cast< MeshSetSequence* >( seq )->get_set( h ); 00167 } 00168 00169 //! Constructor 00170 Core::Core() 00171 { 00172 if( initialize() != MB_SUCCESS ) 00173 { 00174 printf( "Error initializing moab::Core\n" ); 00175 exit( 1 ); 00176 } 00177 } 00178 00179 //! destructor 00180 Core::~Core() 00181 { 00182 if( mMBWriteUtil ) delete mMBWriteUtil; 00183 if( mMBReadUtil ) delete mMBReadUtil; 00184 if( scdInterface ) delete scdInterface; 00185 00186 mMBWriteUtil = NULL; 00187 mMBReadUtil = NULL; 00188 scdInterface = NULL; 00189 00190 deinitialize(); 00191 } 00192 00193 ErrorCode Core::initialize() 00194 { 00195 #ifdef MOAB_HAVE_MPI 00196 int flag; 00197 if( MPI_SUCCESS == MPI_Initialized( &flag ) ) 00198 { 00199 if( flag ) 00200 { 00201 writeMPELog = !MPE_Initialized_logging(); 00202 if( writeMPELog ) (void)MPE_Init_log(); 00203 } 00204 } 00205 #endif 00206 00207 initErrorHandlerInCore = false; 00208 if( !MBErrorHandler_Initialized() ) 00209 { 00210 MBErrorHandler_Init(); 00211 initErrorHandlerInCore = true; 00212 } 00213 00214 geometricDimension = 3; 00215 materialTag = 0; 00216 neumannBCTag = 0; 00217 dirichletBCTag = 0; 00218 geomDimensionTag = 0; 00219 globalIdTag = 0; 00220 00221 sequenceManager = new( std::nothrow ) SequenceManager; 00222 if( !sequenceManager ) return MB_MEMORY_ALLOCATION_FAILED; 00223 00224 aEntityFactory = new( std::nothrow ) AEntityFactory( this ); 00225 if( !aEntityFactory ) return MB_MEMORY_ALLOCATION_FAILED; 00226 00227 mError = new( std::nothrow ) Error; 00228 if( !mError ) return MB_MEMORY_ALLOCATION_FAILED; 00229 00230 mMBWriteUtil = NULL; 00231 mMBReadUtil = NULL; 00232 scdInterface = NULL; 00233 00234 // Readers and writers try to get pointers to above utils. 00235 // Do this after pointers are initialized. (Pointers should 00236 // really be initialized in constructor to avoid this kind 00237 // of thing -- j.kraftcheck.) 00238 readerWriterSet = new( std::nothrow ) ReaderWriterSet( this ); 00239 if( !readerWriterSet ) return MB_MEMORY_ALLOCATION_FAILED; 00240 00241 material_tag(); 00242 neumannBC_tag(); 00243 dirichletBC_tag(); 00244 geom_dimension_tag(); 00245 globalId_tag(); 00246 00247 #ifdef MOAB_HAVE_AHF 00248 ahfRep = new HalfFacetRep( this ); 00249 if( !ahfRep ) return MB_MEMORY_ALLOCATION_FAILED; 00250 mesh_modified = false; 00251 #endif 00252 00253 return MB_SUCCESS; 00254 } 00255 00256 EntityHandle Core::get_root_set() 00257 { 00258 return 0; 00259 } 00260 00261 void Core::deinitialize() 00262 { 00263 00264 #ifdef MOAB_HAVE_MPI 00265 std::vector< ParallelComm* > pc_list; 00266 ParallelComm::get_all_pcomm( this, pc_list ); 00267 for( std::vector< ParallelComm* >::iterator vit = pc_list.begin(); vit != pc_list.end(); ++vit ) 00268 delete *vit; 00269 #endif 00270 00271 #ifdef MOAB_HAVE_AHF 00272 delete ahfRep; 00273 ahfRep = 0; 00274 #endif 00275 00276 if( aEntityFactory ) delete aEntityFactory; 00277 00278 aEntityFactory = 0; 00279 00280 while( !tagList.empty() ) 00281 tag_delete( tagList.front() ); 00282 00283 if( sequenceManager ) delete sequenceManager; 00284 00285 sequenceManager = 0; 00286 00287 delete readerWriterSet; 00288 readerWriterSet = 0; 00289 00290 if( mError ) delete mError; 00291 mError = 0; 00292 00293 #ifdef MOAB_HAVE_MPI 00294 if( writeMPELog ) 00295 { 00296 const char* default_log = MOAB_MPE_LOG; 00297 const char* logfile = getenv( "MPE_LOG_FILE" ); 00298 if( !logfile ) logfile = default_log; 00299 MPE_Finish_log( logfile ); 00300 } 00301 #endif 00302 00303 if( initErrorHandlerInCore ) MBErrorHandler_Finalize(); 00304 } 00305 00306 ErrorCode Core::query_interface_type( const std::type_info& interface_type, void*& ptr ) 00307 { 00308 if( interface_type == typeid( ReadUtilIface ) ) 00309 { 00310 if( !mMBReadUtil ) mMBReadUtil = new ReadUtil( this, mError ); 00311 ptr = static_cast< ReadUtilIface* >( mMBReadUtil ); 00312 } 00313 else if( interface_type == typeid( WriteUtilIface ) ) 00314 { 00315 if( !mMBWriteUtil ) mMBWriteUtil = new WriteUtil( this ); 00316 ptr = static_cast< WriteUtilIface* >( mMBWriteUtil ); 00317 } 00318 else if( interface_type == typeid( ReaderWriterSet ) ) 00319 { 00320 ptr = reader_writer_set(); 00321 } 00322 else if( interface_type == typeid( Error ) ) 00323 { 00324 ptr = mError; 00325 } 00326 else if( interface_type == typeid( ExoIIInterface ) ) 00327 { 00328 ptr = static_cast< ExoIIInterface* >( new ExoIIUtil( this ) ); 00329 } 00330 else if( interface_type == typeid( ScdInterface ) ) 00331 { 00332 if( !scdInterface ) scdInterface = new ScdInterface( this ); 00333 ptr = scdInterface; 00334 } 00335 else 00336 { 00337 ptr = 0; 00338 return MB_FAILURE; 00339 } 00340 return MB_SUCCESS; 00341 } 00342 00343 ErrorCode Core::release_interface_type( const std::type_info& interface_type, void* iface ) 00344 { 00345 if( interface_type == typeid( ExoIIInterface ) ) 00346 delete static_cast< ExoIIInterface* >( iface ); 00347 else if( interface_type != typeid( ReadUtilIface ) && interface_type != typeid( WriteUtilIface ) && 00348 interface_type != typeid( ReaderWriterSet ) && interface_type != typeid( Error ) && 00349 interface_type != typeid( ScdInterface ) ) 00350 return MB_FAILURE; 00351 00352 return MB_SUCCESS; 00353 } 00354 00355 int Core::QueryInterface( const MBuuid& uuid, UnknownInterface** iface ) 00356 { 00357 *iface = 0; 00358 if( uuid == IDD_MBUnknown ) *iface = this; 00359 if( uuid == IDD_MBCore ) 00360 *iface = this; 00361 else 00362 return 0; 00363 return 1; 00364 } 00365 00366 float Core::impl_version( std::string* version_string ) 00367 { 00368 if( version_string ) *version_string = MOAB_VERSION_STRING; 00369 00370 return MOAB_VERSION_MAJOR + MOAB_VERSION_MINOR / 100.0f; 00371 } 00372 00373 //! get the type from a handle, returns type 00374 EntityType Core::type_from_handle( const EntityHandle handle ) const 00375 { 00376 if( !handle ) // root set 00377 return MBENTITYSET; 00378 else 00379 return TYPE_FROM_HANDLE( handle ); 00380 } 00381 00382 //! get the id from a handle, returns id 00383 EntityID Core::id_from_handle( const EntityHandle handle ) const 00384 { 00385 return ID_FROM_HANDLE( handle ); 00386 } 00387 00388 //! get a handle from an id and type 00389 ErrorCode Core::handle_from_id( const EntityType entity_type, const EntityID id, EntityHandle& handle ) const 00390 { 00391 int err; 00392 handle = CREATE_HANDLE( entity_type, id, err ); 00393 00394 // check to see if handle exists 00395 const EntitySequence* dummy_seq = 0; 00396 ErrorCode error_code = sequence_manager()->find( handle, dummy_seq ); 00397 return error_code; 00398 } 00399 00400 int Core::dimension_from_handle( const EntityHandle handle ) const 00401 { 00402 if( !handle ) // root set 00403 return 4; 00404 else 00405 return CN::Dimension( TYPE_FROM_HANDLE( handle ) ); 00406 } 00407 00408 //! load mesh from data in file 00409 //! NOTE: if there is mesh already present, the new mesh will be added 00410 ErrorCode Core::load_mesh( const char* file_name, const int* block_id_list, const int num_blocks ) 00411 { 00412 const char* name = block_id_list ? MATERIAL_SET_TAG_NAME : 0; 00413 return load_file( file_name, 0, 0, name, block_id_list, num_blocks ); 00414 } 00415 00416 ErrorCode Core::load_file( const char* file_name, 00417 const EntityHandle* file_set, 00418 const char* setoptions, 00419 const char* set_tag_name, 00420 const int* set_tag_vals, 00421 int num_set_tag_vals ) 00422 { 00423 FileOptions opts( setoptions ); 00424 ErrorCode rval; 00425 ReaderIface::IDTag t = { set_tag_name, set_tag_vals, num_set_tag_vals }; 00426 ReaderIface::SubsetList sl = { &t, 1, 0, 0 }; 00427 00428 assert( !file_set || ( *file_set && is_valid( *file_set ) ) ); 00429 if( file_set && !*file_set ) 00430 { 00431 MB_SET_GLB_ERR( MB_FAILURE, "Non-NULL file set pointer should point to non-NULL set" ); 00432 } 00433 00434 // if reading in parallel, call a different reader 00435 std::string parallel_opt; 00436 rval = opts.get_option( "PARALLEL", parallel_opt ); 00437 if( MB_SUCCESS == rval ) 00438 { 00439 #ifdef MOAB_HAVE_MPI 00440 ParallelComm* pcomm = 0; 00441 int pcomm_id; 00442 rval = opts.get_int_option( "PARALLEL_COMM", pcomm_id ); 00443 if( MB_ENTITY_NOT_FOUND == rval ) rval = opts.get_int_option( "PCOMM", pcomm_id ); 00444 if( rval == MB_SUCCESS ) 00445 { 00446 pcomm = ParallelComm::get_pcomm( this, pcomm_id ); 00447 if( !pcomm ) return MB_ENTITY_NOT_FOUND; 00448 } 00449 else if( rval != MB_ENTITY_NOT_FOUND ) 00450 return rval; 00451 if( set_tag_name && num_set_tag_vals ) 00452 { 00453 rval = ReadParallel( this, pcomm ).load_file( file_name, file_set, opts, &sl );MB_CHK_ERR( rval ); 00454 } 00455 else 00456 { 00457 rval = ReadParallel( this, pcomm ).load_file( file_name, file_set, opts );MB_CHK_ERR( rval ); 00458 } 00459 #else 00460 MB_SET_GLB_ERR( MB_FAILURE, "PARALLEL option not valid, this instance compiled for serial execution" ); 00461 #endif 00462 } 00463 else 00464 { 00465 if( set_tag_name && num_set_tag_vals ) 00466 { 00467 rval = serial_load_file( file_name, file_set, opts, &sl );MB_CHK_ERR( rval ); 00468 } 00469 else 00470 { 00471 rval = serial_load_file( file_name, file_set, opts );MB_CHK_ERR( rval ); 00472 } 00473 } 00474 00475 if( MB_SUCCESS == rval && !opts.all_seen() ) 00476 { 00477 std::string bad_opt; 00478 if( MB_SUCCESS == opts.get_unseen_option( bad_opt ) ) 00479 { 00480 MB_SET_ERR( MB_UNHANDLED_OPTION, "Unrecognized option: \"" << bad_opt << "\"" ); 00481 } 00482 else 00483 { 00484 MB_SET_ERR( MB_UNHANDLED_OPTION, "Unrecognized option" ); 00485 } 00486 } 00487 00488 return MB_SUCCESS; 00489 } 00490 00491 void Core::clean_up_failed_read( const Range& initial_ents, std::vector< Tag > initial_tags ) 00492 { 00493 Range new_ents; 00494 get_entities_by_handle( 0, new_ents ); 00495 new_ents = subtract( new_ents, initial_ents ); 00496 delete_entities( new_ents ); 00497 00498 std::vector< Tag > all_tags, new_tags; 00499 tag_get_tags( all_tags ); 00500 std::sort( initial_tags.begin(), initial_tags.end() ); 00501 std::sort( all_tags.begin(), all_tags.end() ); 00502 std::set_difference( all_tags.begin(), all_tags.end(), initial_tags.begin(), initial_tags.end(), 00503 std::back_inserter( new_tags ) ); 00504 while( !new_tags.empty() ) 00505 { 00506 tag_delete( new_tags.back() ); 00507 new_tags.pop_back(); 00508 } 00509 } 00510 00511 ErrorCode Core::serial_load_file( const char* file_name, 00512 const EntityHandle* file_set, 00513 const FileOptions& opts, 00514 const ReaderIface::SubsetList* subsets, 00515 const Tag* id_tag ) 00516 { 00517 int status; 00518 #if defined( WIN32 ) || defined( WIN64 ) || defined( MSC_VER ) 00519 struct _stat stat_data; 00520 status = _stat( file_name, &stat_data ); 00521 #else 00522 struct stat stat_data; 00523 status = stat( file_name, &stat_data ); 00524 #endif 00525 if( status ) 00526 { 00527 MB_SET_GLB_ERR( MB_FILE_DOES_NOT_EXIST, file_name << ": " << strerror( errno ) ); 00528 } 00529 #if defined( WIN32 ) || defined( WIN64 ) || defined( MSC_VER ) 00530 else if( stat_data.st_mode & _S_IFDIR ) 00531 { 00532 #else 00533 else if( S_ISDIR( stat_data.st_mode ) ) 00534 { 00535 #endif 00536 MB_SET_GLB_ERR( MB_FILE_DOES_NOT_EXIST, file_name << ": Cannot read directory/folder" ); 00537 } 00538 00539 const ReaderWriterSet* set = reader_writer_set(); 00540 00541 Range initial_ents; 00542 ErrorCode rval = get_entities_by_handle( 0, initial_ents );MB_CHK_ERR( rval ); 00543 00544 std::vector< Tag > initial_tags; 00545 rval = tag_get_tags( initial_tags );MB_CHK_ERR( rval ); 00546 00547 // otherwise try using the file extension to select a reader 00548 std::string ext = set->extension_from_filename( file_name ); 00549 00550 // Try all the readers 00551 ReaderWriterSet::iterator iter; 00552 rval = MB_FAILURE; 00553 bool tried_one = false; 00554 for( iter = set->begin(); iter != set->end(); ++iter ) 00555 { 00556 if( !iter->reads_extension( ext.c_str() ) ) continue; 00557 00558 ReaderIface* reader = iter->make_reader( this ); 00559 if( NULL != reader ) 00560 { 00561 tried_one = true; 00562 rval = reader->load_file( file_name, file_set, opts, subsets, id_tag ); 00563 delete reader; 00564 if( MB_SUCCESS == rval ) break; 00565 clean_up_failed_read( initial_ents, initial_tags ); 00566 } 00567 } 00568 00569 if( MB_SUCCESS != rval && !tried_one ) 00570 { 00571 // didn't recognize the extension; try all of them now 00572 for( iter = set->begin(); iter != set->end(); ++iter ) 00573 { 00574 ReaderIface* reader = iter->make_reader( this ); 00575 if( !reader ) continue; 00576 rval = reader->load_file( file_name, file_set, opts, subsets, id_tag ); 00577 delete reader; 00578 if( MB_SUCCESS == rval ) 00579 break; 00580 else 00581 clean_up_failed_read( initial_ents, initial_tags ); 00582 } 00583 } 00584 00585 if( MB_SUCCESS != rval ) 00586 { 00587 clean_up_failed_read( initial_ents, initial_tags ); 00588 MB_SET_ERR( rval, "Failed to load file after trying all possible readers" ); 00589 } 00590 else if( file_set ) 00591 { 00592 Range new_ents; 00593 get_entities_by_handle( 0, new_ents ); 00594 new_ents = subtract( new_ents, initial_ents ); 00595 00596 // Check if gather set exists 00597 EntityHandle gather_set; 00598 rval = mMBReadUtil->get_gather_set( gather_set ); 00599 if( MB_SUCCESS == rval ) 00600 { 00601 // Exclude gather set itself 00602 new_ents.erase( gather_set ); 00603 00604 // Exclude gather set entities 00605 Range gather_ents; 00606 rval = get_entities_by_handle( gather_set, gather_ents ); 00607 if( MB_SUCCESS == rval ) new_ents = subtract( new_ents, gather_ents ); 00608 } 00609 00610 rval = add_entities( *file_set, new_ents ); 00611 } 00612 00613 return rval; 00614 } // namespace moab 00615 00616 ErrorCode Core::serial_read_tag( const char* file_name, 00617 const char* tag_name, 00618 const FileOptions& opts, 00619 std::vector< int >& vals, 00620 const ReaderIface::SubsetList* subsets ) 00621 { 00622 ErrorCode rval = MB_FAILURE; 00623 const ReaderWriterSet* set = reader_writer_set(); 00624 00625 // otherwise try using the file extension to select a reader 00626 ReaderIface* reader = set->get_file_extension_reader( file_name ); 00627 if( reader ) 00628 { 00629 rval = reader->read_tag_values( file_name, tag_name, opts, vals, subsets ); 00630 delete reader; 00631 } 00632 else 00633 { 00634 // Try all the readers 00635 ReaderWriterSet::iterator iter; 00636 for( iter = set->begin(); iter != set->end(); ++iter ) 00637 { 00638 reader = iter->make_reader( this ); 00639 if( NULL != reader ) 00640 { 00641 rval = reader->read_tag_values( file_name, tag_name, opts, vals, subsets ); 00642 delete reader; 00643 if( MB_SUCCESS == rval ) break; 00644 } 00645 } 00646 } 00647 00648 return rval; 00649 } 00650 00651 ErrorCode Core::write_mesh( const char* file_name, const EntityHandle* output_list, const int num_sets ) 00652 { 00653 return write_file( file_name, 0, 0, output_list, num_sets ); 00654 } 00655 00656 ErrorCode Core::write_file( const char* file_name, 00657 const char* file_type, 00658 const char* options_string, 00659 const EntityHandle* output_sets, 00660 int num_output_sets, 00661 const Tag* tag_list, 00662 int num_tags ) 00663 { 00664 Range range; 00665 std::copy( output_sets, output_sets + num_output_sets, range_inserter( range ) ); 00666 return write_file( file_name, file_type, options_string, range, tag_list, num_tags ); 00667 } 00668 00669 ErrorCode Core::write_file( const char* file_name, 00670 const char* file_type, 00671 const char* options_string, 00672 const Range& output_sets, 00673 const Tag* tag_list, 00674 int num_tags ) 00675 { 00676 // convert range to vector 00677 std::vector< EntityHandle > list( output_sets.size() ); 00678 std::copy( output_sets.begin(), output_sets.end(), list.begin() ); 00679 00680 // parse some options 00681 FileOptions opts( options_string ); 00682 ErrorCode rval; 00683 00684 rval = opts.get_null_option( "CREATE" ); 00685 if( rval == MB_TYPE_OUT_OF_RANGE ) 00686 { 00687 MB_SET_GLB_ERR( MB_FAILURE, "Unexpected value for CREATE option" ); 00688 } 00689 bool overwrite = ( rval == MB_ENTITY_NOT_FOUND ); 00690 00691 // Get the file writer 00692 std::string ext = ReaderWriterSet::extension_from_filename( file_name ); 00693 std::vector< std::string > qa_records; 00694 const EntityHandle* list_ptr = list.empty() ? (EntityHandle*)0 : &list[0]; 00695 00696 rval = MB_TYPE_OUT_OF_RANGE; 00697 00698 // Try all possible writers 00699 for( ReaderWriterSet::iterator i = reader_writer_set()->begin(); i != reader_writer_set()->end(); ++i ) 00700 { 00701 00702 if( ( file_type && !i->name().compare( file_type ) ) || i->writes_extension( ext.c_str() ) ) 00703 { 00704 00705 WriterIface* writer = i->make_writer( this ); 00706 00707 // write the file 00708 rval = 00709 writer->write_file( file_name, overwrite, opts, list_ptr, list.size(), qa_records, tag_list, num_tags ); 00710 delete writer; 00711 if( MB_SUCCESS == rval ) break; 00712 printf( "Writer with name %s for file %s using extension %s (file type \"%s\") was " 00713 "unsuccessful\n", 00714 i->name().c_str(), file_name, ext.c_str(), file_type ); 00715 } 00716 } 00717 00718 if( file_type && rval == MB_TYPE_OUT_OF_RANGE ) 00719 { 00720 MB_SET_ERR( rval, "Unrecognized file type \"" << file_type << "\"" ); 00721 } 00722 // Should we use default writer (e.g. HDF5)? 00723 else if( MB_SUCCESS != rval ) 00724 { 00725 DefaultWriter writer( this ); 00726 printf( "Using default writer %s for file %s \n", DefaultWriterName, file_name ); 00727 rval = writer.write_file( file_name, overwrite, opts, list_ptr, list.size(), qa_records, tag_list, num_tags ); 00728 } 00729 00730 if( MB_SUCCESS == rval && !opts.all_seen() ) 00731 { 00732 std::string bad_opt; 00733 if( MB_SUCCESS == opts.get_unseen_option( bad_opt ) ) 00734 { 00735 MB_SET_ERR( MB_UNHANDLED_OPTION, "Unrecognized option: \"" << bad_opt << "\"" ); 00736 } 00737 else 00738 { 00739 MB_SET_ERR( MB_UNHANDLED_OPTION, "Unrecognized option" ); 00740 } 00741 } 00742 00743 return MB_SUCCESS; 00744 } 00745 00746 //! deletes all mesh entities from this datastore 00747 ErrorCode Core::delete_mesh() 00748 { 00749 00750 ErrorCode result = MB_SUCCESS; 00751 00752 // perform all deinitialization procedures to clean up 00753 if( aEntityFactory ) delete aEntityFactory; 00754 aEntityFactory = new AEntityFactory( this ); 00755 00756 for( std::list< TagInfo* >::iterator i = tagList.begin(); i != tagList.end(); ++i ) 00757 { 00758 result = ( *i )->release_all_data( sequenceManager, mError, false );MB_CHK_ERR( result ); 00759 } 00760 00761 sequenceManager->clear(); 00762 00763 return MB_SUCCESS; 00764 } 00765 00766 //! get overall geometric dimension 00767 ErrorCode Core::get_dimension( int& dim ) const 00768 { 00769 dim = geometricDimension; 00770 return MB_SUCCESS; 00771 } 00772 00773 //! set overall geometric dimension 00774 /** Returns error if setting to 3 dimensions, mesh has been created, and 00775 * there are only 2 dimensions on that mesh 00776 */ 00777 ErrorCode Core::set_dimension( const int dim ) 00778 { 00779 // check to see if current dimension is smaller 00780 if( geometricDimension < dim ) 00781 { 00782 // need to check the number of entities 00783 int num; 00784 /*ErrorCode result = */ get_number_entities_by_dimension( 0, geometricDimension, num ); 00785 00786 // test written to be more readable but possibly less efficient 00787 // if (MB_SUCCESS != result) return MB_FAILURE; 00788 // else if (0 != num && dim == 2 && ycoordTag == 0) return MB_FAILURE; 00789 // else if (0 != num && dim == 3 && (ycoordTag == 0 || zcoordTag == 0)) return MB_FAILURE; 00790 // TODO -- replace this with not using xcoordTag, etc... 00791 } 00792 00793 // if we got here, it's ok to set dimension 00794 geometricDimension = dim; 00795 return MB_SUCCESS; 00796 } 00797 00798 //! get blocked vertex coordinates for all vertices 00799 /** Blocked = all x, then all y, etc. 00800 */ 00801 ErrorCode Core::get_vertex_coordinates( std::vector< double >& coords ) const 00802 { 00803 // INEFFICIENT implementation for now, until we get blocked tag access 00804 Range vertices; 00805 ErrorCode result = get_entities_by_type( 0, MBVERTEX, vertices );MB_CHK_ERR( result ); 00806 00807 // the least we can do is resize the vector and only go through the 00808 // vertex list once 00809 int num_verts = vertices.size(); 00810 int vec_pos = 0; 00811 double xyz[3]; 00812 coords.resize( geometricDimension * num_verts ); 00813 for( Range::iterator it = vertices.begin(); it != vertices.end(); ++it ) 00814 { 00815 result = get_coords( &( *it ), 1, xyz );MB_CHK_ERR( result ); 00816 00817 coords[vec_pos] = xyz[0]; 00818 coords[num_verts + vec_pos] = xyz[1]; 00819 coords[2 * num_verts + vec_pos] = xyz[2]; 00820 00821 vec_pos++; 00822 } 00823 00824 return MB_SUCCESS; 00825 } 00826 00827 ErrorCode Core::coords_iterate( Range::const_iterator iter, 00828 Range::const_iterator end, 00829 double*& xcoords_ptr, 00830 double*& ycoords_ptr, 00831 double*& zcoords_ptr, 00832 int& count ) 00833 { 00834 EntitySequence* seq; 00835 ErrorCode rval = sequence_manager()->find( *iter, seq ); 00836 if( MB_SUCCESS != rval ) 00837 { 00838 xcoords_ptr = ycoords_ptr = zcoords_ptr = NULL; 00839 MB_SET_ERR( rval, "Couldn't find sequence for start handle" ); 00840 } 00841 VertexSequence* vseq = dynamic_cast< VertexSequence* >( seq ); 00842 if( !vseq ) 00843 { 00844 MB_SET_ERR( MB_ENTITY_NOT_FOUND, "Couldn't find sequence for start handle" ); 00845 } 00846 00847 unsigned int offset = *iter - vseq->data()->start_handle(); 00848 xcoords_ptr = reinterpret_cast< double* >( vseq->data()->get_sequence_data( 0 ) ) + offset; 00849 ycoords_ptr = reinterpret_cast< double* >( vseq->data()->get_sequence_data( 1 ) ) + offset; 00850 zcoords_ptr = reinterpret_cast< double* >( vseq->data()->get_sequence_data( 2 ) ) + offset; 00851 00852 EntityHandle real_end = std::min( seq->end_handle(), *( iter.end_of_block() ) ); 00853 if( *end ) real_end = std::min( real_end, *end ); 00854 count = real_end - *iter + 1; 00855 00856 return MB_SUCCESS; 00857 } 00858 00859 ErrorCode Core::get_coords( const Range& entities, double* coords ) const 00860 { 00861 const TypeSequenceManager& vert_data = sequence_manager()->entity_map( MBVERTEX ); 00862 TypeSequenceManager::const_iterator seq_iter; 00863 00864 Range::const_pair_iterator i = entities.const_pair_begin(); 00865 EntityHandle first = i->first; 00866 while( i != entities.const_pair_end() && TYPE_FROM_HANDLE( i->first ) == MBVERTEX ) 00867 { 00868 00869 seq_iter = vert_data.lower_bound( first ); 00870 if( seq_iter == vert_data.end() || first < ( *seq_iter )->start_handle() ) return MB_ENTITY_NOT_FOUND; 00871 const VertexSequence* vseq = reinterpret_cast< const VertexSequence* >( *seq_iter ); 00872 00873 EntityID offset = first - vseq->start_handle(); 00874 EntityID count; 00875 if( i->second <= vseq->end_handle() ) 00876 { 00877 count = i->second - first + 1; 00878 ++i; 00879 if( i != entities.const_pair_end() ) first = i->first; 00880 } 00881 else 00882 { 00883 count = vseq->end_handle() - first + 1; 00884 first = vseq->end_handle() + 1; 00885 } 00886 00887 double const *x, *y, *z; 00888 ErrorCode rval = vseq->get_coordinate_arrays( x, y, z );MB_CHK_ERR( rval ); 00889 x += offset; 00890 y += offset; 00891 z += offset; 00892 for( EntityID j = 0; j < count; ++j ) 00893 { 00894 coords[3 * j] = x[j]; 00895 coords[3 * j + 1] = y[j]; 00896 coords[3 * j + 2] = z[j]; 00897 } 00898 coords = &coords[3 * count]; 00899 } 00900 00901 // for non-vertices... 00902 ErrorCode rval = MB_SUCCESS; 00903 for( Range::const_iterator rit( &( *i ), i->first ); rit != entities.end(); ++rit ) 00904 { 00905 rval = get_coords( &( *rit ), 1, coords );MB_CHK_ERR( rval ); 00906 coords += 3; 00907 } 00908 00909 return rval; 00910 } 00911 00912 /**\author Jason Kraftcheck <[email protected]> - 2007-5-15 */ 00913 ErrorCode Core::get_coords( const Range& entities, double* x_coords, double* y_coords, double* z_coords ) const 00914 { 00915 const TypeSequenceManager& vert_data = sequence_manager()->entity_map( MBVERTEX ); 00916 TypeSequenceManager::const_iterator seq_iter; 00917 00918 Range::const_pair_iterator i = entities.const_pair_begin(); 00919 EntityHandle first = i->first; 00920 while( i != entities.const_pair_end() && TYPE_FROM_HANDLE( i->first ) == MBVERTEX ) 00921 { 00922 00923 seq_iter = vert_data.lower_bound( first ); 00924 if( seq_iter == vert_data.end() || first < ( *seq_iter )->start_handle() ) return MB_ENTITY_NOT_FOUND; 00925 const VertexSequence* vseq = reinterpret_cast< const VertexSequence* >( *seq_iter ); 00926 00927 EntityID offset = first - vseq->start_handle(); 00928 EntityID count; 00929 if( i->second <= vseq->end_handle() ) 00930 { 00931 count = i->second - first + 1; 00932 ++i; 00933 if( i != entities.const_pair_end() ) first = i->first; 00934 } 00935 else 00936 { 00937 count = vseq->end_handle() - first + 1; 00938 first = vseq->end_handle() + 1; 00939 } 00940 00941 double const *x, *y, *z; 00942 ErrorCode rval = vseq->get_coordinate_arrays( x, y, z );MB_CHK_ERR( rval ); 00943 if( x_coords ) 00944 { 00945 memcpy( x_coords, x + offset, count * sizeof( double ) ); 00946 x_coords += count; 00947 } 00948 if( y_coords ) 00949 { 00950 memcpy( y_coords, y + offset, count * sizeof( double ) ); 00951 y_coords += count; 00952 } 00953 if( z_coords ) 00954 { 00955 memcpy( z_coords, z + offset, count * sizeof( double ) ); 00956 z_coords += count; 00957 } 00958 } 00959 00960 // for non-vertices... 00961 ErrorCode rval = MB_SUCCESS; 00962 double xyz[3]; 00963 for( Range::const_iterator rit( &( *i ), i->first ); rit != entities.end(); ++rit ) 00964 { 00965 rval = get_coords( &( *rit ), 1, xyz );MB_CHK_ERR( rval ); 00966 *x_coords++ = xyz[0]; 00967 *y_coords++ = xyz[1]; 00968 *z_coords++ = xyz[2]; 00969 } 00970 00971 return rval; 00972 } 00973 00974 ErrorCode Core::get_coords( const EntityHandle* entities, const int num_entities, double* coords ) const 00975 { 00976 const EntitySequence* seq = NULL; 00977 const VertexSequence* vseq = NULL; 00978 const EntityHandle* const end = entities + num_entities; 00979 const EntityHandle* iter = entities; 00980 ErrorCode status = MB_SUCCESS; 00981 00982 while( iter != end ) 00983 { 00984 if( TYPE_FROM_HANDLE( *iter ) == MBVERTEX ) 00985 { 00986 if( !seq ) 00987 { 00988 seq = sequence_manager()->get_last_accessed_sequence( MBVERTEX ); 00989 vseq = static_cast< const VertexSequence* >( seq ); 00990 } 00991 if( !vseq ) 00992 return MB_ENTITY_NOT_FOUND; 00993 else if( vseq->start_handle() > *iter || vseq->end_handle() < *iter ) 00994 { 00995 if( MB_SUCCESS != sequence_manager()->find( *iter, seq ) ) return MB_ENTITY_NOT_FOUND; 00996 vseq = static_cast< const VertexSequence* >( seq ); 00997 } 00998 vseq->get_coordinates( *iter, coords ); 00999 } 01000 else 01001 { 01002 static std::vector< EntityHandle > dum_conn( CN::MAX_NODES_PER_ELEMENT ); 01003 static std::vector< double > dum_pos( 3 * CN::MAX_NODES_PER_ELEMENT ); 01004 static const EntityHandle* conn; 01005 static int num_conn; 01006 status = get_connectivity( *iter, conn, num_conn, false, &dum_conn );MB_CHK_ERR( status ); 01007 status = get_coords( conn, num_conn, &dum_pos[0] );MB_CHK_ERR( status ); 01008 coords[0] = coords[1] = coords[2] = 0.0; 01009 for( int i = 0; i < num_conn; i++ ) 01010 { 01011 coords[0] += dum_pos[3 * i]; 01012 coords[1] += dum_pos[3 * i + 1]; 01013 coords[2] += dum_pos[3 * i + 2]; 01014 } 01015 coords[0] /= num_conn; 01016 coords[1] /= num_conn; 01017 coords[2] /= num_conn; 01018 } 01019 coords += 3; 01020 ++iter; 01021 } 01022 01023 return status; 01024 } 01025 01026 ErrorCode Core::get_coords( const EntityHandle entity_handle, 01027 const double*& x, 01028 const double*& y, 01029 const double*& z ) const 01030 { 01031 ErrorCode status = MB_TYPE_OUT_OF_RANGE; 01032 01033 if( TYPE_FROM_HANDLE( entity_handle ) == MBVERTEX ) 01034 { 01035 const EntitySequence* seq = 0; 01036 status = sequence_manager()->find( entity_handle, seq ); 01037 01038 if( seq == 0 || status != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND; 01039 01040 status = static_cast< const VertexSequence* >( seq )->get_coordinates_ref( entity_handle, x, y, z ); 01041 } 01042 01043 return status; 01044 } 01045 01046 //! set the coordinate information for this handle if it is of type Vertex 01047 //! otherwise, return an error 01048 ErrorCode Core::set_coords( const EntityHandle* entity_handles, const int num_entities, const double* coords ) 01049 { 01050 01051 ErrorCode status = MB_SUCCESS; 01052 01053 int i, j = 0; 01054 01055 for( i = 0; i < num_entities; i++ ) 01056 { 01057 if( TYPE_FROM_HANDLE( entity_handles[i] ) == MBVERTEX ) 01058 { 01059 EntitySequence* seq = 0; 01060 status = sequence_manager()->find( entity_handles[i], seq ); 01061 01062 if( seq != 0 && status == MB_SUCCESS ) 01063 { 01064 status = static_cast< VertexSequence* >( seq )->set_coordinates( entity_handles[i], coords[j], 01065 coords[j + 1], coords[j + 2] ); 01066 j += 3; 01067 } 01068 } 01069 else if( status == MB_SUCCESS ) 01070 status = MB_TYPE_OUT_OF_RANGE; 01071 } 01072 01073 return status; 01074 } 01075 01076 //! set the coordinate information for this handle if it is of type Vertex 01077 //! otherwise, return an error 01078 ErrorCode Core::set_coords( Range entity_handles, const double* coords ) 01079 { 01080 01081 ErrorCode status = MB_SUCCESS; 01082 01083 int j = 0; 01084 01085 for( Range::iterator rit = entity_handles.begin(); rit != entity_handles.end(); ++rit ) 01086 { 01087 if( TYPE_FROM_HANDLE( *rit ) == MBVERTEX ) 01088 { 01089 EntitySequence* seq = 0; 01090 status = sequence_manager()->find( *rit, seq ); 01091 01092 if( seq != 0 && status == MB_SUCCESS ) 01093 { 01094 status = static_cast< VertexSequence* >( seq )->set_coordinates( *rit, coords[j], coords[j + 1], 01095 coords[j + 2] ); 01096 j += 3; 01097 } 01098 } 01099 else if( status == MB_SUCCESS ) 01100 status = MB_TYPE_OUT_OF_RANGE; 01101 } 01102 01103 return status; 01104 } 01105 01106 double Core::get_sequence_multiplier() const 01107 { 01108 return sequenceManager->get_sequence_multiplier(); 01109 } 01110 01111 void Core::set_sequence_multiplier( double factor ) 01112 { 01113 assert( factor >= 1.0 ); 01114 sequenceManager->set_sequence_multiplier( factor ); 01115 } 01116 01117 //! get global connectivity array for specified entity type 01118 /** Assumes just vertices, no higher order nodes 01119 */ 01120 ErrorCode Core::get_connectivity_by_type( const EntityType entity_type, std::vector< EntityHandle >& connect ) const 01121 { 01122 // inefficient implementation until we get blocked tag access 01123 01124 // get the range of entities of this type 01125 Range this_range; 01126 ErrorCode result = get_entities_by_type( 0, entity_type, this_range ); 01127 01128 int num_ents = this_range.size(); 01129 connect.reserve( num_ents * CN::VerticesPerEntity( entity_type ) ); 01130 01131 // now loop over these entities, getting connectivity for each 01132 for( Range::iterator this_it = this_range.begin(); this_it != this_range.end(); ++this_it ) 01133 { 01134 const EntityHandle* connect_vec = NULL; 01135 result = get_connectivity( *this_it, connect_vec, num_ents, true );MB_CHK_ERR( result ); 01136 connect.insert( connect.end(), &connect_vec[0], &connect_vec[num_ents] ); 01137 } 01138 01139 return MB_SUCCESS; 01140 } 01141 01142 //! get the connectivity for element /handles. For non-element handles, return an error 01143 ErrorCode Core::get_connectivity( const EntityHandle* entity_handles, 01144 const int num_handles, 01145 Range& connectivity, 01146 bool corners_only ) const 01147 { 01148 std::vector< EntityHandle > tmp_connect; 01149 ErrorCode result = get_connectivity( entity_handles, num_handles, tmp_connect, corners_only );MB_CHK_ERR( result ); 01150 01151 std::sort( tmp_connect.begin(), tmp_connect.end() ); 01152 std::copy( tmp_connect.rbegin(), tmp_connect.rend(), range_inserter( connectivity ) ); 01153 return result; 01154 } 01155 01156 //! get the connectivity for element /handles. For non-element handles, return an error 01157 ErrorCode Core::get_connectivity( const EntityHandle* entity_handles, 01158 const int num_handles, 01159 std::vector< EntityHandle >& connectivity, 01160 bool corners_only, 01161 std::vector< int >* offsets ) const 01162 { 01163 connectivity.clear(); // this seems wrong as compared to other API functions, 01164 // but changing it breaks lost of code, so I'm leaving 01165 // it in. - j.kraftcheck 2009-11-06 01166 01167 ErrorCode rval; 01168 std::vector< EntityHandle > tmp_storage; // used only for structured mesh 01169 const EntityHandle* conn; 01170 int len; 01171 if( offsets ) offsets->push_back( 0 ); 01172 for( int i = 0; i < num_handles; ++i ) 01173 { 01174 rval = get_connectivity( entity_handles[i], conn, len, corners_only, &tmp_storage );MB_CHK_ERR( rval ); 01175 connectivity.insert( connectivity.end(), conn, conn + len ); 01176 if( offsets ) offsets->push_back( connectivity.size() ); 01177 } 01178 return MB_SUCCESS; 01179 } 01180 01181 //! get the connectivity for element handles. For non-element handles, return an error 01182 ErrorCode Core::get_connectivity( const EntityHandle entity_handle, 01183 const EntityHandle*& connectivity, 01184 int& number_nodes, 01185 bool corners_only, 01186 std::vector< EntityHandle >* storage ) const 01187 { 01188 ErrorCode status; 01189 01190 // Make sure the entity should have a connectivity. 01191 EntityType entity_type = TYPE_FROM_HANDLE( entity_handle ); 01192 01193 // WARNING: This is very dependent on the ordering of the EntityType enum 01194 if( entity_type < MBVERTEX || entity_type >= MBENTITYSET ) 01195 return MB_TYPE_OUT_OF_RANGE; 01196 01197 else if( entity_type == MBVERTEX ) 01198 { 01199 return MB_FAILURE; 01200 } 01201 01202 const EntitySequence* seq = 0; 01203 01204 // We know that connectivity is stored in an EntitySequence so jump straight 01205 // to the entity sequence 01206 status = sequence_manager()->find( entity_handle, seq ); 01207 if( seq == 0 || status != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND; 01208 01209 return static_cast< const ElementSequence* >( seq )->get_connectivity( entity_handle, connectivity, number_nodes, 01210 corners_only, storage ); 01211 } 01212 01213 //! set the connectivity for element handles. For non-element handles, return an error 01214 ErrorCode Core::set_connectivity( const EntityHandle entity_handle, EntityHandle* connect, const int num_connect ) 01215 { 01216 ErrorCode status = MB_FAILURE; 01217 01218 // Make sure the entity should have a connectivity. 01219 // WARNING: This is very dependent on the ordering of the EntityType enum 01220 EntityType entity_type = TYPE_FROM_HANDLE( entity_handle ); 01221 01222 EntitySequence* seq = 0; 01223 01224 if( entity_type < MBVERTEX || entity_type > MBENTITYSET ) return MB_TYPE_OUT_OF_RANGE; 01225 01226 status = sequence_manager()->find( entity_handle, seq ); 01227 if( seq == 0 || status != MB_SUCCESS ) return ( status != MB_SUCCESS ? status : MB_ENTITY_NOT_FOUND ); 01228 01229 const EntityHandle* old_conn; 01230 int len; 01231 status = static_cast< ElementSequence* >( seq )->get_connectivity( entity_handle, old_conn, len );MB_CHK_ERR( status ); 01232 01233 aEntityFactory->notify_change_connectivity( entity_handle, old_conn, connect, num_connect ); 01234 01235 status = static_cast< ElementSequence* >( seq )->set_connectivity( entity_handle, connect, num_connect ); 01236 if( status != MB_SUCCESS ) 01237 aEntityFactory->notify_change_connectivity( entity_handle, connect, old_conn, num_connect ); 01238 01239 return status; 01240 } 01241 01242 template < typename ITER > 01243 static inline ErrorCode get_adjacencies_union( Core* gMB, 01244 ITER begin, 01245 ITER end, 01246 int to_dimension, 01247 bool create_if_missing, 01248 Range& adj_entities ) 01249 { 01250 const size_t DEFAULT_MAX_BLOCKS_SIZE = 4000; 01251 const size_t MAX_OUTER_ITERATIONS = 100; 01252 01253 std::vector< EntityHandle > temp_vec, storage; 01254 std::vector< EntityHandle >::const_iterator ti; 01255 ErrorCode result = MB_SUCCESS, tmp_result; 01256 ITER i = begin; 01257 Range::iterator ins; 01258 const EntityHandle* conn; 01259 int conn_len; 01260 01261 // Just copy any vertices from the input range into the output 01262 size_t remaining = end - begin; 01263 assert( begin + remaining == end ); 01264 01265 // How many entities to work with at once? 2000 or so shouldn't require 01266 // too much memory, but don't iterate in outer loop more than a 01267 // 1000 times (make it bigger if many input entiites.) 01268 const size_t block_size = std::max( DEFAULT_MAX_BLOCKS_SIZE, remaining / MAX_OUTER_ITERATIONS ); 01269 while( remaining > 0 ) 01270 { 01271 const size_t count = remaining > block_size ? block_size : remaining; 01272 remaining -= count; 01273 temp_vec.clear(); 01274 for( size_t j = 0; j < count; ++i, ++j ) 01275 { 01276 if( CN::Dimension( TYPE_FROM_HANDLE( *i ) ) == to_dimension ) 01277 { 01278 temp_vec.push_back( *i ); 01279 } 01280 else if( to_dimension == 0 && TYPE_FROM_HANDLE( *i ) != MBPOLYHEDRON ) 01281 { 01282 tmp_result = gMB->get_connectivity( *i, conn, conn_len, false, &storage ); 01283 if( MB_SUCCESS != tmp_result ) 01284 { 01285 result = tmp_result; 01286 continue; 01287 } 01288 temp_vec.insert( temp_vec.end(), conn, conn + conn_len ); 01289 } 01290 else 01291 { 01292 tmp_result = gMB->a_entity_factory()->get_adjacencies( *i, to_dimension, create_if_missing, temp_vec ); 01293 if( MB_SUCCESS != tmp_result ) 01294 { 01295 result = tmp_result; 01296 continue; 01297 } 01298 } 01299 } 01300 01301 std::sort( temp_vec.begin(), temp_vec.end() ); 01302 ins = adj_entities.begin(); 01303 ti = temp_vec.begin(); 01304 while( ti != temp_vec.end() ) 01305 { 01306 EntityHandle first = *ti; 01307 EntityHandle second = *ti; 01308 for( ++ti; ti != temp_vec.end() && ( *ti - second <= 1 ); ++ti ) 01309 second = *ti; 01310 ins = adj_entities.insert( ins, first, second ); 01311 } 01312 } 01313 return result; 01314 } 01315 01316 template < typename ITER > 01317 static inline ErrorCode get_adjacencies_intersection( Core* mb, 01318 ITER begin, 01319 ITER end, 01320 const int to_dimension, 01321 const bool create_if_missing, 01322 std::vector< EntityHandle >& adj_entities ) 01323 { 01324 const size_t SORT_THRESHOLD = 200; 01325 std::vector< EntityHandle > temp_vec; 01326 std::vector< EntityHandle >::iterator adj_it, w_it; 01327 ErrorCode result = MB_SUCCESS; 01328 01329 if( begin == end ) 01330 { 01331 adj_entities.clear(); // intersection 01332 return MB_SUCCESS; 01333 } 01334 01335 // First iteration is a special case if input list is empty. 01336 // Rather than returning nothing (intersecting with empty 01337 // input list), we begin with the adjacencies for the first entity. 01338 if( adj_entities.empty() ) 01339 { 01340 EntityType entity_type = TYPE_FROM_HANDLE( *begin ); 01341 if( to_dimension == CN::Dimension( entity_type ) ) 01342 adj_entities.push_back( *begin ); 01343 else if( to_dimension == 0 && entity_type != MBPOLYHEDRON ) 01344 { 01345 result = mb->get_connectivity( &( *begin ), 1, adj_entities );MB_CHK_ERR( result ); 01346 } 01347 else 01348 { 01349 result = mb->a_entity_factory()->get_adjacencies( *begin, to_dimension, create_if_missing, adj_entities );MB_CHK_ERR( result ); 01350 } 01351 ++begin; 01352 } 01353 01354 for( ITER from_it = begin; from_it != end; ++from_it ) 01355 { 01356 // running results kept in adj_entities; clear temp_vec, which is working space 01357 temp_vec.clear(); 01358 01359 // get the next set of adjacencies 01360 EntityType entity_type = TYPE_FROM_HANDLE( *from_it ); 01361 if( to_dimension == CN::Dimension( entity_type ) ) 01362 temp_vec.push_back( *from_it ); 01363 else if( to_dimension == 0 && entity_type != MBPOLYHEDRON ) 01364 { 01365 result = mb->get_connectivity( &( *from_it ), 1, temp_vec );MB_CHK_ERR( result ); 01366 } 01367 else 01368 { 01369 result = mb->a_entity_factory()->get_adjacencies( *from_it, to_dimension, create_if_missing, temp_vec );MB_CHK_ERR( result ); 01370 } 01371 01372 // otherwise intersect with the current set of results 01373 w_it = adj_it = adj_entities.begin(); 01374 if( temp_vec.size() * adj_entities.size() < SORT_THRESHOLD ) 01375 { 01376 for( ; adj_it != adj_entities.end(); ++adj_it ) 01377 if( std::find( temp_vec.begin(), temp_vec.end(), *adj_it ) != temp_vec.end() ) 01378 { 01379 *w_it = *adj_it; 01380 ++w_it; 01381 } 01382 } 01383 else 01384 { 01385 std::sort( temp_vec.begin(), temp_vec.end() ); 01386 for( ; adj_it != adj_entities.end(); ++adj_it ) 01387 if( std::binary_search( temp_vec.begin(), temp_vec.end(), *adj_it ) ) 01388 { 01389 *w_it = *adj_it; 01390 ++w_it; 01391 } 01392 } 01393 adj_entities.erase( w_it, adj_entities.end() ); 01394 01395 // we're intersecting, so if there are no more results, we're done 01396 if( adj_entities.empty() ) break; 01397 } 01398 01399 return MB_SUCCESS; 01400 } 01401 01402 template < typename ITER > 01403 static inline ErrorCode get_adjacencies_intersection( Core* mb, 01404 ITER begin, 01405 ITER end, 01406 const int to_dimension, 01407 const bool create_if_missing, 01408 Range& adj_entities ) 01409 { 01410 std::vector< EntityHandle > results; 01411 ErrorCode rval = moab::get_adjacencies_intersection( mb, begin, end, to_dimension, create_if_missing, results );MB_CHK_ERR( rval ); 01412 01413 if( adj_entities.empty() ) 01414 { 01415 std::copy( results.begin(), results.end(), range_inserter( adj_entities ) ); 01416 return MB_SUCCESS; 01417 } 01418 01419 Range::iterator it = adj_entities.begin(); 01420 while( it != adj_entities.end() ) 01421 { 01422 if( std::find( results.begin(), results.end(), *it ) == results.end() ) 01423 it = adj_entities.erase( it ); 01424 else 01425 ++it; 01426 } 01427 return MB_SUCCESS; 01428 } 01429 01430 /////////////////////////////////////////////////////////////////// 01431 ////////////////////////////////////////// 01432 #ifdef MOAB_HAVE_AHF 01433 01434 template < typename ITER > 01435 static inline ErrorCode get_adjacencies_intersection_ahf( Core* mb, 01436 ITER begin, 01437 ITER end, 01438 const int to_dimension, 01439 std::vector< EntityHandle >& adj_entities ) 01440 { 01441 const size_t SORT_THRESHOLD = 200; 01442 std::vector< EntityHandle > temp_vec; 01443 std::vector< EntityHandle >::iterator adj_it, w_it; 01444 ErrorCode result = MB_SUCCESS; 01445 01446 if( begin == end ) 01447 { 01448 adj_entities.clear(); // intersection 01449 return MB_SUCCESS; 01450 } 01451 01452 // First iteration is a special case if input list is empty. 01453 // Rather than returning nothing (intersecting with empty 01454 // input list), we begin with the adjacencies for the first entity. 01455 if( adj_entities.empty() ) 01456 { 01457 EntityType entity_type = TYPE_FROM_HANDLE( *begin ); 01458 01459 if( to_dimension == 0 && entity_type != MBPOLYHEDRON ) 01460 result = mb->get_connectivity( &( *begin ), 1, adj_entities ); 01461 else 01462 result = mb->a_half_facet_rep()->get_adjacencies( *begin, to_dimension, adj_entities ); 01463 if( MB_SUCCESS != result ) return result; 01464 ++begin; 01465 } 01466 01467 for( ITER from_it = begin; from_it != end; ++from_it ) 01468 { 01469 // running results kept in adj_entities; clear temp_vec, which is working space 01470 temp_vec.clear(); 01471 01472 // get the next set of adjacencies 01473 EntityType entity_type = TYPE_FROM_HANDLE( *from_it ); 01474 if( to_dimension == 0 && entity_type != MBPOLYHEDRON ) 01475 result = mb->get_connectivity( &( *from_it ), 1, temp_vec ); 01476 else 01477 result = mb->a_half_facet_rep()->get_adjacencies( *from_it, to_dimension, temp_vec ); 01478 if( MB_SUCCESS != result ) return result; 01479 01480 // otherwise intersect with the current set of results 01481 w_it = adj_it = adj_entities.begin(); 01482 if( temp_vec.size() * adj_entities.size() < SORT_THRESHOLD ) 01483 { 01484 for( ; adj_it != adj_entities.end(); ++adj_it ) 01485 if( std::find( temp_vec.begin(), temp_vec.end(), *adj_it ) != temp_vec.end() ) 01486 { 01487 *w_it = *adj_it; 01488 ++w_it; 01489 } 01490 } 01491 else 01492 { 01493 std::sort( temp_vec.begin(), temp_vec.end() ); 01494 for( ; adj_it != adj_entities.end(); ++adj_it ) 01495 if( std::binary_search( temp_vec.begin(), temp_vec.end(), *adj_it ) ) 01496 { 01497 *w_it = *adj_it; 01498 ++w_it; 01499 } 01500 } 01501 adj_entities.erase( w_it, adj_entities.end() ); 01502 01503 // we're intersecting, so if there are no more results, we're done 01504 if( adj_entities.empty() ) break; 01505 } 01506 01507 return MB_SUCCESS; 01508 } 01509 #endif 01510 01511 /////////////////////////////////////////// 01512 01513 ErrorCode Core::get_adjacencies( const EntityHandle* from_entities, 01514 const int num_entities, 01515 const int to_dimension, 01516 const bool create_if_missing, 01517 std::vector< EntityHandle >& adj_entities, 01518 const int operation_type ) 01519 { 01520 01521 #ifdef MOAB_HAVE_AHF 01522 bool can_handle = true; 01523 01524 if( to_dimension == 4 ) 01525 can_handle = false; // NOT SUPPORTED: meshsets 01526 else if( create_if_missing ) 01527 can_handle = false; // NOT SUPPORTED: create_if_missing 01528 01529 bool mixed = ahfRep->check_mixed_entity_type(); // NOT SUPPORTED: mixed entity types or 01530 // polygonal/hedrals types 01531 if( mixed ) can_handle = false; 01532 01533 if( mesh_modified ) // NOT SUPPORTED: modified mesh 01534 can_handle = false; 01535 01536 if( can_handle ) 01537 { 01538 ErrorCode result; 01539 if( operation_type == Interface::INTERSECT ) 01540 return get_adjacencies_intersection_ahf( this, from_entities, from_entities + num_entities, to_dimension, 01541 adj_entities ); 01542 else if( operation_type != Interface::UNION ) 01543 return MB_FAILURE; 01544 01545 // do union 01546 01547 std::vector< EntityHandle > tmp_storage; 01548 const EntityHandle* conn; 01549 int len; 01550 for( int i = 0; i < num_entities; ++i ) 01551 { 01552 if( to_dimension == 0 && TYPE_FROM_HANDLE( from_entities[0] ) != MBPOLYHEDRON ) 01553 { 01554 result = get_connectivity( from_entities[i], conn, len, false, &tmp_storage ); 01555 adj_entities.insert( adj_entities.end(), conn, conn + len ); 01556 if( MB_SUCCESS != result ) return result; 01557 } 01558 else 01559 { 01560 result = ahfRep->get_adjacencies( from_entities[i], to_dimension, adj_entities ); 01561 if( MB_SUCCESS != result ) return result; 01562 } 01563 } 01564 std::sort( adj_entities.begin(), adj_entities.end() ); 01565 adj_entities.erase( std::unique( adj_entities.begin(), adj_entities.end() ), adj_entities.end() ); 01566 } 01567 else 01568 { 01569 01570 #endif 01571 01572 if( operation_type == Interface::INTERSECT ) 01573 return get_adjacencies_intersection( this, from_entities, from_entities + num_entities, to_dimension, 01574 create_if_missing, adj_entities ); 01575 else if( operation_type != Interface::UNION ) 01576 return MB_FAILURE; 01577 01578 // do union 01579 ErrorCode result; 01580 std::vector< EntityHandle > tmp_storage; 01581 const EntityHandle* conn; 01582 int len; 01583 for( int i = 0; i < num_entities; ++i ) 01584 { 01585 if( to_dimension == 0 && TYPE_FROM_HANDLE( from_entities[0] ) != MBPOLYHEDRON ) 01586 { 01587 result = get_connectivity( from_entities[i], conn, len, false, &tmp_storage );MB_CHK_ERR( result ); 01588 adj_entities.insert( adj_entities.end(), conn, conn + len ); 01589 } 01590 else 01591 { 01592 result = 01593 aEntityFactory->get_adjacencies( from_entities[i], to_dimension, create_if_missing, adj_entities );MB_CHK_ERR( result ); 01594 } 01595 } 01596 std::sort( adj_entities.begin(), adj_entities.end() ); 01597 adj_entities.erase( std::unique( adj_entities.begin(), adj_entities.end() ), adj_entities.end() ); 01598 01599 // return MB_SUCCESS; 01600 01601 #ifdef MOAB_HAVE_AHF 01602 } 01603 #endif 01604 01605 return MB_SUCCESS; 01606 } 01607 01608 ErrorCode Core::get_adjacencies( const EntityHandle* from_entities, 01609 const int num_entities, 01610 const int to_dimension, 01611 const bool create_if_missing, 01612 Range& adj_entities, 01613 const int operation_type ) 01614 { 01615 if( operation_type == Interface::INTERSECT ) 01616 return get_adjacencies_intersection( this, from_entities, from_entities + num_entities, to_dimension, 01617 create_if_missing, adj_entities ); 01618 else if( operation_type == Interface::UNION ) 01619 return get_adjacencies_union( this, from_entities, from_entities + num_entities, to_dimension, 01620 create_if_missing, adj_entities ); 01621 else 01622 return MB_FAILURE; 01623 } 01624 01625 ErrorCode Core::get_connectivity( const Range& from_entities, Range& adj_entities, bool corners_only ) const 01626 { 01627 const size_t DEFAULT_MAX_BLOCKS_SIZE = 4000; 01628 const size_t MAX_OUTER_ITERATIONS = 100; 01629 01630 std::vector< EntityHandle > temp_vec, storage; 01631 std::vector< EntityHandle >::const_iterator ti; 01632 ErrorCode result = MB_SUCCESS, tmp_result; 01633 Range::const_iterator i = from_entities.begin(); 01634 Range::iterator ins; 01635 const EntityHandle* conn; 01636 int conn_len; 01637 01638 // Just copy any vertices from the input range into the output 01639 size_t remaining = from_entities.size(); 01640 for( ; i != from_entities.end() && TYPE_FROM_HANDLE( *i ) == MBVERTEX; ++i ) 01641 --remaining; 01642 adj_entities.merge( from_entities.begin(), i ); 01643 01644 // How many entities to work with at once? 2000 or so shouldn't require 01645 // too much memory, but don't iterate in outer loop more than a 01646 // 1000 times (make it bigger if many input entiites.) 01647 const size_t block_size = std::max( DEFAULT_MAX_BLOCKS_SIZE, remaining / MAX_OUTER_ITERATIONS ); 01648 while( remaining > 0 ) 01649 { 01650 const size_t count = remaining > block_size ? block_size : remaining; 01651 remaining -= count; 01652 temp_vec.clear(); 01653 for( size_t j = 0; j < count; ++i, ++j ) 01654 { 01655 tmp_result = get_connectivity( *i, conn, conn_len, corners_only, &storage ); 01656 if( MB_SUCCESS != tmp_result ) 01657 { 01658 result = tmp_result; 01659 continue; 01660 } 01661 01662 const size_t oldsize = temp_vec.size(); 01663 temp_vec.resize( oldsize + conn_len ); 01664 memcpy( &temp_vec[oldsize], conn, sizeof( EntityHandle ) * conn_len ); 01665 } 01666 01667 std::sort( temp_vec.begin(), temp_vec.end() ); 01668 ins = adj_entities.begin(); 01669 ti = temp_vec.begin(); 01670 while( ti != temp_vec.end() ) 01671 { 01672 EntityHandle first = *ti; 01673 EntityHandle second = *ti; 01674 for( ++ti; ti != temp_vec.end() && ( *ti - second <= 1 ); ++ti ) 01675 second = *ti; 01676 ins = adj_entities.insert( ins, first, second ); 01677 } 01678 } 01679 return result; 01680 } 01681 01682 ErrorCode Core::connect_iterate( Range::const_iterator iter, 01683 Range::const_iterator end, 01684 EntityHandle*& connect, 01685 int& verts_per_entity, 01686 int& count ) 01687 { 01688 // Make sure the entity should have a connectivity. 01689 EntityType entity_type = TYPE_FROM_HANDLE( *iter ); 01690 01691 // WARNING: This is very dependent on the ordering of the EntityType enum 01692 if( entity_type <= MBVERTEX || entity_type >= MBENTITYSET ) return MB_TYPE_OUT_OF_RANGE; 01693 01694 EntitySequence* seq = NULL; 01695 01696 // We know that connectivity is stored in an EntitySequence so jump straight 01697 // to the entity sequence 01698 ErrorCode rval = sequence_manager()->find( *iter, seq ); 01699 if( !seq || rval != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND; 01700 01701 ElementSequence* eseq = dynamic_cast< ElementSequence* >( seq ); 01702 assert( eseq != NULL ); 01703 01704 connect = eseq->get_connectivity_array(); 01705 if( !connect ) 01706 { 01707 MB_SET_ERR( MB_FAILURE, "Couldn't find connectivity array for start handle" ); 01708 } 01709 01710 connect += eseq->nodes_per_element() * ( *iter - eseq->start_handle() ); 01711 01712 EntityHandle real_end = std::min( eseq->end_handle(), *( iter.end_of_block() ) ); 01713 if( *end ) real_end = std::min( real_end, *end ); 01714 count = real_end - *iter + 1; 01715 01716 verts_per_entity = eseq->nodes_per_element(); 01717 01718 return MB_SUCCESS; 01719 } 01720 01721 ErrorCode Core::get_vertices( const Range& from_entities, Range& vertices ) 01722 { 01723 Range range; 01724 ErrorCode rval = get_connectivity( from_entities, range );MB_CHK_ERR( rval ); 01725 01726 // If input contained polyhedra, connectivity will contain faces. 01727 // Get vertices from faces. 01728 if( !range.all_of_dimension( 0 ) ) 01729 { 01730 Range::iterator it = range.upper_bound( MBVERTEX ); 01731 Range polygons; 01732 polygons.merge( it, range.end() ); 01733 range.erase( it, range.end() ); 01734 rval = get_connectivity( polygons, range );MB_CHK_ERR( rval ); 01735 } 01736 01737 if( vertices.empty() ) 01738 vertices.swap( range ); 01739 else 01740 vertices.merge( range ); 01741 return MB_SUCCESS; 01742 } 01743 01744 ErrorCode Core::get_adjacencies( const Range& from_entities, 01745 const int to_dimension, 01746 const bool create_if_missing, 01747 Range& adj_entities, 01748 const int operation_type ) 01749 { 01750 if( operation_type == Interface::INTERSECT ) 01751 return get_adjacencies_intersection( this, from_entities.begin(), from_entities.end(), to_dimension, 01752 create_if_missing, adj_entities ); 01753 else if( operation_type != Interface::UNION ) 01754 return MB_FAILURE; 01755 else if( to_dimension == 0 ) 01756 return get_vertices( from_entities, adj_entities ); 01757 else 01758 return get_adjacencies_union( this, from_entities.begin(), from_entities.end(), to_dimension, create_if_missing, 01759 adj_entities ); 01760 } 01761 01762 ErrorCode Core::add_adjacencies( const EntityHandle entity_handle, 01763 const EntityHandle* adjacencies, 01764 const int num_handles, 01765 bool both_ways ) 01766 { 01767 ErrorCode result = MB_SUCCESS; 01768 01769 for( const EntityHandle* it = adjacencies; it != adjacencies + num_handles; it++ ) 01770 { 01771 result = aEntityFactory->add_adjacency( entity_handle, *it, both_ways );MB_CHK_ERR( result ); 01772 } 01773 01774 return MB_SUCCESS; 01775 } 01776 01777 ErrorCode Core::add_adjacencies( const EntityHandle entity_handle, Range& adjacencies, bool both_ways ) 01778 { 01779 ErrorCode result = MB_SUCCESS; 01780 01781 for( Range::iterator rit = adjacencies.begin(); rit != adjacencies.end(); ++rit ) 01782 { 01783 result = aEntityFactory->add_adjacency( entity_handle, *rit, both_ways );MB_CHK_ERR( result ); 01784 } 01785 01786 return MB_SUCCESS; 01787 } 01788 01789 ErrorCode Core::remove_adjacencies( const EntityHandle entity_handle, 01790 const EntityHandle* adjacencies, 01791 const int num_handles ) 01792 { 01793 ErrorCode result = MB_SUCCESS; 01794 01795 for( const EntityHandle* it = adjacencies; it != adjacencies + num_handles; it++ ) 01796 { 01797 result = aEntityFactory->remove_adjacency( entity_handle, *it );MB_CHK_ERR( result ); 01798 result = aEntityFactory->remove_adjacency( *it, entity_handle );MB_CHK_ERR( result ); 01799 } 01800 01801 return MB_SUCCESS; 01802 } 01803 01804 ErrorCode Core::adjacencies_iterate( Range::const_iterator iter, 01805 Range::const_iterator end, 01806 const std::vector< EntityHandle >**& adjs_ptr, 01807 int& count ) 01808 { 01809 // Make sure the entity should have a connectivity. 01810 EntityType entity_type = TYPE_FROM_HANDLE( *iter ); 01811 01812 // WARNING: This is very dependent on the ordering of the EntityType enum 01813 if( entity_type < MBVERTEX || entity_type > MBENTITYSET ) return MB_TYPE_OUT_OF_RANGE; 01814 01815 EntitySequence* seq = NULL; 01816 01817 // We know that connectivity is stored in an EntitySequence so jump straight 01818 // to the entity sequence 01819 ErrorCode rval = sequence_manager()->find( *iter, seq ); 01820 if( !seq || rval != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND; 01821 01822 adjs_ptr = const_cast< const std::vector< EntityHandle >** >( seq->data()->get_adjacency_data() ); 01823 if( !adjs_ptr ) return rval; 01824 01825 adjs_ptr += *iter - seq->data()->start_handle(); 01826 01827 EntityHandle real_end = *( iter.end_of_block() ); 01828 if( *end ) real_end = std::min( real_end, *end ); 01829 count = real_end - *iter + 1; 01830 01831 return MB_SUCCESS; 01832 } 01833 01834 ErrorCode Core::get_entities_by_dimension( const EntityHandle meshset, 01835 const int dimension, 01836 Range& entities, 01837 const bool recursive ) const 01838 { 01839 ErrorCode result = MB_SUCCESS; 01840 if( meshset ) 01841 { 01842 const EntitySequence* seq; 01843 result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result ); 01844 const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq ); 01845 result = mseq->get_dimension( sequence_manager(), meshset, dimension, entities, recursive );MB_CHK_ERR( result ); 01846 } 01847 else if( dimension > 3 ) 01848 { 01849 sequence_manager()->get_entities( MBENTITYSET, entities ); 01850 } 01851 else 01852 { 01853 for( EntityType this_type = CN::TypeDimensionMap[dimension].first; 01854 this_type <= CN::TypeDimensionMap[dimension].second; this_type++ ) 01855 { 01856 sequence_manager()->get_entities( this_type, entities ); 01857 } 01858 } 01859 01860 return MB_SUCCESS; 01861 } 01862 01863 ErrorCode Core::get_entities_by_dimension( const EntityHandle meshset, 01864 const int dimension, 01865 std::vector< EntityHandle >& entities, 01866 const bool recursive ) const 01867 { 01868 ErrorCode result = MB_SUCCESS; 01869 if( meshset ) 01870 { 01871 const EntitySequence* seq; 01872 result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result ); 01873 const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq ); 01874 result = mseq->get_dimension( sequence_manager(), meshset, dimension, entities, recursive );MB_CHK_ERR( result ); 01875 } 01876 else if( dimension > 3 ) 01877 { 01878 sequence_manager()->get_entities( MBENTITYSET, entities ); 01879 } 01880 else 01881 { 01882 for( EntityType this_type = CN::TypeDimensionMap[dimension].first; 01883 this_type <= CN::TypeDimensionMap[dimension].second; this_type++ ) 01884 { 01885 sequence_manager()->get_entities( this_type, entities ); 01886 } 01887 } 01888 01889 return MB_SUCCESS; 01890 } 01891 01892 ErrorCode Core::get_entities_by_type( const EntityHandle meshset, 01893 const EntityType entity_type, 01894 Range& entities, 01895 const bool recursive ) const 01896 { 01897 ErrorCode result = MB_SUCCESS; 01898 if( meshset ) 01899 { 01900 const EntitySequence* seq; 01901 result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result ); 01902 const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq ); 01903 result = mseq->get_type( sequence_manager(), meshset, entity_type, entities, recursive );MB_CHK_ERR( result ); 01904 } 01905 else 01906 { 01907 sequence_manager()->get_entities( entity_type, entities ); 01908 } 01909 01910 return MB_SUCCESS; 01911 } 01912 01913 ErrorCode Core::get_entities_by_type( const EntityHandle meshset, 01914 const EntityType entity_type, 01915 std::vector< EntityHandle >& entities, 01916 const bool recursive ) const 01917 { 01918 ErrorCode result = MB_SUCCESS; 01919 if( meshset ) 01920 { 01921 const EntitySequence* seq; 01922 result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result ); 01923 const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq ); 01924 result = mseq->get_type( sequence_manager(), meshset, entity_type, entities, recursive );MB_CHK_ERR( result ); 01925 } 01926 else 01927 { 01928 sequence_manager()->get_entities( entity_type, entities ); 01929 } 01930 01931 return MB_SUCCESS; 01932 } 01933 01934 ErrorCode Core::get_entities_by_type_and_tag( const EntityHandle meshset, 01935 const EntityType entity_type, 01936 const Tag* tags, 01937 const void* const* values, 01938 const int num_tags, 01939 Range& entities, 01940 const int condition, 01941 const bool recursive ) const 01942 { 01943 ErrorCode result; 01944 Range range; 01945 01946 result = get_entities_by_type( meshset, entity_type, range, recursive );MB_CHK_ERR( result ); 01947 if( !entities.empty() && Interface::INTERSECT == condition ) range = intersect( entities, range ); 01948 01949 // For each tag: 01950 // if operation is INTERSECT remove from 'range' any non-tagged entities 01951 // if operation is UNION add to 'entities' any tagged entities 01952 for( int it = 0; it < num_tags && !range.empty(); it++ ) 01953 { 01954 if( !valid_tag_handle( tags[it] ) ) return MB_TAG_NOT_FOUND; 01955 01956 // Of the entities in 'range', put in 'tmp_range' the subset 01957 // that are tagged as requested for this tag. 01958 Range tmp_range; 01959 01960 // get the entities with this tag/value combo 01961 if( NULL == values || NULL == values[it] ) 01962 { 01963 result = tags[it]->get_tagged_entities( sequenceManager, tmp_range, entity_type, &range );MB_CHK_ERR( result ); 01964 } 01965 else 01966 { 01967 result = tags[it]->find_entities_with_value( sequenceManager, mError, tmp_range, values[it], 0, entity_type, 01968 &range );MB_CHK_ERR( result ); 01969 // if there is a default value, then we should return all entities 01970 // that are untagged 01971 if( tags[it]->equals_default_value( values[it] ) ) 01972 { 01973 Range all_tagged, untagged; 01974 result = tags[it]->get_tagged_entities( sequenceManager, all_tagged, entity_type, &range );MB_CHK_ERR( result ); 01975 // add to 'tmp_range' any untagged entities in 'range' 01976 tmp_range.merge( subtract( range, all_tagged ) ); 01977 } 01978 } 01979 01980 // The above calls should have already done the intersect for us. 01981 if( Interface::INTERSECT == condition ) 01982 range.swap( tmp_range ); 01983 else 01984 entities.merge( tmp_range ); 01985 } 01986 01987 if( Interface::INTERSECT == condition ) entities.swap( range ); 01988 01989 return MB_SUCCESS; 01990 } 01991 01992 ErrorCode Core::get_entities_by_handle( const EntityHandle meshset, Range& entities, const bool recursive ) const 01993 { 01994 ErrorCode result = MB_SUCCESS; 01995 if( meshset ) 01996 { 01997 const EntitySequence* seq; 01998 result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result ); 01999 const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq ); 02000 result = mseq->get_entities( sequence_manager(), meshset, entities, recursive );MB_CHK_ERR( result ); 02001 } 02002 else 02003 { 02004 // iterate backwards so range insertion is quicker 02005 for( EntityType entity_type = MBENTITYSET; entity_type >= MBVERTEX; --entity_type ) 02006 sequence_manager()->get_entities( entity_type, entities ); 02007 } 02008 02009 return MB_SUCCESS; 02010 } 02011 02012 ErrorCode Core::get_entities_by_handle( const EntityHandle meshset, 02013 std::vector< EntityHandle >& entities, 02014 const bool recursive ) const 02015 { 02016 ErrorCode result; 02017 if( recursive || !meshset ) 02018 { 02019 Range tmp_range; 02020 result = get_entities_by_handle( meshset, tmp_range, recursive ); 02021 size_t offset = entities.size(); 02022 entities.resize( offset + tmp_range.size() ); 02023 std::copy( tmp_range.begin(), tmp_range.end(), entities.begin() + offset ); 02024 } 02025 else 02026 { 02027 const EntitySequence* seq; 02028 result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result ); 02029 const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq ); 02030 result = mseq->get_entities( meshset, entities );MB_CHK_ERR( result ); 02031 } 02032 return MB_SUCCESS; 02033 } 02034 02035 //! get # entities of a given dimension 02036 ErrorCode Core::get_number_entities_by_dimension( const EntityHandle meshset, 02037 const int dim, 02038 int& number, 02039 const bool recursive ) const 02040 { 02041 ErrorCode result = MB_SUCCESS; 02042 02043 if( !meshset ) 02044 { 02045 number = 0; 02046 for( EntityType this_type = CN::TypeDimensionMap[dim].first; this_type <= CN::TypeDimensionMap[dim].second; 02047 this_type++ ) 02048 { 02049 number += sequence_manager()->get_number_entities( this_type ); 02050 } 02051 } 02052 else 02053 { 02054 const EntitySequence* seq; 02055 result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result ); 02056 const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq ); 02057 result = mseq->num_dimension( sequence_manager(), meshset, dim, number, recursive );MB_CHK_ERR( result ); 02058 } 02059 02060 return MB_SUCCESS; 02061 } 02062 02063 //! returns the number of entities with a given type and tag 02064 ErrorCode Core::get_number_entities_by_type( const EntityHandle meshset, 02065 const EntityType entity_type, 02066 int& num_ent, 02067 const bool recursive ) const 02068 { 02069 ErrorCode result = MB_SUCCESS; 02070 02071 if( recursive && entity_type == MBENTITYSET ) // will never return anything 02072 return MB_TYPE_OUT_OF_RANGE; 02073 02074 if( meshset ) 02075 { 02076 const EntitySequence* seq; 02077 result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result ); 02078 const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq ); 02079 result = mseq->num_type( sequence_manager(), meshset, entity_type, num_ent, recursive );MB_CHK_ERR( result ); 02080 } 02081 else 02082 { 02083 num_ent = sequence_manager()->get_number_entities( entity_type ); 02084 } 02085 02086 return MB_SUCCESS; 02087 } 02088 02089 ErrorCode Core::get_number_entities_by_type_and_tag( const EntityHandle meshset, 02090 const EntityType entity_type, 02091 const Tag* tag_handles, 02092 const void* const* values, 02093 const int num_tags, 02094 int& num_entities, 02095 int condition, 02096 const bool recursive ) const 02097 { 02098 Range dum_ents; 02099 ErrorCode result = get_entities_by_type_and_tag( meshset, entity_type, tag_handles, values, num_tags, dum_ents, 02100 condition, recursive ); 02101 num_entities = dum_ents.size(); 02102 return result; 02103 } 02104 02105 ErrorCode Core::get_number_entities_by_handle( const EntityHandle meshset, int& num_ent, const bool recursive ) const 02106 { 02107 ErrorCode result; 02108 if( meshset ) 02109 { 02110 const EntitySequence* seq; 02111 result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result ); 02112 const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq ); 02113 return mseq->num_entities( sequence_manager(), meshset, num_ent, recursive ); 02114 } 02115 02116 num_ent = 0; 02117 for( EntityType this_type = MBVERTEX; this_type < MBMAXTYPE; this_type++ ) 02118 { 02119 int dummy = 0; 02120 result = get_number_entities_by_type( 0, this_type, dummy ); 02121 if( result != MB_SUCCESS ) 02122 { 02123 num_ent = 0; 02124 return result; 02125 } 02126 num_ent += dummy; 02127 } 02128 02129 return MB_SUCCESS; 02130 } 02131 02132 //! return the tag data for a given EntityHandle and Tag 02133 ErrorCode Core::tag_get_data( const Tag tag_handle, 02134 const EntityHandle* entity_handles, 02135 int num_entities, 02136 void* tag_data ) const 02137 { 02138 assert( valid_tag_handle( tag_handle ) ); 02139 CHECK_MESH_NULL 02140 return tag_handle->get_data( sequenceManager, mError, entity_handles, num_entities, tag_data ); 02141 } 02142 02143 //! return the tag data for a given EntityHandle and Tag 02144 ErrorCode Core::tag_get_data( const Tag tag_handle, const Range& entity_handles, void* tag_data ) const 02145 { 02146 assert( valid_tag_handle( tag_handle ) ); 02147 return tag_handle->get_data( sequenceManager, mError, entity_handles, tag_data ); 02148 } 02149 02150 //! set the data for given EntityHandles and Tag 02151 ErrorCode Core::tag_set_data( Tag tag_handle, 02152 const EntityHandle* entity_handles, 02153 int num_entities, 02154 const void* tag_data ) 02155 { 02156 assert( valid_tag_handle( tag_handle ) ); 02157 CHECK_MESH_NULL 02158 return tag_handle->set_data( sequenceManager, mError, entity_handles, num_entities, tag_data ); 02159 } 02160 02161 //! set the data for given EntityHandles and Tag 02162 ErrorCode Core::tag_set_data( Tag tag_handle, const Range& entity_handles, const void* tag_data ) 02163 { 02164 assert( valid_tag_handle( tag_handle ) ); 02165 return tag_handle->set_data( sequenceManager, mError, entity_handles, tag_data ); 02166 } 02167 02168 //! return the tag data for a given EntityHandle and Tag 02169 ErrorCode Core::tag_get_by_ptr( const Tag tag_handle, 02170 const EntityHandle* entity_handles, 02171 int num_entities, 02172 const void** tag_data, 02173 int* tag_sizes ) const 02174 { 02175 assert( valid_tag_handle( tag_handle ) ); 02176 CHECK_MESH_NULL 02177 ErrorCode result = 02178 tag_handle->get_data( sequenceManager, mError, entity_handles, num_entities, tag_data, tag_sizes ); 02179 int typesize = TagInfo::size_from_data_type( tag_handle->get_data_type() ); 02180 if( tag_sizes && typesize != 1 ) 02181 for( int i = 0; i < num_entities; ++i ) 02182 tag_sizes[i] /= typesize; 02183 return result; 02184 } 02185 02186 //! return the tag data for a given EntityHandle and Tag 02187 ErrorCode Core::tag_get_by_ptr( const Tag tag_handle, 02188 const Range& entity_handles, 02189 const void** tag_data, 02190 int* tag_sizes ) const 02191 { 02192 assert( valid_tag_handle( tag_handle ) ); 02193 ErrorCode result = tag_handle->get_data( sequenceManager, mError, entity_handles, tag_data, tag_sizes ); 02194 int typesize = TagInfo::size_from_data_type( tag_handle->get_data_type() ); 02195 if( tag_sizes && typesize != 1 ) 02196 { 02197 int num_entities = entity_handles.size(); 02198 for( int i = 0; i < num_entities; ++i ) 02199 tag_sizes[i] /= typesize; 02200 } 02201 return result; 02202 } 02203 02204 //! set the data for given EntityHandles and Tag 02205 ErrorCode Core::tag_set_by_ptr( Tag tag_handle, 02206 const EntityHandle* entity_handles, 02207 int num_entities, 02208 void const* const* tag_data, 02209 const int* tag_sizes ) 02210 { 02211 assert( valid_tag_handle( tag_handle ) ); 02212 CHECK_MESH_NULL 02213 std::vector< int > tmp_sizes; 02214 int typesize = TagInfo::size_from_data_type( tag_handle->get_data_type() ); 02215 if( typesize != 1 && tag_sizes ) 02216 { 02217 tmp_sizes.resize( num_entities ); 02218 for( int i = 0; i < num_entities; ++i ) 02219 tmp_sizes[i] = tag_sizes[i] * typesize; 02220 tag_sizes = &tmp_sizes[0]; 02221 } 02222 return tag_handle->set_data( sequenceManager, mError, entity_handles, num_entities, tag_data, tag_sizes ); 02223 } 02224 02225 //! set the data for given EntityHandles and Tag 02226 ErrorCode Core::tag_set_by_ptr( Tag tag_handle, 02227 const Range& entity_handles, 02228 void const* const* tag_data, 02229 const int* tag_sizes ) 02230 { 02231 assert( valid_tag_handle( tag_handle ) ); 02232 std::vector< int > tmp_sizes; 02233 int typesize = TagInfo::size_from_data_type( tag_handle->get_data_type() ); 02234 if( typesize != 1 && tag_sizes ) 02235 { 02236 int num_entities = entity_handles.size(); 02237 tmp_sizes.resize( num_entities ); 02238 for( int i = 0; i < num_entities; ++i ) 02239 tmp_sizes[i] = tag_sizes[i] * typesize; 02240 tag_sizes = &tmp_sizes[0]; 02241 } 02242 return tag_handle->set_data( sequenceManager, mError, entity_handles, tag_data, tag_sizes ); 02243 } 02244 02245 //! set the data for given EntityHandles and Tag 02246 ErrorCode Core::tag_clear_data( Tag tag_handle, 02247 const EntityHandle* entity_handles, 02248 int num_entities, 02249 const void* tag_data, 02250 int tag_size ) 02251 { 02252 assert( valid_tag_handle( tag_handle ) ); 02253 CHECK_MESH_NULL 02254 return tag_handle->clear_data( sequenceManager, mError, entity_handles, num_entities, tag_data, 02255 tag_size * TagInfo::size_from_data_type( tag_handle->get_data_type() ) ); 02256 } 02257 02258 //! set the data for given EntityHandles and Tag 02259 ErrorCode Core::tag_clear_data( Tag tag_handle, const Range& entity_handles, const void* tag_data, int tag_size ) 02260 { 02261 assert( valid_tag_handle( tag_handle ) ); 02262 return tag_handle->clear_data( sequenceManager, mError, entity_handles, tag_data, 02263 tag_size * TagInfo::size_from_data_type( tag_handle->get_data_type() ) ); 02264 } 02265 02266 static bool is_zero_bytes( const void* mem, size_t size ) 02267 { 02268 const char* iter = reinterpret_cast< const char* >( mem ); 02269 const char* const end = iter + size; 02270 for( ; iter != end; ++iter ) 02271 if( *iter ) return false; 02272 return true; 02273 } 02274 02275 ErrorCode Core::tag_get_handle( const char* name, 02276 int size, 02277 DataType data_type, 02278 Tag& tag_handle, 02279 unsigned flags, 02280 const void* default_value, 02281 bool* created ) 02282 { 02283 if( created ) *created = false; 02284 02285 // we always work with sizes in bytes internally 02286 if( !( ( flags & MB_TAG_VARLEN ) && size == MB_VARIABLE_LENGTH ) ) 02287 { 02288 if( flags & MB_TAG_BYTES ) 02289 { 02290 if( size % TagInfo::size_from_data_type( data_type ) ) return MB_INVALID_SIZE; 02291 } 02292 else 02293 { 02294 size *= TagInfo::size_from_data_type( data_type ); 02295 } 02296 } 02297 02298 const TagType storage = static_cast< TagType >( flags & 3 ); 02299 02300 // search for an existing tag 02301 tag_handle = 0; 02302 if( name && *name ) 02303 { // not anonymous tag 02304 for( std::list< Tag >::iterator i = tagList.begin(); i != tagList.end(); ++i ) 02305 { 02306 if( ( *i )->get_name() == name ) 02307 { 02308 tag_handle = *i; 02309 break; 02310 } 02311 } 02312 } 02313 02314 if( tag_handle ) 02315 { 02316 if( flags & MB_TAG_EXCL ) return MB_ALREADY_ALLOCATED; 02317 // user asked that we not check anything 02318 if( flags & MB_TAG_ANY ) return MB_SUCCESS; 02319 // user asked that we also match storage types 02320 if( ( flags & MB_TAG_STORE ) && tag_handle->get_storage_type() != storage ) return MB_TYPE_OUT_OF_RANGE; 02321 // check if data type matches 02322 const DataType extype = tag_handle->get_data_type(); 02323 if( extype != data_type ) 02324 { 02325 if( flags & MB_TAG_NOOPQ ) 02326 return MB_TYPE_OUT_OF_RANGE; 02327 else if( extype != MB_TYPE_OPAQUE && data_type != MB_TYPE_OPAQUE ) 02328 return MB_TYPE_OUT_OF_RANGE; 02329 } 02330 02331 // Require that the size value be zero or MB_VARIABLE_LENGTH 02332 // for variable length tags. The caller passing such a size 02333 // value is sufficient to indicate that the caller is aware 02334 // that it is requesting a variable-length tag, so no need 02335 // to also require/check the MB_TAG_VARLEN bit in the flags. 02336 if( tag_handle->variable_length() ) 02337 { 02338 if( size != 0 && size != MB_VARIABLE_LENGTH && !( flags & MB_TAG_VARLEN ) ) return MB_INVALID_SIZE; 02339 } 02340 // But /do/ fail if MB_TAG_VARLEN flag is set and tag is 02341 // not variable length. 02342 else if( flags & MB_TAG_VARLEN ) 02343 return MB_TYPE_OUT_OF_RANGE; 02344 // check size for fixed-length tag 02345 else if( tag_handle->get_size() != size ) 02346 return MB_INVALID_SIZE; 02347 02348 // If user passed a default value, check that it matches. 02349 // If user did not pass a default value, assume they're OK 02350 // with the existing one. 02351 // If tag does not have a default value but the user passed 02352 // one, allow it only if the tag is dense and the passed value 02353 // is all zero bytes because dense tags have an implicit default 02354 // value of all zeros in some cases. 02355 if( default_value && !( flags & MB_TAG_DFTOK ) && 02356 !( tag_handle->equals_default_value( default_value, size ) || 02357 ( !tag_handle->get_default_value() && tag_handle->get_storage_type() == MB_TAG_DENSE && 02358 is_zero_bytes( default_value, size ) ) ) ) 02359 return MB_ALREADY_ALLOCATED; 02360 02361 return MB_SUCCESS; 02362 } 02363 02364 // MB_TAG_EXCL implies MB_TAG_CREAT 02365 if( !( flags & ( MB_TAG_CREAT | MB_TAG_EXCL ) ) ) return MB_TAG_NOT_FOUND; 02366 02367 // if a non-opaque non-bit type was specified, then the size 02368 // must be multiple of the size of the type 02369 if( ( !( flags & MB_TAG_VARLEN ) || default_value ) && 02370 ( size <= 0 || ( size % TagInfo::size_from_data_type( data_type ) ) != 0 ) ) 02371 return MB_INVALID_SIZE; 02372 02373 // if MB_TYPE_BIT may be used only with MB_TAG_BIT 02374 // if (storage != MB_TAG_BIT && data_type == MB_TYPE_BIT) 02375 // return MB_INVALID_ARG; 02376 if( data_type == MB_TYPE_BIT ) flags &= ~(unsigned)( MB_TAG_DENSE | MB_TAG_SPARSE ); 02377 02378 // create the tag 02379 switch( flags & ( MB_TAG_DENSE | MB_TAG_SPARSE | MB_TAG_MESH | MB_TAG_VARLEN ) ) 02380 { 02381 case MB_TAG_DENSE | MB_TAG_VARLEN: 02382 tag_handle = VarLenDenseTag::create_tag( sequenceManager, mError, name, data_type, default_value, size ); 02383 break; 02384 case MB_TAG_DENSE: 02385 tag_handle = DenseTag::create_tag( sequenceManager, mError, name, size, data_type, default_value ); 02386 break; 02387 case MB_TAG_SPARSE | MB_TAG_VARLEN: 02388 tag_handle = new VarLenSparseTag( name, data_type, default_value, size ); 02389 break; 02390 case MB_TAG_SPARSE: 02391 tag_handle = new SparseTag( name, size, data_type, default_value ); 02392 break; 02393 case MB_TAG_MESH | MB_TAG_VARLEN: 02394 tag_handle = new MeshTag( name, MB_VARIABLE_LENGTH, data_type, default_value, size ); 02395 break; 02396 case MB_TAG_MESH: 02397 tag_handle = new MeshTag( name, size, data_type, default_value, size ); 02398 break; 02399 case MB_TAG_BIT: 02400 if( MB_TYPE_BIT != data_type && MB_TYPE_OPAQUE != data_type ) return MB_TYPE_OUT_OF_RANGE; 02401 tag_handle = BitTag::create_tag( name, size, default_value ); 02402 break; 02403 default: // some illegal combination (multiple storage types, variable-length bit tag, etc.) 02404 return MB_TYPE_OUT_OF_RANGE; 02405 } 02406 02407 if( !tag_handle ) return MB_INVALID_SIZE; 02408 02409 if( created ) *created = true; 02410 tagList.push_back( tag_handle ); 02411 return MB_SUCCESS; 02412 } 02413 02414 ErrorCode Core::tag_get_handle( const char* name, 02415 int size, 02416 DataType data_type, 02417 Tag& tag_handle, 02418 unsigned flags, 02419 const void* default_value ) const 02420 { 02421 // If caller specified MB_TAG_EXCL, then we must fail because 02422 // this const function can never create a tag. We need to test 02423 // this here because the non-const version of this function 02424 // assumes MB_TAG_CREAT if MB_TAG_EXCL is specified. 02425 if( flags & MB_TAG_EXCL ) 02426 { 02427 // anonymous tag? 02428 if( !name || !*name ) return MB_TAG_NOT_FOUND; 02429 02430 // search for an existing tag 02431 tag_handle = 0; 02432 for( std::list< Tag >::const_iterator i = tagList.begin(); i != tagList.end(); ++i ) 02433 { 02434 if( ( *i )->get_name() == name ) 02435 { 02436 tag_handle = *i; 02437 return MB_ALREADY_ALLOCATED; 02438 } 02439 } 02440 02441 return MB_TAG_NOT_FOUND; 02442 } 02443 02444 return const_cast< Core* >( this )->tag_get_handle( name, size, data_type, tag_handle, 02445 flags & ~(unsigned)MB_TAG_CREAT, default_value ); 02446 } 02447 02448 //! removes the tag from the entity 02449 ErrorCode Core::tag_delete_data( Tag tag_handle, const EntityHandle* entity_handles, int num_entities ) 02450 { 02451 assert( valid_tag_handle( tag_handle ) ); 02452 CHECK_MESH_NULL 02453 return tag_handle->remove_data( sequenceManager, mError, entity_handles, num_entities ); 02454 } 02455 02456 //! removes the tag from the entity 02457 ErrorCode Core::tag_delete_data( Tag tag_handle, const Range& entity_handles ) 02458 { 02459 assert( valid_tag_handle( tag_handle ) ); 02460 return tag_handle->remove_data( sequenceManager, mError, entity_handles ); 02461 } 02462 02463 //! removes the tag from MB 02464 ErrorCode Core::tag_delete( Tag tag_handle ) 02465 { 02466 std::list< TagInfo* >::iterator i = std::find( tagList.begin(), tagList.end(), tag_handle ); 02467 if( i == tagList.end() ) return MB_TAG_NOT_FOUND; 02468 02469 ErrorCode rval = tag_handle->release_all_data( sequenceManager, mError, true );MB_CHK_ERR( rval ); 02470 02471 tagList.erase( i ); 02472 delete tag_handle; 02473 return MB_SUCCESS; 02474 } 02475 02476 ErrorCode Core::tag_iterate( Tag tag_handle, 02477 Range::const_iterator iter, 02478 Range::const_iterator end, 02479 int& count, 02480 void*& data_ptr, 02481 bool allocate ) 02482 { 02483 Range::const_iterator init = iter; 02484 assert( valid_tag_handle( tag_handle ) ); 02485 ErrorCode result = tag_handle->tag_iterate( sequenceManager, mError, iter, end, data_ptr, allocate ); 02486 if( MB_SUCCESS == result ) count = iter - init; 02487 return result; 02488 } 02489 02490 //! gets the tag name string for the tag_handle 02491 ErrorCode Core::tag_get_name( const Tag tag_handle, std::string& tag_name ) const 02492 { 02493 if( !valid_tag_handle( tag_handle ) ) return MB_TAG_NOT_FOUND; 02494 tag_name = tag_handle->get_name(); 02495 return MB_SUCCESS; 02496 } 02497 02498 ErrorCode Core::tag_get_handle( const char* tag_name, Tag& tag_handle ) const 02499 { 02500 return tag_get_handle( tag_name, 0, MB_TYPE_OPAQUE, tag_handle, MB_TAG_ANY ); 02501 } 02502 02503 //! get size of tag in bytes 02504 ErrorCode Core::tag_get_bytes( const Tag tag_handle, int& tag_size ) const 02505 { 02506 if( !valid_tag_handle( tag_handle ) ) return MB_TAG_NOT_FOUND; 02507 02508 if( tag_handle->variable_length() ) 02509 { 02510 tag_size = MB_VARIABLE_LENGTH; 02511 return MB_VARIABLE_DATA_LENGTH; 02512 } 02513 else if( tag_handle->get_storage_type() == MB_TAG_BIT ) 02514 { 02515 tag_size = 1; 02516 return MB_SUCCESS; 02517 } 02518 else 02519 { 02520 tag_size = tag_handle->get_size(); 02521 return MB_SUCCESS; 02522 } 02523 } 02524 02525 //! get size of tag in $values 02526 ErrorCode Core::tag_get_length( const Tag tag_handle, int& tag_size ) const 02527 { 02528 if( !valid_tag_handle( tag_handle ) ) return MB_TAG_NOT_FOUND; 02529 02530 if( tag_handle->variable_length() ) 02531 { 02532 tag_size = MB_VARIABLE_LENGTH; 02533 return MB_VARIABLE_DATA_LENGTH; 02534 } 02535 else 02536 { 02537 tag_size = tag_handle->get_size() / TagInfo::size_from_data_type( tag_handle->get_data_type() ); 02538 return MB_SUCCESS; 02539 } 02540 } 02541 02542 ErrorCode Core::tag_get_data_type( const Tag handle, DataType& data_type ) const 02543 { 02544 if( !valid_tag_handle( handle ) ) return MB_TAG_NOT_FOUND; 02545 02546 data_type = handle->get_data_type(); 02547 return MB_SUCCESS; 02548 } 02549 02550 //! get default value of the tag 02551 ErrorCode Core::tag_get_default_value( const Tag tag_handle, void* def_value ) const 02552 { 02553 if( !valid_tag_handle( tag_handle ) ) return MB_TAG_NOT_FOUND; 02554 02555 if( tag_handle->variable_length() ) return MB_VARIABLE_DATA_LENGTH; 02556 02557 if( !tag_handle->get_default_value() ) return MB_ENTITY_NOT_FOUND; 02558 02559 memcpy( def_value, tag_handle->get_default_value(), tag_handle->get_default_value_size() ); 02560 return MB_SUCCESS; 02561 } 02562 02563 ErrorCode Core::tag_get_default_value( Tag tag, const void*& ptr, int& size ) const 02564 { 02565 if( !valid_tag_handle( tag ) ) return MB_ENTITY_NOT_FOUND; 02566 02567 if( !tag->get_default_value() ) return MB_ENTITY_NOT_FOUND; 02568 02569 ptr = tag->get_default_value(); 02570 size = tag->get_default_value_size() / TagInfo::size_from_data_type( tag->get_data_type() ); 02571 return MB_SUCCESS; 02572 } 02573 02574 //! get type of tag (sparse, dense, etc.; 0 = dense, 1 = sparse, 2 = bit, 3 = static) 02575 ErrorCode Core::tag_get_type( const Tag tag_handle, TagType& tag_type ) const 02576 { 02577 assert( valid_tag_handle( tag_handle ) ); 02578 tag_type = tag_handle->get_storage_type(); 02579 return MB_SUCCESS; 02580 } 02581 02582 //! get handles for all tags defined 02583 ErrorCode Core::tag_get_tags( std::vector< Tag >& tag_handles ) const 02584 { 02585 std::copy( tagList.begin(), tagList.end(), std::back_inserter( tag_handles ) ); 02586 return MB_SUCCESS; 02587 } 02588 02589 //! Get handles for all tags defined on this entity 02590 ErrorCode Core::tag_get_tags_on_entity( const EntityHandle entity, std::vector< Tag >& tag_handles ) const 02591 { 02592 for( std::list< TagInfo* >::const_iterator i = tagList.begin(); i != tagList.end(); ++i ) 02593 if( ( *i )->is_tagged( sequenceManager, entity ) ) tag_handles.push_back( *i ); 02594 return MB_SUCCESS; 02595 } 02596 02597 Tag Core::material_tag() 02598 { 02599 const int negone = -1; 02600 if( 0 == materialTag ) 02601 tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, materialTag, MB_TAG_CREAT | MB_TAG_SPARSE, &negone ); 02602 return materialTag; 02603 } 02604 02605 Tag Core::neumannBC_tag() 02606 { 02607 const int negone = -1; 02608 if( 0 == neumannBCTag ) 02609 tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, neumannBCTag, MB_TAG_CREAT | MB_TAG_SPARSE, &negone ); 02610 return neumannBCTag; 02611 } 02612 02613 Tag Core::dirichletBC_tag() 02614 { 02615 const int negone = -1; 02616 if( 0 == dirichletBCTag ) 02617 tag_get_handle( DIRICHLET_SET_TAG_NAME, 1, MB_TYPE_INTEGER, dirichletBCTag, MB_TAG_CREAT | MB_TAG_SPARSE, 02618 &negone ); 02619 return dirichletBCTag; 02620 } 02621 02622 Tag Core::globalId_tag() 02623 { 02624 const int negone = -1; 02625 if( 0 == globalIdTag ) 02626 tag_get_handle( GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, globalIdTag, MB_TAG_CREAT | MB_TAG_DENSE, &negone ); 02627 return globalIdTag; 02628 } 02629 02630 Tag Core::geom_dimension_tag() 02631 { 02632 const int negone = -1; 02633 if( 0 == geomDimensionTag ) 02634 tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geomDimensionTag, MB_TAG_CREAT | MB_TAG_SPARSE, 02635 &negone ); 02636 return geomDimensionTag; 02637 } 02638 02639 //! creates an element based on the type and connectivity. returns a handle and error code 02640 ErrorCode Core::create_element( const EntityType entity_type, 02641 const EntityHandle* connectivity, 02642 const int num_nodes, 02643 EntityHandle& handle ) 02644 { 02645 // make sure we have enough vertices for this entity type 02646 if( num_nodes < CN::VerticesPerEntity( entity_type ) ) return MB_FAILURE; 02647 02648 ErrorCode status = sequence_manager()->create_element( entity_type, connectivity, num_nodes, handle ); 02649 if( MB_SUCCESS == status ) status = aEntityFactory->notify_create_entity( handle, connectivity, num_nodes ); 02650 02651 #ifdef MOAB_HAVE_AHF 02652 mesh_modified = true; 02653 #endif 02654 02655 return status; 02656 } 02657 02658 //! creates a vertex based on coordinates, returns a handle and error code 02659 ErrorCode Core::create_vertex( const double coords[3], EntityHandle& handle ) 02660 { 02661 // get an available vertex handle 02662 return sequence_manager()->create_vertex( coords, handle ); 02663 } 02664 02665 ErrorCode Core::create_vertices( const double* coordinates, const int nverts, Range& entity_handles ) 02666 { 02667 // Create vertices 02668 ReadUtilIface* read_iface; 02669 ErrorCode result = Interface::query_interface( read_iface );MB_CHK_ERR( result ); 02670 02671 std::vector< double* > arrays; 02672 EntityHandle start_handle_out = 0; 02673 result = read_iface->get_node_coords( 3, nverts, MB_START_ID, start_handle_out, arrays ); 02674 Interface::release_interface( read_iface );MB_CHK_ERR( result ); 02675 // Cppcheck warning (false positive): variable arrays is assigned a value that is never used 02676 for( int i = 0; i < nverts; i++ ) 02677 { 02678 arrays[0][i] = coordinates[3 * i]; 02679 arrays[1][i] = coordinates[3 * i + 1]; 02680 arrays[2][i] = coordinates[3 * i + 2]; 02681 } 02682 02683 entity_handles.clear(); 02684 entity_handles.insert( start_handle_out, start_handle_out + nverts - 1 ); 02685 02686 return MB_SUCCESS; 02687 } 02688 02689 //! merges two entities 02690 ErrorCode Core::merge_entities( EntityHandle entity_to_keep, 02691 EntityHandle entity_to_remove, 02692 bool auto_merge, 02693 bool delete_removed_entity ) 02694 { 02695 if( auto_merge ) return MB_FAILURE; 02696 02697 // The two entities to merge must not be the same entity. 02698 if( entity_to_keep == entity_to_remove ) return MB_FAILURE; 02699 02700 // The two entities to merge must be of the same type 02701 EntityType type_to_keep = TYPE_FROM_HANDLE( entity_to_keep ); 02702 02703 if( type_to_keep != TYPE_FROM_HANDLE( entity_to_remove ) ) return MB_TYPE_OUT_OF_RANGE; 02704 02705 // Make sure both entities exist before trying to merge. 02706 EntitySequence* seq = 0; 02707 ErrorCode result, status; 02708 status = sequence_manager()->find( entity_to_keep, seq ); 02709 if( seq == 0 || status != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND; 02710 status = sequence_manager()->find( entity_to_remove, seq ); 02711 if( seq == 0 || status != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND; 02712 02713 // If auto_merge is not set, all sub-entities should 02714 // be merged if the entities are to be merged. 02715 int ent_dim = CN::Dimension( type_to_keep ); 02716 if( ent_dim > 0 ) 02717 { 02718 std::vector< EntityHandle > conn, conn2; 02719 02720 result = get_connectivity( &entity_to_keep, 1, conn );MB_CHK_ERR( result ); 02721 result = get_connectivity( &entity_to_remove, 1, conn2 );MB_CHK_ERR( result ); 02722 02723 // Check to see if we can merge before pulling adjacencies. 02724 int dum1, dum2; 02725 if( !auto_merge && 02726 ( conn.size() != conn2.size() || !CN::ConnectivityMatch( &conn[0], &conn2[0], conn.size(), dum1, dum2 ) ) ) 02727 return MB_FAILURE; 02728 } 02729 02730 result = aEntityFactory->merge_adjust_adjacencies( entity_to_keep, entity_to_remove ); 02731 02732 if( MB_SUCCESS == result && delete_removed_entity ) result = delete_entities( &entity_to_remove, 1 ); 02733 02734 return result; 02735 } 02736 02737 //! deletes an entity range 02738 ErrorCode Core::delete_entities( const Range& range ) 02739 { 02740 ErrorCode result = MB_SUCCESS, temp_result; 02741 Range failed_ents; 02742 02743 for( std::list< TagInfo* >::iterator i = tagList.begin(); i != tagList.end(); ++i ) 02744 { 02745 temp_result = ( *i )->remove_data( sequenceManager, mError, range ); 02746 // ok if the error is tag_not_found, some ents may not have every tag on them 02747 if( MB_SUCCESS != temp_result && MB_TAG_NOT_FOUND != temp_result ) result = temp_result; 02748 } 02749 02750 for( Range::const_reverse_iterator rit = range.rbegin(); rit != range.rend(); ++rit ) 02751 { 02752 02753 // tell AEntityFactory that this element is going away 02754 temp_result = aEntityFactory->notify_delete_entity( *rit ); 02755 if( MB_SUCCESS != temp_result ) 02756 { 02757 result = temp_result; 02758 failed_ents.insert( *rit ); 02759 continue; 02760 } 02761 02762 if( TYPE_FROM_HANDLE( *rit ) == MBENTITYSET ) 02763 { 02764 if( MeshSet* ptr = get_mesh_set( sequence_manager(), *rit ) ) 02765 { 02766 int j, count; 02767 const EntityHandle* rel; 02768 ptr->clear( *rit, a_entity_factory() ); 02769 rel = ptr->get_parents( count ); 02770 for( j = 0; j < count; ++j ) 02771 remove_child_meshset( rel[j], *rit ); 02772 rel = ptr->get_children( count ); 02773 for( j = 0; j < count; ++j ) 02774 remove_parent_meshset( rel[j], *rit ); 02775 } 02776 } 02777 } 02778 02779 if( !failed_ents.empty() ) 02780 { 02781 Range dum_range = subtract( range, failed_ents ); 02782 // don't test for success, since we'll return failure in this case 02783 sequence_manager()->delete_entities( mError, dum_range ); 02784 } 02785 else 02786 // now delete the entities 02787 result = sequence_manager()->delete_entities( mError, range ); 02788 02789 return result; 02790 } 02791 02792 //! deletes an entity vector 02793 ErrorCode Core::delete_entities( const EntityHandle* entities, const int num_entities ) 02794 { 02795 ErrorCode result = MB_SUCCESS, temp_result; 02796 Range failed_ents; 02797 02798 for( std::list< TagInfo* >::iterator i = tagList.begin(); i != tagList.end(); ++i ) 02799 { 02800 temp_result = ( *i )->remove_data( sequenceManager, mError, entities, num_entities ); 02801 // ok if the error is tag_not_found, some ents may not have every tag on them 02802 if( MB_SUCCESS != temp_result && MB_TAG_NOT_FOUND != temp_result ) result = temp_result; 02803 } 02804 02805 for( int i = 0; i < num_entities; i++ ) 02806 { 02807 02808 // tell AEntityFactory that this element is going away 02809 bool failed = false; 02810 temp_result = aEntityFactory->notify_delete_entity( entities[i] ); 02811 if( MB_SUCCESS != temp_result ) 02812 { 02813 result = temp_result; 02814 failed = true; 02815 } 02816 02817 if( TYPE_FROM_HANDLE( entities[i] ) == MBENTITYSET ) 02818 { 02819 if( MeshSet* ptr = get_mesh_set( sequence_manager(), entities[i] ) ) 02820 { 02821 int j, count; 02822 const EntityHandle* rel; 02823 ptr->clear( entities[i], a_entity_factory() ); 02824 rel = ptr->get_parents( count ); 02825 for( j = 0; j < count; ++j ) 02826 remove_child_meshset( rel[j], entities[i] ); 02827 rel = ptr->get_children( count ); 02828 for( j = 0; j < count; ++j ) 02829 remove_parent_meshset( rel[j], entities[i] ); 02830 } 02831 } 02832 02833 if( failed ) 02834 // don't test for success, since we'll return failure in this case 02835 sequence_manager()->delete_entity( mError, entities[i] ); 02836 else 02837 { 02838 // now delete the entity 02839 temp_result = sequence_manager()->delete_entity( mError, entities[i] ); 02840 if( MB_SUCCESS != temp_result ) result = temp_result; 02841 } 02842 } 02843 02844 return result; 02845 } 02846 02847 ErrorCode Core::list_entities( const EntityHandle* entities, const int num_entities ) const 02848 { 02849 Range temp_range; 02850 ErrorCode result = MB_SUCCESS; 02851 if( NULL == entities && num_entities == 0 ) 02852 { 02853 // just list the numbers of each entity type 02854 int num_ents; 02855 std::cout << std::endl; 02856 std::cout << "Number of entities per type: " << std::endl; 02857 for( EntityType this_type = MBVERTEX; this_type < MBMAXTYPE; this_type++ ) 02858 { 02859 result = get_number_entities_by_type( 0, this_type, num_ents ); 02860 std::cout << CN::EntityTypeName( this_type ) << ": " << num_ents << std::endl; 02861 } 02862 std::cout << std::endl; 02863 02864 return MB_SUCCESS; 02865 } 02866 else if( NULL == entities && num_entities < 0 ) 02867 { 02868 02869 // list all entities of all types 02870 std::cout << std::endl; 02871 for( EntityType this_type = MBVERTEX; this_type < MBMAXTYPE; this_type++ ) 02872 { 02873 result = get_entities_by_type( 0, this_type, temp_range ); 02874 } 02875 02876 return list_entities( temp_range ); 02877 } 02878 else if( NULL == entities && num_entities > 0 ) 02879 { 02880 02881 // list all entities of type == num_entities 02882 std::cout << std::endl; 02883 result = get_entities_by_type( 0, (EntityType)num_entities, temp_range ); 02884 02885 return list_entities( temp_range ); 02886 } 02887 else 02888 { 02889 ErrorCode tmp_result; 02890 for( int i = 0; i < num_entities; i++ ) 02891 { 02892 EntityType this_type = TYPE_FROM_HANDLE( entities[i] ); 02893 std::cout << CN::EntityTypeName( this_type ) << " " << ID_FROM_HANDLE( entities[i] ) << ":" << endl; 02894 02895 tmp_result = ( const_cast< Core* >( this ) )->list_entity( entities[i] ); 02896 if( MB_SUCCESS != tmp_result ) result = tmp_result; 02897 } 02898 } 02899 02900 return result; 02901 } 02902 02903 ErrorCode Core::list_entities( const Range& temp_range ) const 02904 { 02905 ErrorCode result = MB_SUCCESS, tmp_result; 02906 02907 for( Range::const_iterator rit = temp_range.begin(); rit != temp_range.end(); ++rit ) 02908 { 02909 EntityType this_type = TYPE_FROM_HANDLE( *rit ); 02910 std::cout << CN::EntityTypeName( this_type ) << " " << ID_FROM_HANDLE( *rit ) << ":" << endl; 02911 02912 tmp_result = ( const_cast< Core* >( this ) )->list_entity( *rit ); 02913 if( MB_SUCCESS != tmp_result ) result = tmp_result; 02914 } 02915 02916 return result; 02917 } 02918 02919 ErrorCode Core::list_entity( const EntityHandle entity ) const 02920 { 02921 ErrorCode result; 02922 HandleVec adj_vec; 02923 02924 if( !is_valid( entity ) ) 02925 { 02926 std::cout << "(invalid)" << std::endl; 02927 return MB_SUCCESS; 02928 } 02929 02930 if( 0 != globalIdTag ) 02931 { 02932 int dum; 02933 result = tag_get_data( globalIdTag, &entity, 1, &dum ); 02934 if( MB_SUCCESS == result ) std::cout << "Global id = " << dum << std::endl; 02935 } 02936 02937 // list entity 02938 EntityType this_type = TYPE_FROM_HANDLE( entity ); 02939 if( this_type == MBVERTEX ) 02940 { 02941 double coords[3]; 02942 result = get_coords( &( entity ), 1, coords );MB_CHK_ERR( result ); 02943 std::cout << "Coordinates: (" << coords[0] << ", " << coords[1] << ", " << coords[2] << ")" << std::endl; 02944 } 02945 else if( this_type == MBENTITYSET ) 02946 this->print( entity, "" ); 02947 02948 std::cout << " Adjacencies:" << std::endl; 02949 bool some = false; 02950 int multiple = 0; 02951 for( int dim = 0; dim <= 3; dim++ ) 02952 { 02953 if( dim == CN::Dimension( this_type ) ) continue; 02954 adj_vec.clear(); 02955 // use const_cast here 'cuz we're in a const function and we're passing 'false' for 02956 // create_if_missing, so we know we won't change anything 02957 result = ( const_cast< Core* >( this ) )->get_adjacencies( &( entity ), 1, dim, false, adj_vec ); 02958 if( MB_FAILURE == result ) continue; 02959 for( HandleVec::iterator adj_it = adj_vec.begin(); adj_it != adj_vec.end(); ++adj_it ) 02960 { 02961 if( adj_it != adj_vec.begin() ) 02962 std::cout << ", "; 02963 else 02964 std::cout << " "; 02965 std::cout << CN::EntityTypeName( TYPE_FROM_HANDLE( *adj_it ) ) << " " << ID_FROM_HANDLE( *adj_it ); 02966 } 02967 if( !adj_vec.empty() ) 02968 { 02969 std::cout << std::endl; 02970 some = true; 02971 } 02972 if( MB_MULTIPLE_ENTITIES_FOUND == result ) multiple += dim; 02973 } 02974 if( !some ) std::cout << "(none)" << std::endl; 02975 const EntityHandle* explicit_adjs; 02976 int num_exp; 02977 aEntityFactory->get_adjacencies( entity, explicit_adjs, num_exp ); 02978 if( NULL != explicit_adjs && 0 != num_exp ) 02979 { 02980 std::cout << " Explicit adjacencies: "; 02981 for( int i = 0; i < num_exp; i++ ) 02982 { 02983 if( i != 0 ) std::cout << ", "; 02984 std::cout << CN::EntityTypeName( TYPE_FROM_HANDLE( explicit_adjs[i] ) ) << " " 02985 << ID_FROM_HANDLE( explicit_adjs[i] ); 02986 } 02987 std::cout << std::endl; 02988 } 02989 if( multiple != 0 ) std::cout << " (MULTIPLE = " << multiple << ")" << std::endl; 02990 02991 result = print_entity_tags( std::string(), entity, MB_TAG_DENSE ); 02992 02993 std::cout << std::endl; 02994 02995 return result; 02996 } 02997 02998 ErrorCode Core::convert_entities( const EntityHandle meshset, 02999 const bool mid_side, 03000 const bool mid_face, 03001 const bool mid_volume, 03002 Interface::HONodeAddedRemoved* function_object ) 03003 { 03004 HigherOrderFactory fact( this, function_object ); 03005 return fact.convert( meshset, mid_side, mid_face, mid_volume ); 03006 } 03007 03008 //! function to get the side number given two elements; returns 03009 //! MB_FAILURE if child not related to parent; does *not* create adjacencies 03010 //! between parent and child 03011 ErrorCode Core::side_number( const EntityHandle parent, 03012 const EntityHandle child, 03013 int& sd_number, 03014 int& sense, 03015 int& offset ) const 03016 { 03017 // get the connectivity of parent and child 03018 const EntityHandle *parent_conn = NULL, *child_conn = NULL; 03019 int num_parent_vertices = 0, num_child_vertices = 0; 03020 ErrorCode result = get_connectivity( parent, parent_conn, num_parent_vertices, true ); 03021 if( MB_NOT_IMPLEMENTED == result ) 03022 { 03023 static std::vector< EntityHandle > tmp_connect( CN::MAX_NODES_PER_ELEMENT ); 03024 result = get_connectivity( parent, parent_conn, num_parent_vertices, true, &tmp_connect ); 03025 } 03026 if( MB_SUCCESS != result ) return result; 03027 03028 if( TYPE_FROM_HANDLE( child ) == MBVERTEX ) 03029 { 03030 int child_index = std::find( parent_conn, parent_conn + num_parent_vertices, child ) - parent_conn; 03031 if( child_index == num_parent_vertices ) 03032 { 03033 sd_number = -1; 03034 sense = 0; 03035 return MB_FAILURE; 03036 } 03037 else 03038 { 03039 sd_number = child_index; 03040 sense = 1; 03041 return MB_SUCCESS; 03042 } 03043 } 03044 03045 if( TYPE_FROM_HANDLE( parent ) == MBPOLYHEDRON ) 03046 { 03047 // find the child in the parent_conn connectivity list, and call it a day .. 03048 // it should work only for faces within a conn list 03049 for( int i = 0; i < num_parent_vertices; i++ ) 03050 if( child == parent_conn[i] ) 03051 { 03052 sd_number = i; 03053 sense = 1; // always 03054 offset = 0; 03055 return MB_SUCCESS; 03056 } 03057 return MB_FAILURE; 03058 } 03059 result = get_connectivity( child, child_conn, num_child_vertices, true );MB_CHK_ERR( result ); 03060 03061 // call handle vector-based function 03062 if( TYPE_FROM_HANDLE( parent ) != MBPOLYGON && TYPE_FROM_HANDLE( parent ) != MBPOLYHEDRON ) 03063 { 03064 03065 // find indices into parent_conn for each entry in child_conn 03066 int child_conn_indices[10]; 03067 assert( (unsigned)num_child_vertices <= sizeof( child_conn_indices ) / sizeof( child_conn_indices[0] ) ); 03068 for( int i = 0; i < num_child_vertices; ++i ) 03069 { 03070 child_conn_indices[i] = 03071 std::find( parent_conn, parent_conn + num_parent_vertices, child_conn[i] ) - parent_conn; 03072 if( child_conn_indices[i] >= num_parent_vertices ) 03073 { 03074 sd_number = -1; 03075 return MB_FAILURE; 03076 } 03077 } 03078 03079 int temp_result = CN::SideNumber( TYPE_FROM_HANDLE( parent ), child_conn_indices, num_child_vertices, 03080 CN::Dimension( TYPE_FROM_HANDLE( child ) ), sd_number, sense, offset ); 03081 return ( 0 == temp_result ? MB_SUCCESS : MB_FAILURE ); 03082 } 03083 else if( TYPE_FROM_HANDLE( parent ) == MBPOLYGON ) 03084 { 03085 // find location of 1st vertex; this works even for padded vertices 03086 const EntityHandle* first_v = std::find( parent_conn, parent_conn + num_parent_vertices, child_conn[0] ); 03087 if( first_v == parent_conn + num_parent_vertices ) return MB_ENTITY_NOT_FOUND; 03088 sd_number = first_v - parent_conn; 03089 offset = sd_number; 03090 if( TYPE_FROM_HANDLE( child ) == MBVERTEX ) 03091 { 03092 sense = 0; 03093 return MB_SUCCESS; 03094 } 03095 else if( TYPE_FROM_HANDLE( child ) == MBPOLYGON ) 03096 { 03097 bool match = CN::ConnectivityMatch( parent_conn, child_conn, num_parent_vertices, sense, offset ); 03098 sd_number = 0; 03099 if( match ) 03100 return MB_SUCCESS; 03101 else 03102 return MB_ENTITY_NOT_FOUND; 03103 } 03104 else if( TYPE_FROM_HANDLE( child ) == MBEDGE ) 03105 { 03106 // determine the actual number of vertices, for the padded case 03107 // the padded case could be like ABCDEFFF; num_parent_vertices=8, 03108 // actual_num_parent_vertices=6 03109 int actual_num_parent_vertices = num_parent_vertices; 03110 while( actual_num_parent_vertices >= 3 && 03111 ( parent_conn[actual_num_parent_vertices - 2] == parent_conn[actual_num_parent_vertices - 1] ) ) 03112 actual_num_parent_vertices--; 03113 03114 if( parent_conn[( sd_number + 1 ) % num_parent_vertices] == child_conn[1] ) 03115 sense = 1; 03116 else if( parent_conn[( sd_number + num_parent_vertices - 1 ) % num_parent_vertices] == 03117 child_conn[1] ) // this will also cover edge AF for padded case, side will 03118 // be 0, sense -1 03119 sense = -1; 03120 // if edge FA in above example, we should return sd_number = 5, sense 1 03121 else if( ( sd_number == actual_num_parent_vertices - 1 ) && ( child_conn[1] == parent_conn[0] ) ) 03122 sense = 1; 03123 else 03124 return MB_ENTITY_NOT_FOUND; 03125 return MB_SUCCESS; 03126 } 03127 } 03128 03129 return MB_FAILURE; 03130 } 03131 03132 //! given an entity and the connectivity and type of one of its subfacets, find the 03133 //! high order node on that subfacet, if any 03134 ErrorCode Core::high_order_node( const EntityHandle parent_handle, 03135 const EntityHandle* subfacet_conn, 03136 const EntityType subfacet_type, 03137 EntityHandle& hon ) const 03138 { 03139 hon = 0; 03140 03141 EntityType parent_type = TYPE_FROM_HANDLE( parent_handle ); 03142 03143 // get the parent's connectivity 03144 const EntityHandle* parent_conn = NULL; 03145 int num_parent_vertices = 0; 03146 ErrorCode result = get_connectivity( parent_handle, parent_conn, num_parent_vertices, false );MB_CHK_ERR( result ); 03147 03148 // find whether this entity has ho nodes 03149 int mid_nodes[4]; 03150 CN::HasMidNodes( parent_type, num_parent_vertices, mid_nodes ); 03151 03152 // check whether this entity has mid nodes on this dimension subfacet; 03153 // use dimension-1 because vertices don't have mid nodes 03154 if( !mid_nodes[CN::Dimension( subfacet_type )] ) return MB_SUCCESS; 03155 03156 // ok, we have mid nodes; now must compute expected index in connectivity array; 03157 // ho nodes stored for edges, faces then entity 03158 03159 // offset starts with # corner vertices 03160 int offset = CN::VerticesPerEntity( parent_type ); 03161 int i; 03162 03163 for( i = 0; i < CN::Dimension( subfacet_type ) - 1; i++ ) 03164 // for each dimension lower than that of the subfacet we're looking for, 03165 // if this entity has midnodes in that dimension, increment offset by # 03166 // of subfacets of that dimension; use dimension-1 in loop because 03167 // canon numbering table only has 2 positions, for edges and faces; 03168 if( mid_nodes[i + 1] ) offset += CN::mConnectivityMap[parent_type][i].num_sub_elements; 03169 03170 // now add the index of this subfacet; only need to if it's not the highest dimension 03171 if( subfacet_type != parent_type ) 03172 { 03173 03174 // find indices into parent_conn for each entry in child_conn 03175 unsigned subfacet_size = CN::VerticesPerEntity( subfacet_type ); 03176 int subfacet_indices[10]; 03177 assert( subfacet_size <= sizeof( subfacet_indices ) / sizeof( subfacet_indices[0] ) ); 03178 for( unsigned j = 0; j < subfacet_size; ++j ) 03179 { 03180 subfacet_indices[j] = 03181 std::find( parent_conn, parent_conn + num_parent_vertices, subfacet_conn[j] ) - parent_conn; 03182 if( subfacet_indices[j] >= num_parent_vertices ) 03183 { 03184 return MB_FAILURE; 03185 } 03186 } 03187 03188 int dum, side_no, temp_offset; 03189 int temp_result = 03190 CN::SideNumber( parent_type, subfacet_indices, subfacet_size, subfacet_type, side_no, dum, temp_offset ); 03191 if( temp_result != 0 ) return MB_FAILURE; 03192 03193 offset += side_no; 03194 } 03195 03196 // offset shouldn't be off the end of the connectivity vector 03197 if( offset >= num_parent_vertices ) return MB_INDEX_OUT_OF_RANGE; 03198 03199 hon = parent_conn[offset]; 03200 03201 return MB_SUCCESS; 03202 } 03203 03204 //! given an entity and a target dimension & side number, get that entity 03205 ErrorCode Core::side_element( const EntityHandle source_entity, 03206 const int dim, 03207 const int sd_number, 03208 EntityHandle& target_entity ) const 03209 { 03210 // get a handle on the connectivity 03211 const EntityHandle* verts; 03212 int num_verts; 03213 ErrorCode result = get_connectivity( source_entity, verts, num_verts );MB_CHK_ERR( result ); 03214 03215 // special case for vertices 03216 if( dim == 0 ) 03217 { 03218 if( sd_number < num_verts ) 03219 { 03220 target_entity = verts[sd_number]; 03221 return MB_SUCCESS; 03222 } 03223 03224 else 03225 return MB_INDEX_OUT_OF_RANGE; 03226 } 03227 03228 // get the vertices comprising the target entity 03229 Range side_verts, target_ents; 03230 const EntityType source_type = TYPE_FROM_HANDLE( source_entity ); 03231 // first get the indices 03232 std::vector< int > vertex_indices; 03233 03234 int temp_result = CN::AdjacentSubEntities( source_type, &sd_number, 1, dim, 0, vertex_indices ); 03235 if( 0 != temp_result ) return MB_FAILURE; 03236 // now get the actual vertices 03237 for( unsigned int i = 0; i < vertex_indices.size(); i++ ) 03238 side_verts.insert( verts[vertex_indices[i]] ); 03239 03240 // now look for an entity of the correct type 03241 // use const_cast here 'cuz we're in a const function and we're passing 'false' for 03242 // create_if_missing, so we know we won't change anything 03243 result = ( const_cast< Core* >( this ) )->get_adjacencies( side_verts, dim, false, target_ents ); 03244 if( MB_SUCCESS != result && MB_MULTIPLE_ENTITIES_FOUND != result ) return result; 03245 03246 if( !target_ents.empty() && TYPE_FROM_HANDLE( *( target_ents.begin() ) ) != MBVERTEX && 03247 TYPE_FROM_HANDLE( *( target_ents.begin() ) ) != 03248 CN::mConnectivityMap[source_type][dim - 1].target_type[sd_number] ) 03249 return MB_ENTITY_NOT_FOUND; 03250 03251 if( !target_ents.empty() ) target_entity = *( target_ents.begin() ); 03252 03253 return result; 03254 } 03255 03256 //-------------------------Set Functions---------------------// 03257 03258 ErrorCode Core::create_meshset( const unsigned int setoptions, EntityHandle& ms_handle, int ) 03259 { 03260 return sequence_manager()->create_mesh_set( setoptions, ms_handle ); 03261 } 03262 03263 ErrorCode Core::get_meshset_options( const EntityHandle ms_handle, unsigned int& setoptions ) const 03264 { 03265 if( !ms_handle ) 03266 { // root set 03267 setoptions = MESHSET_SET | MESHSET_TRACK_OWNER; 03268 return MB_SUCCESS; 03269 } 03270 03271 const MeshSet* set = get_mesh_set( sequence_manager(), ms_handle ); 03272 if( !set ) return MB_ENTITY_NOT_FOUND; 03273 03274 setoptions = set->flags(); 03275 return MB_SUCCESS; 03276 } 03277 03278 ErrorCode Core::set_meshset_options( const EntityHandle ms_handle, const unsigned int setoptions ) 03279 { 03280 MeshSet* set = get_mesh_set( sequence_manager(), ms_handle ); 03281 if( !set ) return MB_ENTITY_NOT_FOUND; 03282 03283 return set->set_flags( setoptions, ms_handle, a_entity_factory() ); 03284 } 03285 03286 ErrorCode Core::clear_meshset( const EntityHandle* ms_handles, const int num_meshsets ) 03287 { 03288 ErrorCode result = MB_SUCCESS; 03289 for( int i = 0; i < num_meshsets; ++i ) 03290 { 03291 MeshSet* set = get_mesh_set( sequence_manager(), ms_handles[i] ); 03292 if( set ) 03293 set->clear( ms_handles[i], a_entity_factory() ); 03294 else 03295 result = MB_ENTITY_NOT_FOUND; 03296 } 03297 03298 return result; 03299 } 03300 03301 ErrorCode Core::clear_meshset( const Range& ms_handles ) 03302 { 03303 ErrorCode result = MB_SUCCESS; 03304 for( Range::iterator i = ms_handles.begin(); i != ms_handles.end(); ++i ) 03305 { 03306 MeshSet* set = get_mesh_set( sequence_manager(), *i ); 03307 if( set ) 03308 set->clear( *i, a_entity_factory() ); 03309 else 03310 result = MB_ENTITY_NOT_FOUND; 03311 } 03312 03313 return result; 03314 } 03315 03316 ErrorCode Core::subtract_meshset( EntityHandle meshset1, const EntityHandle meshset2 ) 03317 { 03318 MeshSet* set1 = get_mesh_set( sequence_manager(), meshset1 ); 03319 MeshSet* set2 = get_mesh_set( sequence_manager(), meshset2 ); 03320 if( !set1 || !set2 ) return MB_ENTITY_NOT_FOUND; 03321 03322 return set1->subtract( set2, meshset1, a_entity_factory() ); 03323 } 03324 03325 ErrorCode Core::intersect_meshset( EntityHandle meshset1, const EntityHandle meshset2 ) 03326 { 03327 MeshSet* set1 = get_mesh_set( sequence_manager(), meshset1 ); 03328 MeshSet* set2 = get_mesh_set( sequence_manager(), meshset2 ); 03329 if( !set1 || !set2 ) return MB_ENTITY_NOT_FOUND; 03330 03331 return set1->intersect( set2, meshset1, a_entity_factory() ); 03332 } 03333 03334 ErrorCode Core::unite_meshset( EntityHandle meshset1, const EntityHandle meshset2 ) 03335 { 03336 MeshSet* set1 = get_mesh_set( sequence_manager(), meshset1 ); 03337 MeshSet* set2 = get_mesh_set( sequence_manager(), meshset2 ); 03338 if( !set1 || !set2 ) return MB_ENTITY_NOT_FOUND; 03339 03340 return set1->unite( set2, meshset1, a_entity_factory() ); 03341 } 03342 03343 ErrorCode Core::add_entities( EntityHandle meshset, const Range& entities ) 03344 { 03345 MeshSet* set = get_mesh_set( sequence_manager(), meshset ); 03346 if( set ) 03347 return set->add_entities( entities, meshset, a_entity_factory() ); 03348 else 03349 return MB_ENTITY_NOT_FOUND; 03350 } 03351 03352 ErrorCode Core::add_entities( EntityHandle meshset, const EntityHandle* entities, const int num_entities ) 03353 { 03354 MeshSet* set = get_mesh_set( sequence_manager(), meshset ); 03355 if( set ) 03356 return set->add_entities( entities, num_entities, meshset, a_entity_factory() ); 03357 else 03358 return MB_ENTITY_NOT_FOUND; 03359 } 03360 03361 //! remove a range of entities from a meshset 03362 ErrorCode Core::remove_entities( EntityHandle meshset, const Range& entities ) 03363 { 03364 MeshSet* set = get_mesh_set( sequence_manager(), meshset ); 03365 if( set ) 03366 return set->remove_entities( entities, meshset, a_entity_factory() ); 03367 else 03368 return MB_ENTITY_NOT_FOUND; 03369 } 03370 03371 //! remove a vector of entities from a meshset 03372 ErrorCode Core::remove_entities( EntityHandle meshset, const EntityHandle* entities, const int num_entities ) 03373 { 03374 MeshSet* set = get_mesh_set( sequence_manager(), meshset ); 03375 if( set ) 03376 return set->remove_entities( entities, num_entities, meshset, a_entity_factory() ); 03377 else 03378 return MB_ENTITY_NOT_FOUND; 03379 } 03380 03381 //! return true if all entities are contained in set 03382 bool Core::contains_entities( EntityHandle meshset, 03383 const EntityHandle* entities, 03384 int num_entities, 03385 const int operation_type ) 03386 { 03387 if( !meshset ) // root 03388 return true; 03389 else if( MeshSet* set = get_mesh_set( sequence_manager(), meshset ) ) 03390 return set->contains_entities( entities, num_entities, operation_type ); 03391 else 03392 return false; 03393 } 03394 03395 // replace entities in a meshset 03396 ErrorCode Core::replace_entities( EntityHandle meshset, 03397 const EntityHandle* old_entities, 03398 const EntityHandle* new_entities, 03399 int num_entities ) 03400 { 03401 MeshSet* set = get_mesh_set( sequence_manager(), meshset ); 03402 if( set ) 03403 return set->replace_entities( meshset, old_entities, new_entities, num_entities, a_entity_factory() ); 03404 else 03405 return MB_ENTITY_NOT_FOUND; 03406 } 03407 03408 ErrorCode Core::get_parent_meshsets( const EntityHandle meshset, 03409 std::vector< EntityHandle >& parents, 03410 const int num_hops ) const 03411 { 03412 if( 0 == meshset ) return MB_ENTITY_NOT_FOUND; 03413 03414 const EntitySequence* seq; 03415 ErrorCode rval = sequence_manager()->find( meshset, seq ); 03416 if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND; 03417 const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq ); 03418 03419 return mseq->get_parents( sequence_manager(), meshset, parents, num_hops ); 03420 } 03421 03422 ErrorCode Core::get_parent_meshsets( const EntityHandle meshset, Range& parents, const int num_hops ) const 03423 { 03424 if( 0 == meshset ) return MB_ENTITY_NOT_FOUND; 03425 03426 std::vector< EntityHandle > parent_vec; 03427 ErrorCode result = get_parent_meshsets( meshset, parent_vec, num_hops );MB_CHK_ERR( result ); 03428 std::sort( parent_vec.begin(), parent_vec.end() ); 03429 std::copy( parent_vec.rbegin(), parent_vec.rend(), range_inserter( parents ) ); 03430 return MB_SUCCESS; 03431 } 03432 03433 ErrorCode Core::get_child_meshsets( const EntityHandle meshset, 03434 std::vector< EntityHandle >& children, 03435 const int num_hops ) const 03436 { 03437 if( 0 == meshset ) return MB_ENTITY_NOT_FOUND; 03438 03439 const EntitySequence* seq; 03440 ErrorCode rval = sequence_manager()->find( meshset, seq ); 03441 if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND; 03442 const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq ); 03443 03444 return mseq->get_children( sequence_manager(), meshset, children, num_hops ); 03445 } 03446 03447 ErrorCode Core::get_child_meshsets( const EntityHandle meshset, Range& children, const int num_hops ) const 03448 { 03449 if( 0 == meshset ) return MB_ENTITY_NOT_FOUND; 03450 03451 std::vector< EntityHandle > child_vec; 03452 ErrorCode result = get_child_meshsets( meshset, child_vec, num_hops );MB_CHK_ERR( result ); 03453 std::sort( child_vec.begin(), child_vec.end() ); 03454 std::copy( child_vec.rbegin(), child_vec.rend(), range_inserter( children ) ); 03455 return MB_SUCCESS; 03456 } 03457 03458 ErrorCode Core::get_contained_meshsets( const EntityHandle meshset, 03459 std::vector< EntityHandle >& children, 03460 const int num_hops ) const 03461 { 03462 if( 0 == meshset ) 03463 { 03464 return get_entities_by_type( meshset, MBENTITYSET, children ); 03465 } 03466 03467 const EntitySequence* seq; 03468 ErrorCode rval = sequence_manager()->find( meshset, seq ); 03469 if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND; 03470 const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq ); 03471 03472 return mseq->get_contained_sets( sequence_manager(), meshset, children, num_hops ); 03473 } 03474 03475 ErrorCode Core::get_contained_meshsets( const EntityHandle meshset, Range& children, const int num_hops ) const 03476 { 03477 if( 0 == meshset ) 03478 { 03479 return get_entities_by_type( meshset, MBENTITYSET, children ); 03480 } 03481 03482 std::vector< EntityHandle > child_vec; 03483 ErrorCode result = get_contained_meshsets( meshset, child_vec, num_hops );MB_CHK_ERR( result ); 03484 std::sort( child_vec.begin(), child_vec.end() ); 03485 std::copy( child_vec.rbegin(), child_vec.rend(), range_inserter( children ) ); 03486 return MB_SUCCESS; 03487 } 03488 03489 ErrorCode Core::num_parent_meshsets( const EntityHandle meshset, int* number, const int num_hops ) const 03490 { 03491 if( 0 == meshset ) return MB_ENTITY_NOT_FOUND; 03492 03493 const EntitySequence* seq; 03494 ErrorCode rval = sequence_manager()->find( meshset, seq ); 03495 if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND; 03496 const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq ); 03497 03498 return mseq->num_parents( sequence_manager(), meshset, *number, num_hops ); 03499 } 03500 03501 ErrorCode Core::num_child_meshsets( const EntityHandle meshset, int* number, const int num_hops ) const 03502 { 03503 if( 0 == meshset ) return MB_ENTITY_NOT_FOUND; 03504 03505 const EntitySequence* seq; 03506 ErrorCode rval = sequence_manager()->find( meshset, seq ); 03507 if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND; 03508 const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq ); 03509 03510 return mseq->num_children( sequence_manager(), meshset, *number, num_hops ); 03511 } 03512 03513 ErrorCode Core::num_contained_meshsets( const EntityHandle meshset, int* number, const int num_hops ) const 03514 { 03515 if( 0 == meshset ) 03516 { 03517 return get_number_entities_by_type( 0, MBENTITYSET, *number ); 03518 } 03519 03520 const EntitySequence* seq; 03521 ErrorCode rval = sequence_manager()->find( meshset, seq ); 03522 if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND; 03523 const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq ); 03524 03525 return mseq->num_contained_sets( sequence_manager(), meshset, *number, num_hops ); 03526 } 03527 03528 ErrorCode Core::add_parent_meshset( EntityHandle meshset, const EntityHandle parent_meshset ) 03529 { 03530 MeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset ); 03531 MeshSet* parent_ptr = get_mesh_set( sequence_manager(), parent_meshset ); 03532 if( !set_ptr || !parent_ptr ) return MB_ENTITY_NOT_FOUND; 03533 03534 set_ptr->add_parent( parent_meshset ); 03535 return MB_SUCCESS; 03536 } 03537 03538 ErrorCode Core::add_parent_meshsets( EntityHandle meshset, const EntityHandle* parents, int count ) 03539 { 03540 MeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset ); 03541 if( !set_ptr ) return MB_ENTITY_NOT_FOUND; 03542 03543 for( int i = 0; i < count; ++i ) 03544 if( !get_mesh_set( sequence_manager(), parents[i] ) ) return MB_ENTITY_NOT_FOUND; 03545 03546 for( int i = 0; i < count; ++i ) 03547 set_ptr->add_parent( parents[i] ); 03548 return MB_SUCCESS; 03549 } 03550 03551 ErrorCode Core::add_child_meshset( EntityHandle meshset, const EntityHandle child_meshset ) 03552 { 03553 MeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset ); 03554 MeshSet* child_ptr = get_mesh_set( sequence_manager(), child_meshset ); 03555 if( !set_ptr || !child_ptr ) return MB_ENTITY_NOT_FOUND; 03556 03557 set_ptr->add_child( child_meshset ); 03558 return MB_SUCCESS; 03559 } 03560 03561 ErrorCode Core::add_child_meshsets( EntityHandle meshset, const EntityHandle* children, int count ) 03562 { 03563 MeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset ); 03564 if( !set_ptr ) return MB_ENTITY_NOT_FOUND; 03565 03566 for( int i = 0; i < count; ++i ) 03567 if( !get_mesh_set( sequence_manager(), children[i] ) ) return MB_ENTITY_NOT_FOUND; 03568 03569 for( int i = 0; i < count; ++i ) 03570 set_ptr->add_child( children[i] ); 03571 return MB_SUCCESS; 03572 } 03573 03574 ErrorCode Core::add_parent_child( EntityHandle parent, EntityHandle child ) 03575 { 03576 MeshSet* parent_ptr = get_mesh_set( sequence_manager(), parent ); 03577 MeshSet* child_ptr = get_mesh_set( sequence_manager(), child ); 03578 if( !parent_ptr || !child_ptr ) return MB_ENTITY_NOT_FOUND; 03579 03580 parent_ptr->add_child( child ); 03581 child_ptr->add_parent( parent ); 03582 return MB_SUCCESS; 03583 } 03584 03585 ErrorCode Core::remove_parent_child( EntityHandle parent, EntityHandle child ) 03586 { 03587 MeshSet* parent_ptr = get_mesh_set( sequence_manager(), parent ); 03588 MeshSet* child_ptr = get_mesh_set( sequence_manager(), child ); 03589 if( !parent_ptr || !child_ptr ) return MB_ENTITY_NOT_FOUND; 03590 03591 parent_ptr->remove_child( child ); 03592 child_ptr->remove_parent( parent ); 03593 return MB_SUCCESS; 03594 } 03595 03596 ErrorCode Core::remove_parent_meshset( EntityHandle meshset, const EntityHandle parent_meshset ) 03597 { 03598 MeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset ); 03599 if( !set_ptr ) return MB_ENTITY_NOT_FOUND; 03600 set_ptr->remove_parent( parent_meshset ); 03601 return MB_SUCCESS; 03602 } 03603 03604 ErrorCode Core::remove_child_meshset( EntityHandle meshset, const EntityHandle child_meshset ) 03605 { 03606 MeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset ); 03607 if( !set_ptr ) return MB_ENTITY_NOT_FOUND; 03608 set_ptr->remove_child( child_meshset ); 03609 return MB_SUCCESS; 03610 } 03611 03612 ErrorCode Core::get_last_error( std::string& info ) const 03613 { 03614 MBErrorHandler_GetLastError( info ); 03615 return MB_SUCCESS; 03616 } 03617 03618 std::string Core::get_error_string( const ErrorCode code ) const 03619 { 03620 return (unsigned)code <= (unsigned)MB_FAILURE ? ErrorCodeStr[code] : "INVALID ERROR CODE"; 03621 } 03622 03623 void Core::print( const EntityHandle ms_handle, const char* prefix, bool first_call ) const 03624 { 03625 // get the entities 03626 Range entities; 03627 03628 if( 0 != ms_handle ) 03629 { 03630 get_entities_by_handle( ms_handle, entities ); 03631 std::cout << prefix << "MBENTITYSET " << ID_FROM_HANDLE( ms_handle ) << std::endl; 03632 } 03633 else 03634 { 03635 get_entities_by_dimension( 0, 3, entities ); 03636 if( entities.empty() ) get_entities_by_dimension( 0, 2, entities ); 03637 if( entities.empty() ) get_entities_by_dimension( 0, 1, entities ); 03638 get_entities_by_dimension( 0, 0, entities ); 03639 get_entities_by_type( 0, MBENTITYSET, entities ); 03640 std::cout << prefix << "--: " << std::endl; 03641 } 03642 03643 std::string indent_prefix = prefix; 03644 indent_prefix += " "; 03645 entities.print( indent_prefix.c_str() ); 03646 03647 if( !first_call || !ms_handle ) return; 03648 03649 // print parent/children 03650 Range temp; 03651 this->get_parent_meshsets( ms_handle, temp ); 03652 std::cout << " Parent sets: "; 03653 if( temp.empty() ) 03654 std::cout << "(none)" << std::endl; 03655 else 03656 { 03657 for( Range::iterator rit = temp.begin(); rit != temp.end(); ++rit ) 03658 { 03659 if( rit != temp.begin() ) std::cout << ", "; 03660 std::cout << ID_FROM_HANDLE( *rit ); 03661 } 03662 std::cout << std::endl; 03663 } 03664 03665 temp.clear(); 03666 this->get_child_meshsets( ms_handle, temp ); 03667 std::cout << " Child sets: "; 03668 if( temp.empty() ) 03669 std::cout << "(none)" << std::endl; 03670 else 03671 { 03672 for( Range::iterator rit = temp.begin(); rit != temp.end(); ++rit ) 03673 { 03674 if( rit != temp.begin() ) std::cout << ", "; 03675 std::cout << ID_FROM_HANDLE( *rit ); 03676 } 03677 std::cout << std::endl; 03678 } 03679 03680 // print all sparse tags 03681 print_entity_tags( indent_prefix, ms_handle, MB_TAG_SPARSE ); 03682 } 03683 03684 ErrorCode Core::print_entity_tags( std::string indent_prefix, const EntityHandle handle, TagType tp ) const 03685 { 03686 std::vector< Tag > set_tags; 03687 ErrorCode result = this->tag_get_tags_on_entity( handle, set_tags ); 03688 std::cout << indent_prefix << ( tp == MB_TAG_SPARSE ? "Sparse tags:" : "Dense tags:" ) << std::endl; 03689 indent_prefix += " "; 03690 03691 for( std::vector< Tag >::iterator vit = set_tags.begin(); vit != set_tags.end(); ++vit ) 03692 { 03693 TagType this_type; 03694 result = this->tag_get_type( *vit, this_type ); 03695 if( MB_SUCCESS != result || tp != this_type ) continue; 03696 DataType this_data_type; 03697 result = this->tag_get_data_type( *vit, this_data_type ); 03698 if( MB_SUCCESS != result ) continue; 03699 int this_size; 03700 result = this->tag_get_length( *vit, this_size ); 03701 if( MB_SUCCESS != result ) continue; 03702 // use double since this is largest single-valued tag 03703 std::vector< double > dbl_vals( this_size ); 03704 std::vector< int > int_vals( this_size ); 03705 std::vector< EntityHandle > hdl_vals( this_size ); 03706 std::string tag_name; 03707 result = this->tag_get_name( *vit, tag_name ); 03708 if( MB_SUCCESS != result ) continue; 03709 switch( this_data_type ) 03710 { 03711 case MB_TYPE_INTEGER: 03712 result = this->tag_get_data( *vit, &handle, 1, &int_vals[0] ); 03713 if( MB_SUCCESS != result ) continue; 03714 std::cout << indent_prefix << tag_name << " = "; 03715 if( this_size < 10 ) 03716 for( int i = 0; i < this_size; i++ ) 03717 std::cout << int_vals[i] << " "; 03718 else 03719 std::cout << int_vals[0] << "... (mult values)"; 03720 std::cout << std::endl; 03721 break; 03722 case MB_TYPE_DOUBLE: 03723 result = this->tag_get_data( *vit, &handle, 1, &dbl_vals[0] ); 03724 if( MB_SUCCESS != result ) continue; 03725 std::cout << indent_prefix << tag_name << " = "; 03726 if( this_size < 10 ) 03727 for( int i = 0; i < this_size; i++ ) 03728 std::cout << dbl_vals[i] << " "; 03729 else 03730 std::cout << dbl_vals[0] << "... (mult values)"; 03731 std::cout << std::endl; 03732 break; 03733 case MB_TYPE_HANDLE: 03734 result = this->tag_get_data( *vit, &handle, 1, &hdl_vals[0] ); 03735 if( MB_SUCCESS != result ) continue; 03736 std::cout << indent_prefix << tag_name << " = "; 03737 if( this_size < 10 ) 03738 for( int i = 0; i < this_size; i++ ) 03739 std::cout << hdl_vals[i] << " "; 03740 else 03741 std::cout << hdl_vals[0] << "... (mult values)"; 03742 std::cout << std::endl; 03743 break; 03744 case MB_TYPE_OPAQUE: 03745 if( NAME_TAG_SIZE == this_size ) 03746 { 03747 char dum_tag[NAME_TAG_SIZE]; 03748 result = this->tag_get_data( *vit, &handle, 1, &dum_tag ); 03749 if( MB_SUCCESS != result ) continue; 03750 // insert NULL just in case there isn't one 03751 dum_tag[NAME_TAG_SIZE - 1] = '\0'; 03752 std::cout << indent_prefix << tag_name << " = " << dum_tag << std::endl; 03753 } 03754 break; 03755 case MB_TYPE_BIT: 03756 break; 03757 } 03758 } 03759 03760 return MB_SUCCESS; 03761 } 03762 03763 ErrorCode Core::check_adjacencies() 03764 { 03765 // run through all entities, checking adjacencies and reverse-evaluating them 03766 Range all_ents; 03767 ErrorCode result = get_entities_by_handle( 0, all_ents );MB_CHK_ERR( result ); 03768 03769 for( Range::iterator rit = all_ents.begin(); rit != all_ents.end(); ++rit ) 03770 { 03771 result = check_adjacencies( &( *rit ), 1 );MB_CHK_ERR( result ); 03772 } 03773 03774 return MB_SUCCESS; 03775 } 03776 03777 ErrorCode Core::check_adjacencies( const EntityHandle* ents, int num_ents ) 03778 { 03779 03780 ErrorCode result = MB_SUCCESS, tmp_result; 03781 std::ostringstream oss; 03782 03783 for( int i = 0; i < num_ents; i++ ) 03784 { 03785 EntityHandle this_ent = ents[i]; 03786 std::ostringstream ent_str; 03787 ent_str << CN::EntityTypeName( TYPE_FROM_HANDLE( this_ent ) ) << " " << ID_FROM_HANDLE( this_ent ) << ": "; 03788 int this_dim = dimension_from_handle( this_ent ); 03789 03790 if( !is_valid( this_ent ) ) 03791 { 03792 std::cerr << ent_str.str() << "Not a valid entity." << std::endl; 03793 result = MB_FAILURE; 03794 } 03795 03796 else 03797 { 03798 if( TYPE_FROM_HANDLE( this_ent ) == MBENTITYSET ) continue; 03799 03800 // get adjacencies for this entity 03801 Range adjs; 03802 for( int dim = 0; dim <= 3; dim++ ) 03803 { 03804 if( dim == this_dim ) continue; 03805 tmp_result = get_adjacencies( &this_ent, 1, dim, false, adjs, Interface::UNION ); 03806 if( MB_SUCCESS != tmp_result ) 03807 { 03808 oss << ent_str.str() << "Failed to get adjacencies for dimension " << dim << "." << std::endl; 03809 result = tmp_result; 03810 } 03811 } 03812 if( !oss.str().empty() ) 03813 { 03814 std::cerr << oss.str(); 03815 oss.str( "" ); 03816 } 03817 03818 // now check and reverse-evaluate them 03819 for( Range::iterator rit = adjs.begin(); rit != adjs.end(); ++rit ) 03820 { 03821 EntitySequence* seq = 0; 03822 tmp_result = sequence_manager()->find( *rit, seq ); 03823 if( seq == 0 || tmp_result != MB_SUCCESS ) 03824 { 03825 oss << ent_str.str() << "Adjacent entity " << CN::EntityTypeName( TYPE_FROM_HANDLE( *rit ) ) << " " 03826 << ID_FROM_HANDLE( *rit ) << " is invalid." << std::endl; 03827 result = tmp_result; 03828 } 03829 else 03830 { 03831 Range rev_adjs; 03832 tmp_result = get_adjacencies( &( *rit ), 1, this_dim, false, rev_adjs ); 03833 if( MB_SUCCESS != tmp_result ) 03834 { 03835 oss << ent_str.str() << "Failed to get reverse adjacency from " 03836 << CN::EntityTypeName( TYPE_FROM_HANDLE( *rit ) ) << " " << ID_FROM_HANDLE( *rit ); 03837 if( MB_MULTIPLE_ENTITIES_FOUND == tmp_result ) 03838 oss << " (MULTIPLE)" << std::endl; 03839 else 03840 oss << " (" << tmp_result << ")" << std::endl; 03841 result = tmp_result; 03842 } 03843 else if( rev_adjs.find( this_ent ) == rev_adjs.end() ) 03844 { 03845 oss << ent_str.str() << "Failed to find adjacency to this entity from " 03846 << CN::EntityTypeName( TYPE_FROM_HANDLE( *rit ) ) << " " << ID_FROM_HANDLE( *rit ) << "." 03847 << std::endl; 03848 result = tmp_result; 03849 } 03850 } 03851 if( !oss.str().empty() ) 03852 { 03853 std::cerr << oss.str(); 03854 oss.str( "" ); 03855 } 03856 } 03857 } 03858 } 03859 03860 return result; 03861 } 03862 03863 bool Core::is_valid( const EntityHandle this_ent ) const 03864 { 03865 const EntitySequence* seq = 0; 03866 ErrorCode result = sequence_manager()->find( this_ent, seq ); 03867 return seq != 0 && result == MB_SUCCESS; 03868 } 03869 03870 ErrorCode Core::create_set_iterator( EntityHandle meshset, 03871 EntityType ent_type, 03872 int ent_dim, 03873 int chunk_size, 03874 bool check_valid, 03875 SetIterator*& set_iter ) 03876 { 03877 // check the type of set 03878 unsigned int setoptions; 03879 ErrorCode rval = MB_SUCCESS; 03880 if( meshset ) 03881 { 03882 rval = get_meshset_options( meshset, setoptions );MB_CHK_ERR( rval ); 03883 } 03884 03885 if( !meshset || ( setoptions & MESHSET_SET ) ) 03886 set_iter = new( std::nothrow ) RangeSetIterator( this, meshset, chunk_size, ent_type, ent_dim, check_valid ); 03887 else 03888 set_iter = new( std::nothrow ) VectorSetIterator( this, meshset, chunk_size, ent_type, ent_dim, check_valid ); 03889 03890 setIterators.push_back( set_iter ); 03891 return MB_SUCCESS; 03892 } 03893 03894 /** \brief Remove the set iterator from the instance's list 03895 * This function is called from the SetIterator destructor, and should not be called directly 03896 * from anywhere else. 03897 * \param set_iter Set iterator being removed 03898 */ 03899 ErrorCode Core::remove_set_iterator( SetIterator* set_iter ) 03900 { 03901 std::vector< SetIterator* >::iterator vit = std::find( setIterators.begin(), setIterators.end(), set_iter ); 03902 if( vit == setIterators.end() ) 03903 { 03904 MB_SET_ERR( MB_FAILURE, "Didn't find that iterator" ); 03905 } 03906 03907 setIterators.erase( vit ); 03908 03909 return MB_SUCCESS; 03910 } 03911 03912 /** \brief Get all set iterators associated with the set passed in 03913 * \param meshset Meshset for which iterators are requested 03914 * \param set_iters Set iterators for the set 03915 */ 03916 ErrorCode Core::get_set_iterators( EntityHandle meshset, std::vector< SetIterator* >& set_iters ) 03917 { 03918 for( std::vector< SetIterator* >::const_iterator vit = setIterators.begin(); vit != setIterators.end(); ++vit ) 03919 if( ( *vit )->ent_set() == meshset ) set_iters.push_back( *vit ); 03920 return MB_SUCCESS; 03921 } 03922 03923 void Core::estimated_memory_use_internal( const Range* ents, 03924 type_memstorage* total_storage, 03925 type_memstorage* total_amortized_storage, 03926 type_memstorage* entity_storage, 03927 type_memstorage* amortized_entity_storage, 03928 type_memstorage* adjacency_storage, 03929 type_memstorage* amortized_adjacency_storage, 03930 const Tag* tag_array, 03931 unsigned num_tags, 03932 type_memstorage* tag_storage, 03933 type_memstorage* amortized_tag_storage ) 03934 { 03935 // Figure out which values we need to calculate 03936 type_memstorage i_entity_storage, ia_entity_storage, i_adjacency_storage, ia_adjacency_storage, i_tag_storage, 03937 ia_tag_storage; 03938 type_memstorage *total_tag_storage = 0, *amortized_total_tag_storage = 0; 03939 if( !tag_array ) 03940 { 03941 total_tag_storage = tag_storage; 03942 amortized_total_tag_storage = amortized_tag_storage; 03943 } 03944 if( total_storage || total_amortized_storage ) 03945 { 03946 if( !entity_storage ) entity_storage = &i_entity_storage; 03947 if( !amortized_entity_storage ) amortized_entity_storage = &ia_entity_storage; 03948 if( !adjacency_storage ) adjacency_storage = &i_adjacency_storage; 03949 if( !amortized_adjacency_storage ) amortized_adjacency_storage = &ia_adjacency_storage; 03950 } 03951 else 03952 { 03953 if( entity_storage || amortized_entity_storage ) 03954 { 03955 if( !amortized_entity_storage ) 03956 amortized_entity_storage = &ia_entity_storage; 03957 else if( !entity_storage ) 03958 entity_storage = &i_entity_storage; 03959 } 03960 if( adjacency_storage || amortized_adjacency_storage ) 03961 { 03962 if( !amortized_adjacency_storage ) 03963 amortized_adjacency_storage = &ia_adjacency_storage; 03964 else if( !adjacency_storage ) 03965 adjacency_storage = &i_adjacency_storage; 03966 } 03967 } 03968 if( !total_tag_storage && total_storage ) total_tag_storage = &i_tag_storage; 03969 if( !amortized_total_tag_storage && total_amortized_storage ) amortized_total_tag_storage = &ia_tag_storage; 03970 03971 // get entity storage 03972 if( amortized_entity_storage ) 03973 { 03974 if( ents ) 03975 sequenceManager->get_memory_use( *ents, *entity_storage, *amortized_entity_storage ); 03976 else 03977 sequenceManager->get_memory_use( *entity_storage, *amortized_entity_storage ); 03978 } 03979 03980 // get adjacency storage 03981 if( amortized_adjacency_storage ) 03982 { 03983 if( ents ) 03984 aEntityFactory->get_memory_use( *ents, *adjacency_storage, *amortized_adjacency_storage ); 03985 else 03986 #ifdef MOAB_HAVE_AHF 03987 ahfRep->get_memory_use( *adjacency_storage, *amortized_adjacency_storage ); 03988 #else 03989 aEntityFactory->get_memory_use( *adjacency_storage, *amortized_adjacency_storage ); 03990 #endif 03991 } 03992 03993 // get storage for requested list of tags 03994 if( tag_array ) 03995 { 03996 for( unsigned i = 0; i < num_tags; ++i ) 03997 { 03998 if( !valid_tag_handle( tag_array[i] ) ) continue; 03999 04000 unsigned long total = 0, per_ent = 0; 04001 tag_array[i]->get_memory_use( sequenceManager, total, per_ent ); 04002 04003 if( ents ) 04004 { 04005 size_t count = 0, count2 = 0; 04006 tag_array[i]->num_tagged_entities( sequenceManager, count, MBMAXTYPE, ents ); 04007 if( tag_storage ) tag_storage[i] = count * per_ent; 04008 if( amortized_tag_storage ) 04009 { 04010 tag_array[i]->num_tagged_entities( sequenceManager, count2 ); 04011 if( count2 ) 04012 amortized_tag_storage[i] = static_cast< type_memstorage >( total * count * 1.0 / count2 ); 04013 } 04014 } 04015 else 04016 { 04017 size_t count = 0; 04018 if( tag_storage ) 04019 { 04020 tag_array[i]->num_tagged_entities( sequenceManager, count ); 04021 tag_storage[i] = count * per_ent; 04022 } 04023 if( amortized_tag_storage ) amortized_tag_storage[i] = total; 04024 } 04025 } 04026 } 04027 04028 // get storage for all tags 04029 if( total_tag_storage || amortized_total_tag_storage ) 04030 { 04031 if( amortized_total_tag_storage ) *amortized_total_tag_storage = 0; 04032 if( total_tag_storage ) *total_tag_storage = 0; 04033 04034 std::vector< Tag > tags; 04035 tag_get_tags( tags ); 04036 for( std::list< TagInfo* >::const_iterator i = tagList.begin(); i != tagList.end(); ++i ) 04037 { 04038 unsigned long total = 0, per_ent = 0; 04039 ( *i )->get_memory_use( sequenceManager, total, per_ent ); 04040 04041 if( ents ) 04042 { 04043 size_t count = 0, count2 = 0; 04044 ( *i )->num_tagged_entities( sequenceManager, count, MBMAXTYPE, ents ); 04045 if( total_tag_storage ) *total_tag_storage += count * per_ent; 04046 if( amortized_total_tag_storage ) 04047 { 04048 ( *i )->num_tagged_entities( sequenceManager, count2 ); 04049 if( count2 ) 04050 *amortized_total_tag_storage += static_cast< type_memstorage >( total * count * 1.0 / count2 ); 04051 } 04052 } 04053 else 04054 { 04055 size_t count = 0; 04056 if( total_tag_storage ) 04057 { 04058 ( *i )->num_tagged_entities( sequenceManager, count ); 04059 *total_tag_storage += count * per_ent; 04060 } 04061 if( amortized_total_tag_storage ) *amortized_total_tag_storage += total; 04062 } 04063 } 04064 } 04065 04066 // calculate totals 04067 if( total_storage ) *total_storage = *entity_storage + *adjacency_storage + *total_tag_storage; 04068 04069 if( total_amortized_storage ) 04070 *total_amortized_storage = 04071 *amortized_entity_storage + *amortized_adjacency_storage + *amortized_total_tag_storage; 04072 } 04073 04074 void Core::estimated_memory_use( const EntityHandle* ent_array, 04075 unsigned long num_ents, 04076 type_memstorage* total_storage, 04077 type_memstorage* total_amortized_storage, 04078 type_memstorage* entity_storage, 04079 type_memstorage* amortized_entity_storage, 04080 type_memstorage* adjacency_storage, 04081 type_memstorage* amortized_adjacency_storage, 04082 const Tag* tag_array, 04083 unsigned num_tags, 04084 type_memstorage* tag_storage, 04085 type_memstorage* amortized_tag_storage ) 04086 { 04087 Range range; 04088 04089 // If non-empty entity list, call range version of function 04090 if( ent_array ) 04091 { 04092 if( num_ents > 20 ) 04093 { 04094 std::vector< EntityHandle > list( num_ents ); 04095 std::copy( ent_array, ent_array + num_ents, list.begin() ); 04096 std::sort( list.begin(), list.end() ); 04097 Range::iterator j = range.begin(); 04098 for( std::vector< EntityHandle >::reverse_iterator i = list.rbegin(); i != list.rend(); ++i ) 04099 j = range.insert( j, *i, *i ); 04100 } 04101 else 04102 { 04103 std::copy( ent_array, ent_array + num_ents, range_inserter( range ) ); 04104 } 04105 } 04106 04107 estimated_memory_use_internal( ent_array ? &range : 0, total_storage, total_amortized_storage, entity_storage, 04108 amortized_entity_storage, adjacency_storage, amortized_adjacency_storage, tag_array, 04109 num_tags, tag_storage, amortized_tag_storage ); 04110 } 04111 04112 void Core::estimated_memory_use( const Range& ents, 04113 type_memstorage* total_storage, 04114 type_memstorage* total_amortized_storage, 04115 type_memstorage* entity_storage, 04116 type_memstorage* amortized_entity_storage, 04117 type_memstorage* adjacency_storage, 04118 type_memstorage* amortized_adjacency_storage, 04119 const Tag* tag_array, 04120 unsigned num_tags, 04121 type_memstorage* tag_storage, 04122 type_memstorage* amortized_tag_storage ) 04123 { 04124 estimated_memory_use_internal( &ents, total_storage, total_amortized_storage, entity_storage, 04125 amortized_entity_storage, adjacency_storage, amortized_adjacency_storage, tag_array, 04126 num_tags, tag_storage, amortized_tag_storage ); 04127 } 04128 04129 void Core::print_database() const 04130 { 04131 ErrorCode rval; 04132 TypeSequenceManager::const_iterator i; 04133 const TypeSequenceManager& verts = sequence_manager()->entity_map( MBVERTEX ); 04134 if( !verts.empty() ) 04135 printf( " Vertex ID X Y Z Adjacencies \n" 04136 " ---------- -------- -------- -------- -----------...\n" ); 04137 const EntityHandle* adj; 04138 int nadj; 04139 for( i = verts.begin(); i != verts.end(); ++i ) 04140 { 04141 const VertexSequence* seq = static_cast< const VertexSequence* >( *i ); 04142 printf( "(Sequence [%d,%d] in SequenceData [%d,%d])\n", (int)ID_FROM_HANDLE( seq->start_handle() ), 04143 (int)ID_FROM_HANDLE( seq->end_handle() ), (int)ID_FROM_HANDLE( seq->data()->start_handle() ), 04144 (int)ID_FROM_HANDLE( seq->data()->end_handle() ) ); 04145 04146 double c[3]; 04147 for( EntityHandle h = seq->start_handle(); h <= seq->end_handle(); ++h ) 04148 { 04149 rval = seq->get_coordinates( h, c ); 04150 if( MB_SUCCESS == rval ) 04151 printf( " %10d %8g %8g %8g", (int)ID_FROM_HANDLE( h ), c[0], c[1], c[2] ); 04152 else 04153 printf( " %10d < ERROR %4d >", (int)ID_FROM_HANDLE( h ), (int)rval ); 04154 04155 rval = a_entity_factory()->get_adjacencies( h, adj, nadj ); 04156 if( MB_SUCCESS != rval ) 04157 { 04158 printf( " <ERROR %d>\n", (int)rval ); 04159 continue; 04160 } 04161 EntityType pt = MBMAXTYPE; 04162 for( int j = 0; j < nadj; ++j ) 04163 { 04164 if( TYPE_FROM_HANDLE( adj[j] ) != pt ) 04165 { 04166 pt = TYPE_FROM_HANDLE( adj[j] ); 04167 printf( " %s", pt >= MBMAXTYPE ? "INVALID TYPE" : CN::EntityTypeName( pt ) ); 04168 } 04169 printf( " %d", (int)ID_FROM_HANDLE( adj[j] ) ); 04170 } 04171 printf( "\n" ); 04172 } 04173 } 04174 04175 for( EntityType t = MBEDGE; t < MBENTITYSET; ++t ) 04176 { 04177 const TypeSequenceManager& elems = sequence_manager()->entity_map( t ); 04178 if( elems.empty() ) continue; 04179 04180 int clen = 0; 04181 for( i = elems.begin(); i != elems.end(); ++i ) 04182 { 04183 int n = static_cast< const ElementSequence* >( *i )->nodes_per_element(); 04184 if( n > clen ) clen = n; 04185 } 04186 04187 clen *= 5; 04188 if( clen < (int)strlen( "Connectivity" ) ) clen = strlen( "Connectivity" ); 04189 std::vector< char > dashes( clen, '-' ); 04190 dashes.push_back( '\0' ); 04191 printf( " %7s ID %-*s Adjacencies\n", CN::EntityTypeName( t ), clen, "Connectivity" ); 04192 printf( " ---------- %s -----------...\n", &dashes[0] ); 04193 04194 std::vector< EntityHandle > storage; 04195 const EntityHandle* conn; 04196 int nconn; 04197 for( i = elems.begin(); i != elems.end(); ++i ) 04198 { 04199 const ElementSequence* seq = static_cast< const ElementSequence* >( *i ); 04200 printf( "(Sequence [%d,%d] in SequenceData [%d,%d])\n", (int)ID_FROM_HANDLE( seq->start_handle() ), 04201 (int)ID_FROM_HANDLE( seq->end_handle() ), (int)ID_FROM_HANDLE( seq->data()->start_handle() ), 04202 (int)ID_FROM_HANDLE( seq->data()->end_handle() ) ); 04203 04204 for( EntityHandle h = seq->start_handle(); h <= seq->end_handle(); ++h ) 04205 { 04206 printf( " %10d", (int)ID_FROM_HANDLE( h ) ); 04207 rval = get_connectivity( h, conn, nconn, false, &storage ); 04208 if( MB_SUCCESS != rval ) 04209 printf( " <ERROR %2d>%*s", (int)rval, clen - 10, "" ); 04210 else 04211 { 04212 for( int j = 0; j < nconn; ++j ) 04213 printf( " %4d", (int)ID_FROM_HANDLE( conn[j] ) ); 04214 printf( "%*s", clen - 5 * nconn, "" ); 04215 } 04216 04217 rval = a_entity_factory()->get_adjacencies( h, adj, nadj ); 04218 if( MB_SUCCESS != rval ) 04219 { 04220 printf( " <ERROR %d>\n", (int)rval ); 04221 continue; 04222 } 04223 EntityType pt = MBMAXTYPE; 04224 for( int j = 0; j < nadj; ++j ) 04225 { 04226 if( TYPE_FROM_HANDLE( adj[j] ) != pt ) 04227 { 04228 pt = TYPE_FROM_HANDLE( adj[j] ); 04229 printf( " %s", pt >= MBMAXTYPE ? "INVALID TYPE" : CN::EntityTypeName( pt ) ); 04230 } 04231 printf( " %d", (int)ID_FROM_HANDLE( adj[j] ) ); 04232 } 04233 printf( "\n" ); 04234 } 04235 } 04236 } 04237 } 04238 04239 ErrorCode Core::create_scd_sequence( const HomCoord& coord_min, 04240 const HomCoord& coord_max, 04241 EntityType entity_type, 04242 EntityID start_id_hint, 04243 EntityHandle& first_handle_out, 04244 EntitySequence*& sequence_out ) 04245 { 04246 // NR: Previously, the structured element sequences were created via direct call to 04247 // the sequence manager instead of using the same from the ScdInterface which 04248 // creates the associated scd bounding box after element sequence creation. 04249 04250 if( !scdInterface ) scdInterface = new ScdInterface( this ); 04251 ScdBox* newBox = NULL; 04252 ErrorCode rval = scdInterface->create_scd_sequence( coord_min, coord_max, entity_type, 04253 /*starting_id*/ (int)start_id_hint, newBox );MB_CHK_ERR( rval ); 04254 04255 if( MBVERTEX == entity_type ) 04256 first_handle_out = newBox->get_vertex( coord_min ); 04257 else 04258 first_handle_out = newBox->get_element( coord_min ); 04259 return sequence_manager()->find( first_handle_out, sequence_out ); 04260 } 04261 04262 ErrorCode Core::add_vsequence( EntitySequence* vert_seq, 04263 EntitySequence* elem_seq, 04264 const HomCoord& p1, 04265 const HomCoord& q1, 04266 const HomCoord& p2, 04267 const HomCoord& q2, 04268 const HomCoord& p3, 04269 const HomCoord& q3, 04270 bool bb_input, 04271 const HomCoord* bb_min, 04272 const HomCoord* bb_max ) 04273 { 04274 return sequence_manager()->add_vsequence( vert_seq, elem_seq, p1, q1, p2, q2, p3, q3, bb_input, bb_min, bb_max ); 04275 } 04276 04277 } // namespace moab