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