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