MOAB: Mesh Oriented datABase  (version 5.5.0)
iMesh_MOAB.cpp
Go to the documentation of this file.
1 #include "moab/MOABConfig.h"
2 #include "iMesh_extensions.h"
3 #include "moab/Core.hpp"
4 #include "moab/Range.hpp"
5 #include "moab/CN.hpp"
6 #include "moab/MeshTopoUtil.hpp"
7 #include "moab/ScdInterface.hpp"
8 #include "moab/FileOptions.hpp"
9 #include "iMesh_MOAB.hpp"
10 #include "MBIter.hpp"
11 #include "MBTagConventions.hpp"
12 #define IS_BUILDING_MB
13 #include "Internals.hpp"
14 #undef IS_BUILDING_MB
15 
16 #ifdef MOAB_HAVE_MPI
17 #include "moab_mpi.h"
18 #include "moab/ParallelComm.hpp"
19 #endif
20 
21 #define STRINGIFY_( X ) #X
22 #define STRINGIFY( X ) STRINGIFY_( X )
23 #ifdef MOAB_HAVE_UNORDERED_MAP
24 #include STRINGIFY( MOAB_HAVE_UNORDERED_MAP )
25 #else
26 #include <map>
27 #endif
28 
29 #include <iostream>
30 #include <cassert>
31 #include <cctype>
32 #include <cstring>
33 #include <cstdarg>
34 #include <cstdio>
35 #define MIN( a, b ) ( ( a ) < ( b ) ? ( a ) : ( b ) )
36 
37 #ifdef _WIN32
38 #define snprintf( A, B, C, D ) _snprintf( ( A ), ( B ), ( C ), ( D ) )
39 #endif
40 
41 static ErrorCode create_int_ents( MBiMesh* mbimesh, Range& from_ents, const EntityHandle* in_set = 0 );
42 #define HANDLE_ARRAY_PTR( array ) ( reinterpret_cast< EntityHandle* >( array ) )
43 #define CONST_HANDLE_ARRAY_PTR( array ) reinterpret_cast< const EntityHandle* >( array )
44 #define TAG_HANDLE( handle ) reinterpret_cast< Tag >( handle )
45 #define CONST_TAG_HANDLE( handle ) static_cast< const Tag >( handle )
46 #define ENTITY_HANDLE( handle ) reinterpret_cast< EntityHandle >( handle )
47 #define CONST_ENTITY_HANDLE( handle ) reinterpret_cast< const EntityHandle >( handle )
48 #define CAST_TO_VOID( ptr ) ( reinterpret_cast< void* >( ptr ) )
49 
50 // map from MB's entity type to TSTT's entity topology
52  iMesh_POINT, // MBVERTEX
53  iMesh_LINE_SEGMENT, // MBEDGE
54  iMesh_TRIANGLE, // MBTRI
55  iMesh_QUADRILATERAL, // MBQUAD
56  iMesh_POLYGON, // MBPOLYGON
57  iMesh_TETRAHEDRON, // MBTET
58  iMesh_PYRAMID, // MBPYRAMID
59  iMesh_PRISM, // MBPRISM
60  iMesh_ALL_TOPOLOGIES, // MBKNIFE
61  iMesh_HEXAHEDRON, // MBHEX
62  iMesh_POLYHEDRON, // MBPOLYHEDRON
63  iMesh_ALL_TOPOLOGIES, // MBENTITYSET
64  iMesh_ALL_TOPOLOGIES, // MBMAXTYPE
65 };
66 
67 // map from MB's entity type to TSTT's entity type
69  iBase_VERTEX, // MBVERTEX
70  iBase_EDGE, // MBEDGE
71  iBase_FACE, // MBTRI
72  iBase_FACE, // MBQUAD
73  iBase_FACE, // MBPOLYGON
74  iBase_REGION, // MBTET
75  iBase_REGION, // MBPYRAMID
76  iBase_REGION, // MBPRISM
77  iBase_REGION, // MBKNIFE
78  iBase_REGION, // MBHEX
79  iBase_REGION, // MBPOLYHEDRON
80  iBase_ALL_TYPES, // MBENTITYSET
81  iBase_ALL_TYPES // MBMAXTYPE
82 };
83 
84 // map to MB's entity type from TSTT's entity topology
87 
88 // map from TSTT's tag types to MOAB's
91 
92 // map from MOAB's tag types to tstt's
95 
96 const iBase_ErrorType iBase_ERROR_MAP[MB_FAILURE + 1] = {
97  iBase_SUCCESS, // MB_SUCCESS = 0,
98  iBase_INVALID_ENTITY_HANDLE, // MB_INDEX_OUT_OF_RANGE,
99  iBase_INVALID_ENTITY_TYPE, // MB_TYPE_OUT_OF_RANGE,
100  iBase_MEMORY_ALLOCATION_FAILED, // MB_MEMORY_ALLOCATION_FAILED,
101  iBase_INVALID_ENTITY_HANDLE, // MB_ENTITY_NOT_FOUND,
102  iBase_NOT_SUPPORTED, // MB_MULTIPLE_ENTITIES_FOUND,
103  iBase_TAG_NOT_FOUND, // MB_TAG_NOT_FOUND,
104  iBase_FILE_NOT_FOUND, // MB_FILE_DOES_NOT_EXIST,
105  iBase_FILE_WRITE_ERROR, // MB_FILE_WRITE_ERROR,
106  iBase_NOT_SUPPORTED, // MB_NOT_IMPLEMENTED,
107  iBase_TAG_ALREADY_EXISTS, // MB_ALREADY_ALLOCATED,
108  iBase_FAILURE, // MB_VARIABLE_DATA_LENGTH,
109  iBase_FAILURE, // MB_INVALID_SIZE,
110  iBase_NOT_SUPPORTED, // MB_UNSUPPORTED_OPERATION,
111  iBase_INVALID_ARGUMENT, // MB_UNHANDLED_OPTION
112  iBase_INVALID_ENTITY_TYPE, // MB_STRUCTURED_MESH
113  iBase_FAILURE // MB_FAILURE};
114 };
115 
116 // Return data about a list of handles for use in check_handle_tag_type.
117 // Set output arguments to true if the list contains the corresponding
118 // type of handle. Leave them unmodified if it does not.
119 static inline void ht_content_type( const std::vector< EntityHandle >& h, bool& saw_ent, bool& saw_set, bool& saw_root )
120 {
121  std::vector< EntityHandle >::const_iterator i;
122  for( i = h.begin(); i != h.end(); ++i )
123  {
124  if( *i == 0 )
125  saw_root = true;
126  else if( TYPE_FROM_HANDLE( *i ) == MBENTITYSET )
127  saw_set = true;
128  else
129  saw_ent = true;
130  }
131 }
132 
133 // Scan all tag data to try to guess whether the MOAB tag with
134 // data of type MB_TYPE_HANDLE is iBase_ENTITY_HANDLE or
135 // iBase_ENTITY_SET_HANDLE.
137 {
138  Interface* mb = mbi->mbImpl;
139  ErrorCode rval;
140  int size;
141  DataType type;
142  rval = mb->tag_get_data_type( t, type );
143  if( MB_SUCCESS != rval ) return rval;
144  if( MB_TYPE_HANDLE != type ) return MB_TYPE_OUT_OF_RANGE;
145  rval = mb->tag_get_length( t, size );
146  if( MB_SUCCESS != rval ) return rval;
147  std::vector< EntityHandle > data( size );
148 
149  // check for global/mesh value
150  bool saw_set = false, saw_ent = false, saw_root = false;
151  EntityHandle root = 0;
152  rval = mb->tag_get_data( t, &root, 1, &data[0] );
153  if( MB_SUCCESS == rval ) ht_content_type( data, saw_ent, saw_set, saw_root );
154 
155  // check default value
156  rval = mb->tag_get_default_value( t, &data[0] );
157  if( MB_SUCCESS == rval ) ht_content_type( data, saw_ent, saw_set, saw_root );
158 
159  // check all tagged entities
160  Range r;
161  rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, &t, 0, 1, r );
162  if( MB_SUCCESS != rval ) return rval;
163  for( Range::iterator i = r.begin(); i != r.end(); ++i )
164  {
165  rval = mb->tag_get_data( t, &*i, 1, &data[0] );
166  if( MB_SUCCESS != rval ) return rval;
167  ht_content_type( data, saw_ent, saw_set, saw_root );
168  }
169 
170  // If tag values were only entities, note type accordingly.
171  // Similarly if all are entity sets, note accordingly.
172  // Because root set (zero handle) is sometimes used to mean NULL
173  // rather than the actual root set, treat that specially. If
174  // all values are either root set or an entity handle, then
175  // treat as if all values were non-set handles.
176  if( saw_set && !saw_ent )
177  mbi->note_set_handle_tag( t );
178  else if( !saw_set && saw_ent )
179  mbi->note_ent_handle_tag( t );
180  else if( saw_root && !saw_ent )
181  mbi->note_set_handle_tag( t );
182 
183  return MB_SUCCESS;
184 }
185 
186 static void remove_var_len_tags( Interface* mb, std::vector< Tag >& tags )
187 {
188  int size;
189  size_t r, w = 0;
190  for( r = 0; r < tags.size(); ++r )
191  if( MB_SUCCESS == mb->tag_get_length( tags[r], size ) ) tags[w++] = tags[r];
192  tags.resize( w );
193 }
194 
195 // modify the adjacency table to match the ITAPS spec's expectations
196 static void munge_adj_table( int* adjTable, int geom_dim )
197 {
198  // If geom_dim is 2, 3D adjacencies are unavailable. This may change!
199  if( geom_dim == 2 )
200  {
201  for( size_t i = 0; i < 16; ++i )
202  {
203  if( i % 4 == 3 || i >= 12 ) adjTable[i] = iBase_UNAVAILABLE;
204  }
205  }
206 
207  // Ensure that diagonal entries are only available/unavailable.
208  for( size_t i = 0; i < 16; i += 5 )
209  {
210  if( adjTable[i] != iBase_UNAVAILABLE ) adjTable[i] = iBase_AVAILABLE;
211  }
212 }
213 
214 #ifdef __cplusplus
215 extern "C" {
216 #endif
217 
218 static void eatwhitespace( std::string& this_string );
219 
220 void iMesh_getErrorType( iMesh_Instance instance, int* error_type )
221 {
222  if( instance == NULL )
223  *error_type = iBase_FAILURE;
224  else
225  *error_type = MBIMESHI->lastErrorType;
226 }
227 
228 void iMesh_getDescription( iMesh_Instance instance, char* descr, int descr_len )
229 {
230  if( instance == NULL )
231  {
232  strcpy( descr, "iMesh_getDescription: Invalid instance" );
233  }
234  else
235  {
236  unsigned int len = MIN( strlen( MBIMESHI->lastErrorDescription ), static_cast< unsigned int >( descr_len ) );
237  strncpy( descr, MBIMESHI->lastErrorDescription, len );
238  descr[len] = '\0';
239  }
240 }
241 
242 void iMesh_newMesh( const char* options, iMesh_Instance* instance, int* err, int options_len )
243 {
244  std::string tmp_options = filter_options( options, options + options_len );
245  FileOptions opts( tmp_options.c_str() );
246 
247  MBiMesh** mbi = reinterpret_cast< MBiMesh** >( instance );
248  *mbi = NULL;
249 
250  ErrorCode result = opts.get_null_option( "PARALLEL" );
251  if( MB_SUCCESS == result )
252  {
253 #ifdef MOAB_HAVE_MPI
254  int flag = 1;
255  int retval = MPI_Initialized( &flag );
256  if( MPI_SUCCESS != retval || !flag )
257  {
258  int argc = 0;
259  char** argv = NULL;
260 
261  // mpi not initialized yet - initialize here
262  retval = MPI_Init( &argc, &argv );
263  assert( MPI_SUCCESS == retval );
264  }
265  *mbi = new( std::nothrow ) MBiMesh( NULL );
266 #else
267  // mError->set_last_error( "PARALLEL option not valid, this instance"
268  // " compiled for serial execution.\n" );
269  *mbi = new( std::nothrow ) MBiMesh( NULL );
270  *err = ( *mbi )->set_last_error( MB_NOT_IMPLEMENTED, "Not configured with parallel support" );
271  return;
272 #endif
273  }
274  else
275  {
276  *mbi = new( std::nothrow ) MBiMesh( NULL );
277  }
278  if( NULL == *mbi )
279  {
280  *err = iBase_FAILURE;
281  return;
282  }
283 
284  *err = iBase_SUCCESS;
285 }
286 
287 void iMesh_dtor( iMesh_Instance instance, int* err )
288 {
289  delete MBIMESHI;
290  *err = iBase_SUCCESS;
291 }
292 
293 void iMesh_load( iMesh_Instance instance,
294  const iBase_EntitySetHandle handle,
295  const char* name,
296  const char* options,
297  int* err,
298  int name_len,
299  int options_len )
300 {
301  // get filename, option & null-terminate
302  std::string filename( name, name_len );
304 
305  std::string opts = filter_options( options, options + options_len );
306 
307  Range orig_ents;
308  ErrorCode result = MOABI->get_entities_by_handle( 0, orig_ents );CHKERR( result, "Internal error" );
309 
310  const EntityHandle* file_set = 0;
311  if( handle != 0 /*root_set*/ )
312  {
313  const iBase_EntitySetHandle* ptr = &handle;
314  file_set = reinterpret_cast< const EntityHandle* >( ptr );
315  }
316 
317  result = MOABI->load_file( filename.c_str(), file_set, opts.c_str() );
318 
319  CHKERR( result, "iMesh_load:ERROR loading a mesh." );
320 
321  // create interior edges/faces if requested
322  if( MBIMESHI->AdjTable[5] || MBIMESHI->AdjTable[10] )
323  {
324  Range set_ents;
325  result = MOABI->get_entities_by_handle( 0, set_ents );CHKERR( result, "" );
326  Range sets;
327  result = MOABI->get_entities_by_type( 0, MBENTITYSET, sets );CHKERR( result, "" );
328  set_ents = subtract( set_ents, sets );
329  set_ents = subtract( set_ents, orig_ents );
330  result = create_int_ents( MBIMESHI, set_ents, file_set );CHKERR( result, "" );
331  }
333 }
334 
335 void iMesh_save( iMesh_Instance instance,
336  const iBase_EntitySetHandle handle,
337  const char* name,
338  const char* options,
339  int* err,
340  const int name_len,
341  int options_len )
342 {
343  // get filename & attempt to NULL-terminate
344  std::string filename( name, name_len );
346  std::string opts = filter_options( options, options + options_len );
347 
348  EntityHandle set = ENTITY_HANDLE( handle );
349  ErrorCode result = MOABI->write_file( filename.c_str(), NULL, opts.c_str(), &set, 1 );
350 
351  CHKERR( result, "iMesh_save:ERROR saving a mesh." );
353 }
354 
356 {
357  *root_set = 0;
358  // return CAST_TO_VOID(MOABI->get_root_set());
360 }
361 
362 void iMesh_getGeometricDimension( iMesh_Instance instance, int* geom_dim, int* err )
363 {
364  MOABI->get_dimension( *geom_dim );
366 }
367 
368 void iMesh_setGeometricDimension( iMesh_Instance instance, int geom_dim, int* err )
369 {
370  ErrorCode rval = MOABI->set_dimension( geom_dim );CHKERR( rval, "iMesh_setGeometricDimension: failed" );
371 
373 }
374 
375 void iMesh_getDfltStorage( iMesh_Instance instance, int* order, int* err )
376 {
377  *order = iBase_BLOCKED;
379 }
380 
382  int** adjacency_table,
383  /*inout*/ int* adjacency_table_allocated,
384  /*out*/ int* adjacency_table_size,
385  int* err )
386 {
387  int geom_dim;
388  iMesh_getGeometricDimension( instance, &geom_dim, err );
389 
390  ALLOC_CHECK_ARRAY_NOFAIL( adjacency_table, 16 );
391  memcpy( *adjacency_table, MBIMESHI->AdjTable, 16 * sizeof( int ) );
392  munge_adj_table( *adjacency_table, geom_dim );
394 }
395 
397  int* adj_table,
398  /*inout*/ int adj_table_size,
399  int* err )
400 {
401  if( 16 != adj_table_size )
402  {
404  }
405 
406  int geom_dim;
407  iMesh_getGeometricDimension( instance, &geom_dim, err );
408 
409  memcpy( MBIMESHI->AdjTable, adj_table, 16 * sizeof( int ) );
410  munge_adj_table( adj_table, geom_dim );
412 }
413 
415  /*in*/ const iBase_EntitySetHandle entity_set_handle,
416  /*in*/ const int entity_type,
417  int* num_type,
418  int* err )
419 {
420  iMesh_getNumOfTypeRec( instance, entity_set_handle, entity_type, false, num_type, err );
421 }
422 
424  /*in*/ const iBase_EntitySetHandle entity_set_handle,
425  /*in*/ const int entity_topology,
426  int* num_topo,
427  int* err )
428 {
429  iMesh_getNumOfTopoRec( instance, entity_set_handle, entity_topology, false, num_topo, err );
430 }
431 
432 void iMesh_optimize( iMesh_Instance instance, int* handles_invalidated, int* err )
433 {
434  // TODO: implement this for real
435  *handles_invalidated = 0;
437 }
438 
440  /*in*/ const iBase_EntitySetHandle entity_set_handle,
441  /*in*/ const int entity_type,
442  /*in*/ const int entity_topology,
443  /*inout*/ iBase_EntityHandle** entity_handles,
444  /*inout*/ int* entity_handles_allocated,
445  /*out*/ int* entity_handles_size,
446  int* err )
447 {
448  iMesh_getEntitiesRec( instance, entity_set_handle, entity_type, entity_topology, false, entity_handles,
449  entity_handles_allocated, entity_handles_size, err );
450 }
451 
453  /*in*/ const iBase_EntityHandle* vertex_handles,
454  /*in*/ const int vertex_handles_size,
455  /*inout*/ int storage_order,
456  /*inout*/ double** coords,
457  /*inout*/ int* coords_allocated,
458  /*out*/ int* coords_size,
459  int* err )
460 {
461  int geom_dim;
462  MOABI->get_dimension( geom_dim );
463 
464  // make sure we can hold them all
465  ALLOC_CHECK_ARRAY( coords, geom_dim * vertex_handles_size );
466 
467  // now get all the coordinates
468  // coords will come back interleaved by default
469  ErrorCode result;
470  if( storage_order == iBase_INTERLEAVED )
471  {
472  if( 3 == geom_dim )
473  {
474  result = MOABI->get_coords( CONST_HANDLE_ARRAY_PTR( vertex_handles ), vertex_handles_size, *coords );
475  }
476  else
477  {
478  std::vector< double > dum_coords( 3 * vertex_handles_size );
479  result = MOABI->get_coords( CONST_HANDLE_ARRAY_PTR( vertex_handles ), vertex_handles_size, &dum_coords[0] );
480 
481  for( int i = 0; i < vertex_handles_size; i++ )
482  {
483  for( int j = 0; j < geom_dim; j++ )
484  ( *coords )[geom_dim * i + j] = dum_coords[3 * i + j];
485  }
486  }
487  }
488  else
489  {
490  std::vector< double > dum_coords( 3 * vertex_handles_size );
491  result = MOABI->get_coords( CONST_HANDLE_ARRAY_PTR( vertex_handles ), vertex_handles_size, &dum_coords[0] );CHKERR( result, "iMesh_getVtxArrCoords: problem getting vertex coords" );
492 
493  for( int i = 0; i < vertex_handles_size; i++ )
494  {
495  for( int j = 0; j < geom_dim; j++ )
496  ( *coords )[i + vertex_handles_size * j] = dum_coords[3 * i + j];
497  }
498  }
499 
500  KEEP_ARRAY( coords );
502 }
503 
504 /**
505  * Method: initEntArrIter[]
506  */
508  /*in*/ const iBase_EntitySetHandle entity_set_handle,
509  /*in*/ const int requested_entity_type,
510  /*in*/ const int requested_entity_topology,
511  /*in*/ const int requested_array_size,
512  /*in*/ const int resilient,
513  /*out*/ iBase_EntityArrIterator* entArr_iterator,
514  int* err )
515 {
516  iMesh_initEntArrIterRec( instance, entity_set_handle, requested_entity_type, requested_entity_topology,
517  requested_array_size, resilient, false, entArr_iterator, err );
518 }
519 
520 /**
521  * Method: getEntArrNextIter[]
522  */
524  /*in*/ iBase_EntityArrIterator entArr_iterator,
525  /*inout*/ iBase_EntityHandle** entity_handles,
526  /*inout*/ int* entity_handles_allocated,
527  /*out*/ int* entity_handles_size,
528  int* has_data,
529  int* err )
530 {
531  // check the size of the destination array
532  ALLOC_CHECK_ARRAY_NOFAIL( entity_handles, entArr_iterator->array_size() );
533  entArr_iterator->get_entities( dynamic_cast< Core* >( MOABI ), (EntityHandle*)*entity_handles,
534  *entity_handles_size );
535  *has_data = ( *entity_handles_size != 0 );
537 }
538 
539 /**
540  * Method: resetEntArrIter[]
541  */
543  /*in*/ iBase_EntityArrIterator entArr_iterator,
544  int* err )
545 {
546  ErrorCode result = entArr_iterator->reset( MOABI );CHKERR( result, "Re-query of iterator data for iMesh_resetEntArrIter failed" );
548 }
549 
551  /*in*/ iBase_EntityArrIterator entArr_iterator,
552  int* err )
553 {
554  delete entArr_iterator;
556 }
557 
559  /*in*/ const iBase_EntityHandle* entity_handles,
560  /*in*/ const int entity_handles_size,
561  /*inout*/ int** topology,
562  /*inout*/ int* topology_allocated,
563  /*out*/ int* topology_size,
564  int* err )
565 {
566  // go through each entity and look up its type
567  ALLOC_CHECK_ARRAY_NOFAIL( topology, entity_handles_size );
568 
569  for( int i = 0; i < entity_handles_size; i++ )
570  ( *topology )[i] = tstt_topology_table[MOABI->type_from_handle( ENTITY_HANDLE( entity_handles[i] ) )];
571 
572  *topology_size = entity_handles_size;
573 
575 }
576 
578  /*in*/ const iBase_EntityHandle* entity_handles,
579  /*in*/ const int entity_handles_size,
580  /*inout*/ int** etype,
581  /*inout*/ int* etype_allocated,
582  /*out*/ int* etype_size,
583  int* err )
584 {
585  // go through each entity and look up its type
586  ALLOC_CHECK_ARRAY_NOFAIL( etype, entity_handles_size );
587 
588  for( int i = 0; i < entity_handles_size; i++ )
589  ( *etype )[i] = tstt_type_table[MOABI->type_from_handle( ENTITY_HANDLE( entity_handles[i] ) )];
590 
591  *etype_size = entity_handles_size;
592 
594 }
595 
597  /*in*/ const iBase_EntityHandle* entity_handles,
598  /*in*/ const int entity_handles_size,
599  /*in*/ const int entity_type_requested,
600  /*inout*/ iBase_EntityHandle** adjacentEntityHandles,
601  /*inout*/ int* adjacentEntityHandles_allocated,
602  /*out*/ int* adjacentEntityHandles_size,
603  /*inout*/ int** offset,
604  /*inout*/ int* offset_allocated,
605  /*out*/ int* offset_size,
606  int* err )
607 {
608  ErrorCode result = MB_SUCCESS;
609 
610  ALLOC_CHECK_ARRAY( offset, entity_handles_size + 1 );
611 
612  const EntityHandle* entity_iter = (const EntityHandle*)entity_handles;
613  const EntityHandle* const entity_end = entity_iter + entity_handles_size;
614  int* off_iter = *offset;
615  int prev_off = 0;
616 
617  std::vector< EntityHandle > conn_storage;
618  std::vector< EntityHandle > adj_ents;
619  const EntityHandle* connect;
620  int num_connect;
621 
622  EntityHandle* array; // ptr to working array of result handles
623  int array_alloc; // allocated size of 'array'
624  const bool allocated_array = !*adjacentEntityHandles_allocated || !*adjacentEntityHandles;
625  if( allocated_array )
626  {
627  array = 0;
628  array_alloc = 0;
629  }
630  else
631  {
632  array = reinterpret_cast< EntityHandle* >( *adjacentEntityHandles );
633  array_alloc = *adjacentEntityHandles_allocated;
634  }
635 
636  for( ; entity_iter != entity_end; ++entity_iter )
637  {
638  *off_iter = prev_off;
639  off_iter++;
640 
641  if( iBase_VERTEX == entity_type_requested && TYPE_FROM_HANDLE( *entity_iter ) != MBPOLYHEDRON )
642  {
643  if( CN::Dimension( TYPE_FROM_HANDLE( *entity_iter ) ) == 0 ) continue;
644  result = MOABI->get_connectivity( *entity_iter, connect, num_connect, false, &conn_storage );
645  if( MB_SUCCESS != result )
646  {
647  if( allocated_array ) free( array );
648  ERROR( result, "iMesh_getEntArrAdj: trouble getting adjacency list." );
649  }
650  }
651  else if( iBase_ALL_TYPES == entity_type_requested )
652  {
653  adj_ents.clear();
654  for( int dim = 0; dim < 4; ++dim )
655  {
656  if( CN::Dimension( TYPE_FROM_HANDLE( *entity_iter ) ) == dim ) continue;
657  result = MOABI->get_adjacencies( entity_iter, 1, dim, false, adj_ents, Interface::UNION );
658  if( MB_SUCCESS != result )
659  {
660  if( allocated_array ) free( array );
661  ERROR( result, "iMesh_getEntArrAdj: trouble getting adjacency list." );
662  }
663  }
664  connect = &adj_ents[0];
665  num_connect = adj_ents.size();
666  }
667  else
668  {
669  if( CN::Dimension( TYPE_FROM_HANDLE( *entity_iter ) ) == entity_type_requested ) continue;
670  adj_ents.clear();
671  result = MOABI->get_adjacencies( entity_iter, 1, entity_type_requested, false, adj_ents );
672  if( MB_SUCCESS != result )
673  {
674  if( allocated_array ) free( array );
675  ERROR( result, "iMesh_getEntArrAdj: trouble getting adjacency list." );
676  }
677  connect = &adj_ents[0];
678  num_connect = adj_ents.size();
679  }
680 
681  if( prev_off + num_connect <= array_alloc )
682  {
683  std::copy( connect, connect + num_connect, array + prev_off );
684  }
685  else if( allocated_array )
686  {
687  // if array is not allocated yet, guess at initial size
688  // as the number of adjacencies for the first entity times
689  // the number of input entities. This will result in a single
690  // exact allocation if one input entity or typical queries
691  // such as connectivity of a non-mixed mesh or regions adjacent
692  // to faces.
693  if( !array_alloc )
694  array_alloc = entity_handles_size * num_connect;
695  else
696  array_alloc = std::max( array_alloc * 2, prev_off + num_connect );
697  EntityHandle* new_array = (EntityHandle*)realloc( array, array_alloc * sizeof( EntityHandle ) );
698  if( !new_array )
699  {
700  free( array );
702  }
703  else
704  array = new_array;
705  std::copy( connect, connect + num_connect, array + prev_off );
706  }
707  // else do nothing. Will catch error later when comparing
708  // occupied to allocated sizes. Continue here because
709  // must pass back required size.
710 
711  prev_off += num_connect;
712  }
713  *off_iter = prev_off;
714  *adjacentEntityHandles_size = prev_off;
715 
716  if( *adjacentEntityHandles_size > array_alloc )
717  {
718  if( allocated_array ) free( array );
720  }
721  else if( allocated_array )
722  {
723  *adjacentEntityHandles = reinterpret_cast< iBase_EntityHandle* >( array );
724  *adjacentEntityHandles_allocated = array_alloc;
725  }
726 
727  KEEP_ARRAY( offset );
729 }
730 
732  iBase_EntityHandle const* entity_handles,
733  int entity_handles_size,
734  int bridge_entity_type,
735  int requested_entity_type,
736  iBase_EntityHandle** adj_entity_handles,
737  int* adj_entity_handles_allocated,
738  int* adj_entity_handles_size,
739  int** offset,
740  int* offset_allocated,
741  int* offset_size,
742  int* err )
743 {
744  CHKENUM( bridge_entity_type, iBase_EntityType, iBase_INVALID_ENTITY_TYPE );
745  CHKENUM( requested_entity_type, iBase_EntityType, iBase_INVALID_ENTITY_TYPE );
746 
747  ErrorCode result = MB_SUCCESS;
748 
749  ALLOC_CHECK_ARRAY( offset, entity_handles_size + 1 );
750 
751  const EntityHandle* entity_iter = (const EntityHandle*)entity_handles;
752  const EntityHandle* const entity_end = entity_iter + entity_handles_size;
753  int* off_iter = *offset;
754  int prev_off = 0;
755 
756  std::vector< EntityHandle > all_adj_ents;
757  MeshTopoUtil mtu( MOABI );
758 
759  int min_bridge = iBase_VERTEX, max_bridge = iBase_REGION;
760  int min_req = iBase_VERTEX, max_req = iBase_REGION;
761  if( iBase_ALL_TYPES != bridge_entity_type ) min_bridge = max_bridge = bridge_entity_type;
762  if( iBase_ALL_TYPES != requested_entity_type ) min_req = max_req = requested_entity_type;
763 
764  for( ; entity_iter != entity_end; ++entity_iter )
765  {
766  *off_iter = prev_off;
767  off_iter++;
768  Range adj_ents;
769 
770  int source = CN::Dimension( TYPE_FROM_HANDLE( *entity_iter ) );
771  for( int bridge = min_bridge; bridge <= max_bridge; ++bridge )
772  {
773  if( source == bridge ) continue;
774  for( int requested = min_req; requested <= max_req; ++requested )
775  {
776  if( bridge == requested ) continue;
777  result = mtu.get_bridge_adjacencies( *entity_iter, bridge, requested, adj_ents );CHKERR( result, "iMesh_getEntArr2ndAdj: trouble getting adjacency list." );
778  }
779  }
780 
781  std::copy( adj_ents.begin(), adj_ents.end(), std::back_inserter( all_adj_ents ) );
782  prev_off += adj_ents.size();
783  }
784  *off_iter = prev_off;
785 
786  ALLOC_CHECK_ARRAY_NOFAIL( adj_entity_handles, all_adj_ents.size() );
787  memcpy( *adj_entity_handles, &all_adj_ents[0], sizeof( EntityHandle ) * all_adj_ents.size() );
788 
789  KEEP_ARRAY( offset );
790 
791  // Return an error if the bridge and requested entity types are different
792  if( iBase_ALL_TYPES != bridge_entity_type && bridge_entity_type == requested_entity_type )
793  ERROR( iBase_INVALID_ARGUMENT, "iMesh_getEntArr2ndAdj: bridge and "
794  "requested entity types must be different." );
795  else
797 }
798 
800  /*in*/ iBase_EntitySetHandle entity_set_handle,
801  /*in*/ int entity_type_requestor,
802  /*in*/ int entity_topology_requestor,
803  /*in*/ int entity_type_requested,
804  /*inout*/ iBase_EntityHandle** entity_handles,
805  /*inout*/ int* entity_handles_allocated,
806  /*out*/ int* entity_handles_size,
807  /*inout*/ iBase_EntityHandle** adj_entity_handles,
808  /*inout*/ int* adj_entity_handles_allocated,
809  /*out*/ int* adj_entity_handles_size,
810  /*inout*/ int** adj_entity_indices,
811  /*inout*/ int* adj_entity_indices_allocated,
812  /*out*/ int* adj_entity_indices_size,
813  /*inout*/ int** offset,
814  /*inout*/ int* offset_allocated,
815  /*out*/ int* offset_size,
816  /*out*/ int* err )
817 {
818  const int allocated_entity_handles = ( *entity_handles_allocated == 0 );
819  const int allocated_indices = ( *adj_entity_indices_allocated == 0 );
820  const int allocated_offset = ( *offset_allocated == 0 );
821 
822  // get source entities
823  iMesh_getEntities( instance, entity_set_handle, entity_type_requestor, entity_topology_requestor, entity_handles,
824  entity_handles_allocated, entity_handles_size, err );
825  if( iBase_SUCCESS != *err ) return;
826 
827  // get adjacencies
828  iBase_EntityHandle* all_adj_handles = 0;
829  int size = 0, alloc = 0;
830  iMesh_getEntArrAdj( instance, *entity_handles, *entity_handles_size, entity_type_requested, &all_adj_handles,
831  &alloc, &size, offset, offset_allocated, offset_size, err );
832  if( *err != iBase_SUCCESS )
833  {
834  if( allocated_entity_handles )
835  {
836  free( *entity_handles );
837  *entity_handles = 0;
838  *entity_handles_allocated = 0;
839  }
840  return;
841  }
842 
843  // allocate or check size of adj_entity_indices
844  *adj_entity_indices_size = size;
845  if( allocated_indices )
846  {
847  *adj_entity_indices = (int*)malloc( sizeof( iBase_EntityHandle ) * size );
848  if( !*adj_entity_indices )
850  else
851  *adj_entity_indices_allocated = size;
852  }
853  else if( *adj_entity_indices_allocated < size )
854  {
856  }
857  if( iBase_SUCCESS != *err )
858  {
859  free( all_adj_handles );
860  if( allocated_entity_handles )
861  {
862  free( *entity_handles );
863  *entity_handles = 0;
864  *entity_handles_allocated = 0;
865  }
866  if( allocated_offset )
867  {
868  free( *offset );
869  *offset = 0;
870  *offset_allocated = 0;
871  }
872  return;
873  }
874 
875  // Now create an array of unique sorted handles from all_adj_handles.
876  // We need to create a copy because we still need all_adj_handles. We
877  // will eventually need to copy the resulting unique list into
878  // adj_entity_handles, so if adj_entity_handles is already allocated and
879  // of sufficient size, use it rather than allocating another temporary.
880  iBase_EntityHandle* unique_adj = 0;
881  if( *adj_entity_handles_allocated >= size )
882  {
883  unique_adj = *adj_entity_handles;
884  }
885  else
886  {
887  unique_adj = (iBase_EntityHandle*)malloc( sizeof( iBase_EntityHandle ) * size );
888  }
889  std::copy( all_adj_handles, all_adj_handles + size, unique_adj );
890  std::sort( unique_adj, unique_adj + size );
891  *adj_entity_handles_size = std::unique( unique_adj, unique_adj + size ) - unique_adj;
892 
893  // If we created a temporary array for unique_adj rather than using
894  // already allocated space in adj_entity_handles, allocate adj_entity_handles
895  // and copy the unique handle list into it
896  if( *adj_entity_handles != unique_adj )
897  {
898  if( !*adj_entity_handles_allocated )
899  {
900  *adj_entity_handles =
901  (iBase_EntityHandle*)malloc( sizeof( iBase_EntityHandle ) * *adj_entity_handles_size );
902  if( !*adj_entity_handles )
904  else
905  *adj_entity_handles_allocated = *adj_entity_handles_size;
906  }
907  else if( *adj_entity_handles_allocated < *adj_entity_handles_size )
909  if( iBase_SUCCESS != *err )
910  {
911  free( unique_adj );
912  free( all_adj_handles );
913  if( allocated_entity_handles )
914  {
915  free( *entity_handles );
916  *entity_handles = 0;
917  *entity_handles_allocated = 0;
918  }
919  if( allocated_offset )
920  {
921  free( *offset );
922  *offset = 0;
923  *offset_allocated = 0;
924  }
925  if( allocated_indices )
926  {
927  free( *adj_entity_indices );
928  *adj_entity_indices = 0;
929  *adj_entity_indices_allocated = 0;
930  }
931  return;
932  }
933 
934  std::copy( unique_adj, unique_adj + *adj_entity_handles_size, *adj_entity_handles );
935  free( unique_adj );
936  unique_adj = *adj_entity_handles;
937  }
938 
939  // convert from adjacency list to indices into unique_adj
940  for( int i = 0; i < *adj_entity_indices_size; ++i )
941  ( *adj_entity_indices )[i] =
942  std::lower_bound( unique_adj, unique_adj + *adj_entity_handles_size, all_adj_handles[i] ) - unique_adj;
943  free( all_adj_handles );
944 }
945 
947  /*in*/ const int isList,
948  /*out*/ iBase_EntitySetHandle* entity_set_created,
949  int* err )
950 {
951  // create the entity set
952  EntityHandle meshset;
953  ErrorCode result;
954 
955  if( isList )
956  result = MOABI->create_meshset( MESHSET_ORDERED, meshset );
957  else
958  result = MOABI->create_meshset( MESHSET_SET, meshset );
959 
960  CHKERR( result, "iMesh_createEntSet: ERROR creating a entityset instance" );
961 
962  // return EntitySet_Handle
963  *entity_set_created = (iBase_EntitySetHandle)meshset;
965 }
966 
968  /*in*/ iBase_EntitySetHandle entity_set,
969  int* err )
970 {
971  EntityHandle set = ENTITY_HANDLE( entity_set );
972  ErrorCode result = MOABI->delete_entities( &set, 1 );CHKERR( result, "iMesh_destroyEntSet: couldn't delete the set." );
973 
975 }
976 
978  /*in*/ const iBase_EntitySetHandle entity_set,
979  int* is_list,
980  int* err )
981 {
982  unsigned int options;
983  ErrorCode result = MOABI->get_meshset_options( ENTITY_HANDLE( entity_set ), options );CHKERR( result, "iMesh_isList: couldn't query set." );
984  if( options & MESHSET_ORDERED )
985  *is_list = true;
986  else
987  *is_list = false;
988 
990 }
991 
993  /*in*/ const iBase_EntitySetHandle entity_set_handle,
994  /*in*/ const int num_hops,
995  int* num_sets,
996  int* err )
997 {
998  ErrorCode rval =
999  MOABI->num_contained_meshsets( ENTITY_HANDLE( entity_set_handle ), num_sets, std::max( 0, num_hops + 1 ) );CHKERR( rval, "iMesh_entitysetGetNumberEntitySets:ERROR getting number of entitysets." );
1000 
1001  RETURN( iBase_SUCCESS );
1002 }
1003 
1005  /*in*/ const iBase_EntitySetHandle entity_set_handle,
1006  /*in*/ const int num_hops,
1007  /*inout*/ iBase_EntitySetHandle** contained_entset_handles,
1008  /*inout*/ int* contained_entset_handles_allocated,
1009  /*inout*/ int* contained_entset_handles_size,
1010  int* err )
1011 {
1012  std::vector< EntityHandle > sets;
1013  ErrorCode rval =
1014  MOABI->get_contained_meshsets( ENTITY_HANDLE( entity_set_handle ), sets, std::max( num_hops + 1, 0 ) );CHKERR( rval, "iMesh_entitysetGetEntitySets: problem getting entities by type." );
1015  ALLOC_CHECK_ARRAY_NOFAIL( contained_entset_handles, sets.size() );
1016 
1017  std::copy( sets.begin(), sets.end(), (EntityHandle*)*contained_entset_handles );
1018  *contained_entset_handles_size = sets.size();
1019  RETURN( iBase_SUCCESS );
1020 }
1021 
1023  /*in*/ const iBase_EntityHandle* entity_handles,
1024  /*in*/ int entity_handles_size,
1025  /*in*/ iBase_EntitySetHandle entity_set,
1026  int* err )
1027 {
1028  const EntityHandle* ents = CONST_HANDLE_ARRAY_PTR( entity_handles );
1029  ErrorCode result = MOABI->add_entities( ENTITY_HANDLE( entity_set ), ents, entity_handles_size );
1030 
1031  CHKERR( result, "iMesh_addEntArrToSet:ERROR adding entities in EntitySet." );
1032  RETURN( iBase_SUCCESS );
1033 }
1034 
1036  /*in*/ iBase_EntityHandle entity_handle,
1037  /*in*/ iBase_EntitySetHandle entity_set,
1038  int* err )
1039 {
1040  iMesh_addEntArrToSet( instance, &entity_handle, 1, entity_set, err );
1041 }
1042 
1044  /*in*/ const iBase_EntityHandle* entity_handles,
1045  /*in*/ int entity_handles_size,
1046  /*in*/ iBase_EntitySetHandle entity_set,
1047  int* err )
1048 {
1049  const EntityHandle* ents = CONST_HANDLE_ARRAY_PTR( entity_handles );
1050 
1051  ErrorCode result = MOABI->remove_entities( ENTITY_HANDLE( entity_set ), ents, entity_handles_size );
1052 
1053  CHKERR( result, "iMesh_rmvEntArrFromSet:ERROR removing entities in EntitySet." );
1054  RETURN( iBase_SUCCESS );
1055 }
1056 
1058  /*in*/ iBase_EntityHandle entity_handle,
1059  /*in*/ iBase_EntitySetHandle entity_set,
1060  int* err )
1061 {
1062  iMesh_rmvEntArrFromSet( instance, &entity_handle, 1, entity_set, err );
1063 }
1064 
1066  /*in*/ iBase_EntitySetHandle entity_set_to_add,
1067  /*in*/ iBase_EntitySetHandle entity_set_handle,
1068  int* err )
1069 {
1070  if( !entity_set_to_add || !entity_set_handle )
1071  ERROR( iBase_INVALID_ARGUMENT, "iMesh_addEntSet: ERROR invalid argument" );
1072 
1073  EntityHandle to_add = ENTITY_HANDLE( entity_set_to_add );
1074  ErrorCode result = MOABI->add_entities( ENTITY_HANDLE( entity_set_handle ), &to_add, 1 );
1075 
1076  CHKERR( result, "iMesh_addEntSet:ERROR adding entitysets." );
1077  RETURN( iBase_SUCCESS );
1078 }
1079 
1081  /*in*/ iBase_EntitySetHandle entity_set_to_remove,
1082  /*in*/ iBase_EntitySetHandle entity_set_handle,
1083  int* err )
1084 {
1085  if( !entity_set_to_remove || !entity_set_handle )
1086  ERROR( iBase_INVALID_ARGUMENT, "iMesh_rmvEntSet: ERROR invalid argument" );
1087 
1088  EntityHandle to_remove = ENTITY_HANDLE( entity_set_to_remove );
1089  ErrorCode result = MOABI->remove_entities( ENTITY_HANDLE( entity_set_handle ), &to_remove, 1 );
1090 
1091  CHKERR( result, "iMesh_rmvEntSet:ERROR removing entitysets in EntitySet." );
1092  RETURN( iBase_SUCCESS );
1093 }
1094 
1096  /*in*/ iBase_EntitySetHandle containing_entity_set,
1097  /*in*/ iBase_EntityHandle contained_entity,
1098  int* is_contained,
1099  int* err )
1100 {
1101  int junk1 = 1, junk2 = 1;
1102  iMesh_isEntArrContained( instance, containing_entity_set, &contained_entity, 1, &is_contained, &junk1, &junk2,
1103  err );
1104 }
1105 
1107  /*in*/ iBase_EntitySetHandle containing_set,
1108  /*in*/ const iBase_EntityHandle* entity_handles,
1109  /*in*/ int num_entity_handles,
1110  /*inout*/ int** is_contained,
1111  /*inout*/ int* is_contained_allocated,
1112  /*out*/ int* is_contained_size,
1113  /*out*/ int* err )
1114 
1115 {
1116  EntityHandle set = ENTITY_HANDLE( containing_set );
1117  ALLOC_CHECK_ARRAY_NOFAIL( is_contained, num_entity_handles );
1118  *is_contained_size = num_entity_handles;
1119 
1120  if( containing_set )
1121  {
1122  for( int i = 0; i < num_entity_handles; ++i )
1123  {
1124  EntityHandle h = ENTITY_HANDLE( entity_handles[i] );
1125  ( *is_contained )[i] = MOABI->contains_entities( set, &h, 1 );
1126  }
1127  }
1128  else
1129  {
1130  std::fill( *is_contained, ( *is_contained ) + num_entity_handles, 1 );
1131  }
1132  RETURN( iBase_SUCCESS );
1133 }
1134 
1136  /*in*/ const iBase_EntitySetHandle containing_entity_set,
1137  /*in*/ const iBase_EntitySetHandle contained_entity_set,
1138  int* is_contained,
1139  int* err )
1140 {
1141  iMesh_isEntContained( instance, containing_entity_set,
1142  reinterpret_cast< iBase_EntityHandle >( contained_entity_set ), is_contained, err );
1143 }
1144 
1146  /*inout*/ iBase_EntitySetHandle parent_entity_set,
1147  /*inout*/ iBase_EntitySetHandle child_entity_set,
1148  int* err )
1149 {
1150  ErrorCode result = MOABI->add_parent_child( ENTITY_HANDLE( parent_entity_set ), ENTITY_HANDLE( child_entity_set ) );
1151 
1152  if( result == MB_ENTITY_NOT_FOUND )
1153  ERROR( iBase_INVALID_ENTITYSET_HANDLE, "iMesh_addPrntChld: ERROR invalid entity set." );CHKERR( result, "iMesh_addPrntChld: ERROR addParentChild failed." );
1154  RETURN( iBase_SUCCESS );
1155 }
1156 
1158  /*inout*/ iBase_EntitySetHandle parent_entity_set,
1159  /*inout*/ iBase_EntitySetHandle child_entity_set,
1160  int* err )
1161 {
1162  ErrorCode result =
1163  MOABI->remove_parent_child( ENTITY_HANDLE( parent_entity_set ), ENTITY_HANDLE( child_entity_set ) );
1164 
1165  if( result == MB_ENTITY_NOT_FOUND )
1166  ERROR( iBase_INVALID_ENTITYSET_HANDLE, "iMesh_rmvPrntChld: ERROR invalid entity set." );CHKERR( result, "iMesh_rmvPrntChld: ERROR RemoveParentChild failed." );
1167  RETURN( iBase_SUCCESS );
1168 }
1169 
1171  /*in*/ const iBase_EntitySetHandle parent_entity_set,
1172  /*in*/ const iBase_EntitySetHandle child_entity_set,
1173  int* is_child,
1174  int* err )
1175 {
1176  if( !child_entity_set ) ERROR( iBase_INVALID_ENTITYSET_HANDLE, "iMesh_isChildOf: ERROR invalid entity set." );
1177 
1178  std::vector< EntityHandle > children;
1179 
1180  ErrorCode result = MOABI->get_child_meshsets( ENTITY_HANDLE( parent_entity_set ), children );
1181 
1182  if( result == MB_ENTITY_NOT_FOUND )
1183  ERROR( iBase_INVALID_ENTITYSET_HANDLE, "iMesh_rmvPrntChld: ERROR invalid entity set." );CHKERR( result, "iMesh_isChildOf: ERROR IsParentChildRelated failed." );
1184 
1185  if( std::find( children.begin(), children.end(), ENTITY_HANDLE( child_entity_set ) ) != children.end() )
1186  *is_child = true;
1187 
1188  else
1189  *is_child = false;
1190 
1191  RETURN( iBase_SUCCESS );
1192 }
1193 
1195  /*in*/ const iBase_EntitySetHandle entity_set,
1196  /*in*/ const int num_hops,
1197  int* num_child,
1198  int* err )
1199 {
1200  *num_child = 0;
1201  ErrorCode result = MOABI->num_child_meshsets( ENTITY_HANDLE( entity_set ), num_child, num_hops + 1 );
1202 
1203  if( result == MB_ENTITY_NOT_FOUND )
1204  ERROR( iBase_INVALID_ENTITYSET_HANDLE, "iMesh_getNumChld: ERROR invalid entity set." );CHKERR( result, "iMesh_getNumChld: ERROR GetNumChildren failed." );
1205 
1206  RETURN( iBase_SUCCESS );
1207 }
1208 
1210  /*in*/ const iBase_EntitySetHandle entity_set,
1211  /*in*/ const int num_hops,
1212  int* num_parent,
1213  int* err )
1214 {
1215  *num_parent = 0;
1216  ErrorCode result = MOABI->num_parent_meshsets( ENTITY_HANDLE( entity_set ), num_parent, num_hops + 1 );
1217 
1218  if( result == MB_ENTITY_NOT_FOUND )
1219  ERROR( iBase_INVALID_ENTITYSET_HANDLE, "iMesh_getNumPrnt: ERROR invalid entity set." );CHKERR( result, "iMesh_getNumPrnt: ERROR GetNumParents failed." );
1220  RETURN( iBase_SUCCESS );
1221 }
1222 
1224  /*in*/ const iBase_EntitySetHandle from_entity_set,
1225  /*in*/ const int num_hops,
1226  /*out*/ iBase_EntitySetHandle** entity_set_handles,
1227  /*out*/ int* entity_set_handles_allocated,
1228  /*out*/ int* entity_set_handles_size,
1229  int* err )
1230 {
1231  std::vector< EntityHandle > children;
1232 
1233  ErrorCode result = MOABI->get_child_meshsets( ENTITY_HANDLE( from_entity_set ), children, num_hops + 1 );
1234 
1235  if( result == MB_ENTITY_NOT_FOUND )
1236  ERROR( iBase_INVALID_ENTITYSET_HANDLE, "iMesh_getChldn: ERROR invalid entity set." );CHKERR( result, "ERROR getChildren failed." );
1237  ALLOC_CHECK_ARRAY_NOFAIL( entity_set_handles, children.size() );
1238 
1239  EntityHandle* ents = HANDLE_ARRAY_PTR( *entity_set_handles );
1240  // use a memcpy for efficiency
1241  memcpy( ents, &children[0], children.size() * sizeof( EntityHandle ) );
1242 
1243  RETURN( iBase_SUCCESS );
1244 }
1245 
1247  /*in*/ const iBase_EntitySetHandle from_entity_set,
1248  /*in*/ const int num_hops,
1249  /*out*/ iBase_EntitySetHandle** entity_set_handles,
1250  /*out*/ int* entity_set_handles_allocated,
1251  /*out*/ int* entity_set_handles_size,
1252  int* err )
1253 {
1254  std::vector< EntityHandle > parents;
1255 
1256  ErrorCode result = MOABI->get_parent_meshsets( ENTITY_HANDLE( from_entity_set ), parents, num_hops + 1 );
1257 
1258  if( result == MB_ENTITY_NOT_FOUND )
1259  ERROR( iBase_INVALID_ENTITYSET_HANDLE, "iMesh_getPrnts: ERROR invalid entity set." );CHKERR( result, "ERROR getParents failed." );
1260 
1261  ALLOC_CHECK_ARRAY_NOFAIL( entity_set_handles, parents.size() );
1262 
1263  EntityHandle* ents = HANDLE_ARRAY_PTR( *entity_set_handles );
1264  // use a memcpy for efficiency
1265  memcpy( ents, &parents[0], parents.size() * sizeof( EntityHandle ) );
1266 
1267  RETURN( iBase_SUCCESS );
1268 }
1269 
1271  /*in*/ const iBase_EntityHandle* vertex_handles,
1272  /*in*/ const int vertex_handles_size,
1273  /*in*/ const int storage_order,
1274  /*in*/ const double* new_coords,
1275  /*in*/ const int new_coords_size,
1276  int* err )
1277 {
1279 
1280  int geom_dim;
1281  MOABI->get_dimension( geom_dim );
1282  if( new_coords_size != geom_dim * vertex_handles_size )
1283  {
1284  ERROR( iBase_INVALID_ARGUMENT, "iMesh_setVtxArrCoords: Didn't get the right # coordinates." );
1285  }
1286 
1287  ErrorCode result = MB_SUCCESS, tmp_result;
1288  if( storage_order == iBase_INTERLEAVED )
1289  {
1290  if( 3 == geom_dim )
1291  {
1292  result = MOABI->set_coords( CONST_HANDLE_ARRAY_PTR( vertex_handles ), vertex_handles_size, new_coords );
1293  }
1294  else
1295  {
1296  const EntityHandle* verts = CONST_HANDLE_ARRAY_PTR( vertex_handles );
1297  double dummy[3] = { 0, 0, 0 };
1298  for( int i = 0; i < vertex_handles_size; i++ )
1299  {
1300  for( int j = 0; j < geom_dim; j++ )
1301  dummy[j] = new_coords[geom_dim * i + j];
1302  tmp_result = MOABI->set_coords( &verts[i], 1, dummy );
1303  if( MB_SUCCESS != tmp_result ) result = tmp_result;
1304  }
1305  }
1306  }
1307  else
1308  {
1309  const EntityHandle* verts = CONST_HANDLE_ARRAY_PTR( vertex_handles );
1310  double dummy[3] = { 0, 0, 0 };
1311  for( int i = 0; i < vertex_handles_size; i++ )
1312  {
1313  for( int j = 0; j < geom_dim; j++ )
1314  dummy[j] = new_coords[i + vertex_handles_size * j];
1315  tmp_result = MOABI->set_coords( &verts[i], 1, dummy );
1316  if( MB_SUCCESS != tmp_result ) result = tmp_result;
1317  }
1318  }
1319 
1320  CHKERR( result, "iMesh_setVtxArrCoords: problem setting coordinates." );
1321 
1322  RETURN( iBase_SUCCESS );
1323 }
1324 
1326  /*in*/ const int num_verts,
1327  /*in*/ const int storage_order,
1328  /*in*/ const double* new_coords,
1329  /*in*/ const int new_coords_size,
1330  /*inout*/ iBase_EntityHandle** new_vertex_handles,
1331  /*inout*/ int* new_vertex_handles_allocated,
1332  /*inout*/ int* new_vertex_handles_size,
1333  int* err )
1334 {
1335  int geom_dim;
1336  MOABI->get_dimension( geom_dim );
1337  if( new_coords_size != geom_dim * num_verts )
1338  {
1339  ERROR( iBase_INVALID_ARGUMENT, "iMesh_createVtxArr: Didn't get the right # coordinates." );
1340  }
1341 
1342  // if there aren't any elements in the array, allocate it
1343  ALLOC_CHECK_ARRAY( new_vertex_handles, num_verts );
1344 
1345  // make the entities
1346  EntityHandle* new_verts = HANDLE_ARRAY_PTR( *new_vertex_handles );
1347 
1348  if( storage_order == iBase_INTERLEAVED )
1349  {
1350  if( 3 == geom_dim )
1351  {
1352  for( int i = 0; i < num_verts; i++ )
1353  {
1354  ErrorCode result = MOABI->create_vertex( &new_coords[3 * i], new_verts[i] );CHKERR( result, "iMesh_createVtxArr: couldn't create vertex." );
1355  }
1356  }
1357  else
1358  {
1359  double tmp[3] = { 0, 0, 0 };
1360  for( int i = 0; i < num_verts; i++ )
1361  {
1362  for( int j = 0; j < geom_dim; j++ )
1363  tmp[j] = new_coords[geom_dim * i + j];
1364  ErrorCode result = MOABI->create_vertex( tmp, new_verts[i] );CHKERR( result, "iMesh_createVtxArr: couldn't create vertex." );
1365  }
1366  }
1367  }
1368  else
1369  {
1370  double tmp[3] = { 0, 0, 0 };
1371  for( int i = 0; i < num_verts; i++ )
1372  {
1373  for( int j = 0; j < geom_dim; j++ )
1374  tmp[j] = new_coords[j * num_verts + i];
1375 
1376  ErrorCode result = MOABI->create_vertex( tmp, new_verts[i] );CHKERR( result, "iMesh_createVtxArr: couldn't create vertex." );
1377  }
1378  }
1379 
1380  KEEP_ARRAY( new_vertex_handles );
1381  RETURN( iBase_SUCCESS );
1382 }
1383 
1385  /*in*/ const int new_entity_topology,
1386  /*in*/ const iBase_EntityHandle* lower_order_entity_handles,
1387  /*in*/ const int lower_order_entity_handles_size,
1388  /*out*/ iBase_EntityHandle** new_entity_handles,
1389  /*out*/ int* new_entity_handles_allocated,
1390  /*out*/ int* new_entity_handles_size,
1391  /*inout*/ int** status,
1392  /*inout*/ int* status_allocated,
1393  /*out*/ int* status_size,
1394  int* err )
1395 {
1396  // for now, throw an error if lower order entity handles aren't vertices
1397  if( iMesh_POINT > new_entity_topology || iMesh_SEPTAHEDRON < new_entity_topology )
1398  {
1399  ERROR( iBase_INVALID_ARGUMENT, "iMesh_createEntArr: invalid topology." );
1400  }
1401  EntityType this_type = mb_topology_table[new_entity_topology];
1402  int num_ents = 0, num_verts;
1403  const EntityHandle* lower_ents;
1404  if( MBVERTEX != this_type )
1405  {
1406  num_verts = CN::VerticesPerEntity( this_type );
1407  num_ents = lower_order_entity_handles_size / num_verts;
1408  lower_ents = CONST_HANDLE_ARRAY_PTR( lower_order_entity_handles );
1409  // check that we have the right number of lower order entity handles
1410  if( lower_order_entity_handles_size % CN::VerticesPerEntity( this_type ) != 0 )
1411  {
1412  ERROR( iBase_INVALID_ENTITY_COUNT, "iMesh_createEntArr: wrong # vertices for this entity type." );
1413  }
1414  }
1415  else
1416  {
1417  ERROR( iBase_INVALID_ARGUMENT, "iMesh_createEntArr: can't create vertices with this "
1418  "function, use createVtxArr instead." );
1419  }
1420 
1421  if( num_ents == 0 )
1422  {
1423  ERROR( iBase_INVALID_ENTITY_COUNT, "iMesh_createEntArr: called to create 0 entities." );
1424  }
1425 
1426  // if there aren't any elements in the array, allocate it
1427 
1428  // This function is poorly defined. We have to return allocated
1429  // arrays even if we fail.
1430  ALLOC_CHECK_ARRAY_NOFAIL( new_entity_handles, num_ents );
1431  ALLOC_CHECK_ARRAY_NOFAIL( status, num_ents );
1432 
1433  // make the entities
1434  EntityHandle* new_ents = HANDLE_ARRAY_PTR( *new_entity_handles );
1435 
1436  ErrorCode tmp_result, result = MB_SUCCESS;
1437 
1438  for( int i = 0; i < num_ents; i++ )
1439  {
1440  tmp_result = MOABI->create_element( this_type, lower_ents, num_verts, new_ents[i] );
1441  if( MB_SUCCESS != tmp_result )
1442  {
1443  ( *status )[i] = iBase_CREATION_FAILED;
1444  result = tmp_result;
1445  }
1446  else
1447  ( *status )[i] = iBase_NEW;
1448 
1449  lower_ents += num_verts;
1450  }
1451 
1452  CHKERR( result, "iMesh_createEntArr: couldn't create one of the entities." );
1453 
1454  *new_entity_handles_size = num_ents;
1455  *status_size = num_ents;
1456 
1457  if( MBIMESHI->AdjTable[5] || MBIMESHI->AdjTable[10] )
1458  {
1459  Range set_ents;
1460  std::copy( HANDLE_ARRAY_PTR( *new_entity_handles ),
1461  HANDLE_ARRAY_PTR( *new_entity_handles ) + *new_entity_handles_size, range_inserter( set_ents ) );
1462  result = create_int_ents( MBIMESHI, set_ents );CHKERR( result, "" );
1463  }
1464 
1465  RETURN( iBase_SUCCESS );
1466 }
1467 
1469  /*in*/ const iBase_EntityHandle* entity_handles,
1470  /*in*/ const int entity_handles_size,
1471  int* err )
1472 {
1473  if( 0 == entity_handles_size )
1474  {
1475  RETURN( iBase_SUCCESS );
1476  }
1477 
1478  ErrorCode result = MOABI->delete_entities( CONST_HANDLE_ARRAY_PTR( entity_handles ), entity_handles_size );CHKERR( result, "iMesh_deleteEntArr: trouble deleting entities." );
1479 
1480  RETURN( iBase_SUCCESS );
1481 }
1482 
1484  /*in*/ const char* tag_name,
1485  /*in*/ const int tag_size,
1486  /*in*/ const int tag_type,
1487  /*out*/ iBase_TagHandle* tag_handle,
1488  int* err,
1489  const int tag_name_size )
1490 {
1491  iMesh_createTagWithOptions( instance, tag_name, NULL, tag_size, tag_type, tag_handle, err, tag_name_size, 0 );
1492 }
1493 
1495  /*in*/ iBase_TagHandle tag_handle,
1496  /*in*/ const int forced,
1497  int* err )
1498 {
1499  // might need to check if it's used first
1500  if( false == forced )
1501  {
1502  Range ents;
1503  ErrorCode result;
1504  Tag this_tag = TAG_HANDLE( tag_handle );
1505  for( EntityType this_type = MBVERTEX; this_type != MBMAXTYPE; this_type++ )
1506  {
1507  result = MOABI->get_entities_by_type_and_tag( 0, this_type, &this_tag, NULL, 1, ents, Interface::UNION );CHKERR( result, "iMesh_destroyTag: problem finding tag." );
1508  if( !ents.empty() )
1509  {
1510  ERROR( iBase_TAG_IN_USE, "iMesh_destroyTag: forced=false and entities"
1511  " are still assigned this tag." );
1512  }
1513  }
1514  // check if tag value is set on mesh
1515  const void* data_ptr;
1516  EntityHandle root = 0;
1517  result = MOABI->tag_get_by_ptr( this_tag, &root, 1, &data_ptr );
1518  if( MB_SUCCESS == result )
1519  ERROR( iBase_TAG_IN_USE, "iMesh_destroyTag: forced=false and mesh"
1520  " is still assigned this tag." );
1521  }
1522 
1523  // ok, good to go - either forced or no entities with this tag
1524  ErrorCode result = MOABI->tag_delete( TAG_HANDLE( tag_handle ) );
1525  if( MB_SUCCESS != result && MB_TAG_NOT_FOUND != result ) ERROR( result, "iMesh_destroyTag: problem deleting tag." );
1526 
1527  if( MB_SUCCESS == result ) MBIMESHI->note_tag_destroyed( TAG_HANDLE( tag_handle ) );
1528 
1529  RETURN( iBase_ERROR_MAP[result] );
1530 }
1531 
1533  /*in*/ const iBase_TagHandle tag_handle,
1534  char* out_data,
1535  int* err,
1536  int out_data_len )
1537 {
1538  static ::std::string name;
1539  ErrorCode result = MOABI->tag_get_name( TAG_HANDLE( tag_handle ), name );CHKERR( result, "iMesh_getTagName: problem getting name." );
1540 
1541  strncpy( out_data, name.c_str(), out_data_len );
1542  RETURN( iBase_SUCCESS );
1543 }
1544 
1546  /*in*/ const iBase_TagHandle tag_handle,
1547  int* value_type,
1548  int* err )
1549 {
1550  DataType this_type;
1551  ErrorCode result = MOABI->tag_get_data_type( TAG_HANDLE( tag_handle ), this_type );CHKERR( result, "iMesh_getTagType: problem getting type." );
1552 
1553  if( this_type != MB_TYPE_HANDLE )
1554  *value_type = tstt_data_type_table[this_type];
1555  else if( MBIMESHI->is_set_handle_tag( TAG_HANDLE( tag_handle ) ) )
1556  *value_type = iBase_ENTITY_SET_HANDLE;
1557  else if( MBIMESHI->is_ent_handle_tag( TAG_HANDLE( tag_handle ) ) )
1558  *value_type = iBase_ENTITY_HANDLE;
1559  else
1560  {
1561  result = check_handle_tag_type( TAG_HANDLE( tag_handle ), MBIMESHI );CHKERR( result, "iMesh_getTagType: problem guessing handle tag subtype" );
1562  if( MBIMESHI->is_set_handle_tag( TAG_HANDLE( tag_handle ) ) )
1563  *value_type = iBase_ENTITY_SET_HANDLE;
1564  else
1565  *value_type = iBase_ENTITY_HANDLE;
1566  }
1567 
1568  RETURN( iBase_SUCCESS );
1569 }
1570 
1572  /*in*/ const iBase_TagHandle tag_handle,
1573  int* tag_size_val,
1574  int* err )
1575 {
1576  ErrorCode result = MOABI->tag_get_length( TAG_HANDLE( tag_handle ), *tag_size_val );CHKERR( result, "iMesh_getTagSize: problem getting size." );
1577 
1578  RETURN( iBase_SUCCESS );
1579 }
1580 
1582  /*in*/ const iBase_TagHandle tag_handle,
1583  int* tag_size_bytes,
1584  int* err )
1585 {
1586  ErrorCode result = MOABI->tag_get_bytes( TAG_HANDLE( tag_handle ), *tag_size_bytes );CHKERR( result, "iMesh_getTagSize: problem getting size." );
1587 
1588  RETURN( iBase_SUCCESS );
1589 }
1590 
1592  /*in*/ const char* tag_name,
1593  iBase_TagHandle* tag_handle,
1594  int* err,
1595  const int tag_name_len )
1596 {
1597  std::string tmp_tagname( tag_name, tag_name_len );
1598  eatwhitespace( tmp_tagname );
1599 
1600  ErrorCode result = MOABI->tag_get_handle( tmp_tagname.c_str(), 0, MB_TYPE_OPAQUE, (Tag&)*tag_handle, MB_TAG_ANY );
1601 
1602  if( MB_SUCCESS != result )
1603  {
1604  std::string msg( "iMesh_getTagHandle: problem getting handle for tag named '" );
1605  msg += std::string( tag_name ) + std::string( "'" );
1606  *tag_handle = 0;
1607  ERROR( result, msg.c_str() );
1608  }
1609 
1610  // do not return variable-length tags through ITAPS API
1611  int size;
1612  if( MB_SUCCESS != MOABI->tag_get_length( TAG_HANDLE( *tag_handle ), size ) ) RETURN( iBase_TAG_NOT_FOUND );
1613 
1614  RETURN( iBase_SUCCESS );
1615 }
1616 
1618  /*inout*/ iBase_TagHandle** tag_handles,
1619  /*inout*/ int* tag_handles_allocated,
1620  /*out*/ int* tag_handles_size,
1621  int* err )
1622 {
1623  std::vector< Tag > all_tags;
1624 
1625  ErrorCode result = MOABI->tag_get_tags( all_tags );CHKERR( result, "iMesh_getAllIfaceTags failed." );
1626 
1627  remove_var_len_tags( MOABI, all_tags );
1628 
1629  // now put those tag handles into sidl array
1630  ALLOC_CHECK_ARRAY_NOFAIL( tag_handles, all_tags.size() );
1631  memcpy( *tag_handles, &all_tags[0], all_tags.size() * sizeof( Tag ) );
1632  *tag_handles_size = all_tags.size();
1633 
1634  RETURN( iBase_SUCCESS );
1635 }
1636 
1638  /*in*/ iBase_EntitySetHandle entity_set_handle,
1639  /*in*/ const iBase_TagHandle tag_handle,
1640  /*in*/ const void* tag_value,
1641  /*in*/ const int,
1642  int* err )
1643 {
1644  ErrorCode result;
1645 
1646  EntityHandle set = ENTITY_HANDLE( entity_set_handle );
1647  result = MOABI->tag_set_data( TAG_HANDLE( tag_handle ), &set, 1, tag_value );CHKERR( result, "iMesh_setEntSetData: error" );
1648 
1649  RETURN( iBase_SUCCESS );
1650 }
1651 
1653  /*in*/ iBase_EntitySetHandle entity_set,
1654  /*in*/ const iBase_TagHandle tag_handle,
1655  /*in*/ const int tag_value,
1656  int* err )
1657 {
1658  CHKTAGTYPE( tag_handle, iBase_INTEGER );
1659  iMesh_setEntSetData( instance, entity_set, tag_handle, &tag_value, sizeof( int ), err );
1660 }
1661 
1663  /*in*/ iBase_EntitySetHandle entity_set,
1664  /*in*/ const iBase_TagHandle tag_handle,
1665  /*in*/ const double tag_value,
1666  int* err )
1667 {
1668  CHKTAGTYPE( tag_handle, iBase_DOUBLE );
1669  iMesh_setEntSetData( instance, entity_set, tag_handle, &tag_value, sizeof( double ), err );
1670 }
1671 
1673  /*in*/ iBase_EntitySetHandle entity_set,
1674  /*in*/ const iBase_TagHandle tag_handle,
1675  /*in*/ const iBase_EntityHandle tag_value,
1676  int* err )
1677 {
1678  // XXX: decide how best to handle validating entity handles as tag data
1679  CHKNONEMPTY();
1680  CHKTAGTYPE( tag_handle, iBase_ENTITY_HANDLE );
1681  iMesh_setEntSetData( instance, entity_set, tag_handle, &tag_value, sizeof( iBase_EntityHandle ), err );
1682 }
1683 
1685  /*in*/ iBase_EntitySetHandle entity_set,
1686  /*in*/ const iBase_TagHandle tag_handle,
1687  /*in*/ const iBase_EntitySetHandle tag_value,
1688  int* err )
1689 {
1690  CHKTAGTYPE( tag_handle, iBase_ENTITY_SET_HANDLE );
1691  iMesh_setEntSetData( instance, entity_set, tag_handle, &tag_value, sizeof( iBase_EntitySetHandle ), err );
1692 }
1693 
1695  /*in*/ const iBase_EntitySetHandle entity_set_handle,
1696  /*in*/ const iBase_TagHandle tag_handle,
1697  /*inout*/ void* tag_value,
1698  /*inout*/ int* tag_value_allocated,
1699  /*inout*/ int* tag_value_size,
1700  int* err )
1701 {
1702  EntityHandle eh = ENTITY_HANDLE( entity_set_handle );
1703  Tag tag = TAG_HANDLE( tag_handle );
1704 
1705  int tag_size;
1706  ErrorCode result = MOABI->tag_get_bytes( tag, tag_size );CHKERR( result, "iMesh_getEntSetData: couldn't get tag size." );
1707 
1708  ALLOC_CHECK_TAG_ARRAY( tag_value, tag_size );
1709 
1710  result = MOABI->tag_get_data( tag, &eh, 1, *static_cast< void** >( tag_value ) );
1711 
1712  CHKERR( result, "iMesh_getEntSetData didn't succeed." );
1713  KEEP_ARRAY( tag_value );
1714  RETURN( iBase_SUCCESS );
1715 }
1716 
1718  /*in*/ const iBase_EntitySetHandle entity_set,
1719  /*in*/ const iBase_TagHandle tag_handle,
1720  int* out_data,
1721  int* err )
1722 {
1723  CHKTAGTYPE( tag_handle, iBase_INTEGER );
1724  void* tag_ptr = out_data;
1725  int dum_size = sizeof( int );
1726  iMesh_getEntSetData( instance, entity_set, tag_handle, &tag_ptr, &dum_size, &dum_size, err );
1727 }
1728 
1730  /*in*/ const iBase_EntitySetHandle entity_set,
1731  /*in*/ const iBase_TagHandle tag_handle,
1732  double* out_data,
1733  int* err )
1734 {
1735  CHKTAGTYPE( tag_handle, iBase_DOUBLE );
1736  void* tag_ptr = out_data;
1737  int tag_size = sizeof( double );
1738  iMesh_getEntSetData( instance, entity_set, tag_handle, &tag_ptr, &tag_size, &tag_size, err );
1739 }
1740 
1742  /*in*/ const iBase_EntitySetHandle entity_set,
1743  /*in*/ const iBase_TagHandle tag_handle,
1744  iBase_EntityHandle* out_data,
1745  int* err )
1746 {
1747  CHKTAGTYPE( tag_handle, iBase_ENTITY_HANDLE );
1748  void* tag_ptr = out_data;
1749  int tag_size = sizeof( EntityHandle );
1750  iMesh_getEntSetData( instance, entity_set, tag_handle, &tag_ptr, &tag_size, &tag_size, err );
1751 }
1752 
1754  /*in*/ const iBase_EntitySetHandle entity_set,
1755  /*in*/ const iBase_TagHandle tag_handle,
1756  iBase_EntitySetHandle* out_data,
1757  int* err )
1758 {
1759  CHKTAGTYPE( tag_handle, iBase_ENTITY_SET_HANDLE );
1760  void* tag_ptr = out_data;
1761  int tag_size = sizeof( EntityHandle );
1762  iMesh_getEntSetData( instance, entity_set, tag_handle, &tag_ptr, &tag_size, &tag_size, err );
1763 }
1764 
1766  /*in*/ const iBase_EntitySetHandle entity_set_handle,
1767  /*out*/ iBase_TagHandle** tag_handles,
1768  /*out*/ int* tag_handles_allocated,
1769  /*out*/ int* tag_handles_size,
1770  int* err )
1771 {
1772  EntityHandle eh = ENTITY_HANDLE( entity_set_handle );
1773  std::vector< Tag > all_tags;
1774 
1775  ErrorCode result = MOABI->tag_get_tags_on_entity( eh, all_tags );CHKERR( result, "iMesh_entitysetGetAllTagHandles failed." );
1776 
1777  remove_var_len_tags( MOABI, all_tags );
1778 
1779  // now put those tag handles into sidl array
1780  ALLOC_CHECK_ARRAY_NOFAIL( tag_handles, all_tags.size() );
1781  memcpy( *tag_handles, &all_tags[0], all_tags.size() * sizeof( Tag ) );
1782 
1783  *tag_handles_size = (int)all_tags.size();
1784  RETURN( iBase_SUCCESS );
1785 }
1786 
1788  /*in*/ iBase_EntitySetHandle entity_set_handle,
1789  /*in*/ const iBase_TagHandle tag_handle,
1790  int* err )
1791 {
1792  EntityHandle set = ENTITY_HANDLE( entity_set_handle );
1793  ErrorCode result = MOABI->tag_delete_data( TAG_HANDLE( tag_handle ), &set, 1 );
1794 
1795  // don't return an error if the tag simply wasn't set on the ent set
1796  if( MB_TAG_NOT_FOUND == result )
1797  RETURN( iBase_SUCCESS );
1798  else
1799  RETURN( iBase_ERROR_MAP[result] );
1800 }
1801 
1803  /*in*/ iBase_EntityHandle vertex_handle,
1804  /*in*/ const double x,
1805  /*in*/ const double y,
1806  /*in*/ const double z,
1807  int* err )
1808 
1809 {
1810  const double xyz[3] = { x, y, z };
1811  int geom_dim;
1812  MOABI->get_dimension( geom_dim );
1813 
1814  iMesh_setVtxArrCoords( instance, &vertex_handle, 1, iBase_BLOCKED, xyz, geom_dim, err );
1815 }
1816 
1818  /*in*/ const double x,
1819  /*in*/ const double y,
1820  /*in*/ const double z,
1821  /*out*/ iBase_EntityHandle* new_vertex_handle,
1822  int* err )
1823 {
1824  int dum = 1;
1825  const double xyz[3] = { x, y, z };
1826  int geom_dim;
1827  MOABI->get_dimension( geom_dim );
1828  iMesh_createVtxArr( instance, 1, iBase_BLOCKED, xyz, geom_dim, &new_vertex_handle, &dum, &dum, err );
1829 }
1830 
1832  /*in*/ const int new_entity_topology,
1833  /*in*/ const iBase_EntityHandle* lower_order_entity_handles,
1834  /*in*/ const int lower_order_entity_handles_size,
1835  /*out*/ iBase_EntityHandle* new_entity_handle,
1836  /*out*/ int* status,
1837  int* err )
1838 {
1839  if( 0 == lower_order_entity_handles_size )
1840  {
1841  ERROR( iBase_INVALID_ENTITY_COUNT, "iMesh_createEnt: need more than zero lower order entities." );
1842  }
1843 
1844  // call directly to allow creation of higher-order entities
1845  // directly from connectivity
1846  EntityType this_type = mb_topology_table[new_entity_topology];
1847  EntityHandle tmp_ent;
1848  ErrorCode result = MOABI->create_element( this_type, CONST_HANDLE_ARRAY_PTR( lower_order_entity_handles ),
1849  lower_order_entity_handles_size, tmp_ent );
1850  if( MB_SUCCESS == result )
1851  {
1852  *new_entity_handle = reinterpret_cast< iBase_EntityHandle >( tmp_ent );
1853  *status = iBase_NEW;
1854 
1855  if( MBIMESHI->AdjTable[5] || MBIMESHI->AdjTable[10] )
1856  {
1857  Range set_ents;
1858  set_ents.insert( tmp_ent );
1859  create_int_ents( MBIMESHI, set_ents );
1860  }
1861 
1862  RETURN( iBase_SUCCESS );
1863  }
1864  else
1865  {
1866  *new_entity_handle = 0;
1867  *status = iBase_CREATION_FAILED;
1868  ERROR( result, "iMesh_createEnt: couldn't create entity" );
1869  }
1870 }
1871 
1873  /*in*/ iBase_EntityHandle entity_handle,
1874  int* err )
1875 {
1876  iMesh_deleteEntArr( instance, &entity_handle, 1, err );
1877 }
1878 
1880  /*in*/ const iBase_EntityHandle* entity_handles,
1881  /*in*/ const int entity_handles_size,
1882  /*in*/ const iBase_TagHandle tag_handle,
1883  /*inout*/ void* tag_values,
1884  /*inout*/ int* tag_values_allocated,
1885  /*out*/ int* tag_values_size,
1886  int* err )
1887 {
1888  if( 0 == entity_handles_size ) RETURN( iBase_SUCCESS );
1889  CHKNONEMPTY();
1890 
1891  const EntityHandle* ents = reinterpret_cast< const EntityHandle* >( entity_handles );
1892  Tag tag = TAG_HANDLE( tag_handle );
1893 
1894  int tag_size;
1895  ErrorCode result = MOABI->tag_get_bytes( tag, tag_size );
1896  if( MB_SUCCESS != result )
1897  {
1898  int nerr = -1;
1899  char tagn[64], msg[256];
1900  iMesh_getTagName( instance, tag_handle, tagn, &nerr, sizeof( tagn ) );
1901  snprintf( msg, sizeof( msg ), "iMesh_getArrData: couldn't get size for tag \"%s\"",
1902  nerr == 0 ? tagn : "unknown" );
1903  ERROR( result, msg );
1904  }
1905 
1906  ALLOC_CHECK_TAG_ARRAY( tag_values, tag_size * entity_handles_size );
1907 
1908  result = MOABI->tag_get_data( tag, ents, entity_handles_size, *static_cast< void** >( tag_values ) );
1909 
1910  if( MB_SUCCESS != result )
1911  {
1912  std::string message( "iMesh_getArrData: " );
1913  if( MB_TAG_NOT_FOUND == result )
1914  message += "tag not found";
1915  else
1916  message += "failed";
1917 
1918  std::string name;
1919  if( MB_SUCCESS == MOABI->tag_get_name( tag, name ) )
1920  {
1921  message += "for tag \"";
1922  message += name;
1923  message += "\".";
1924  }
1925  ERROR( result, message.c_str() );
1926  }
1927 
1928  KEEP_ARRAY( tag_values );
1929  RETURN( iBase_SUCCESS );
1930 }
1931 
1933  /*in*/ const iBase_EntityHandle* entity_handles,
1934  /*in*/ const int entity_handles_size,
1935  /*in*/ const iBase_TagHandle tag_handle,
1936  /*inout*/ int** tag_values,
1937  /*inout*/ int* tag_values_allocated,
1938  /*out*/ int* tag_values_size,
1939  int* err )
1940 {
1941  CHKTAGTYPE( tag_handle, iBase_INTEGER );
1942  *tag_values_allocated *= sizeof( int );
1943  if( tag_values_size != tag_values_allocated ) *tag_values_size *= sizeof( int );
1944  iMesh_getArrData( instance, entity_handles, entity_handles_size, tag_handle, tag_values, tag_values_allocated,
1945  tag_values_size, err );
1946  *tag_values_allocated /= sizeof( int );
1947  if( tag_values_size != tag_values_allocated ) *tag_values_size /= sizeof( int );
1948 }
1949 
1951  /*in*/ const iBase_EntityHandle* entity_handles,
1952  /*in*/ const int entity_handles_size,
1953  /*in*/ const iBase_TagHandle tag_handle,
1954  /*inout*/ double** tag_values,
1955  /*inout*/ int* tag_values_allocated,
1956  /*out*/ int* tag_values_size,
1957  int* err )
1958 {
1959  CHKTAGTYPE( tag_handle, iBase_DOUBLE );
1960  *tag_values_allocated *= sizeof( double );
1961  if( tag_values_size != tag_values_allocated ) *tag_values_size *= sizeof( double );
1962  iMesh_getArrData( instance, entity_handles, entity_handles_size, tag_handle, tag_values, tag_values_allocated,
1963  tag_values_size, err );
1964  *tag_values_allocated /= sizeof( double );
1965  if( tag_values_size != tag_values_allocated ) *tag_values_size /= sizeof( double );
1966 }
1967 
1969  /*in*/ const iBase_EntityHandle* entity_handles,
1970  /*in*/ const int entity_handles_size,
1971  /*in*/ const iBase_TagHandle tag_handle,
1972  /*inout*/ iBase_EntityHandle** tag_value,
1973  /*inout*/ int* tag_value_allocated,
1974  /*out*/ int* tag_value_size,
1975  int* err )
1976 {
1977  CHKTAGTYPE( tag_handle, iBase_ENTITY_HANDLE );
1978  *tag_value_allocated *= sizeof( iBase_EntityHandle );
1979  if( tag_value_size != tag_value_allocated ) *tag_value_size *= sizeof( iBase_EntityHandle );
1980  iMesh_getArrData( instance, entity_handles, entity_handles_size, tag_handle,
1981  reinterpret_cast< void** >( tag_value ), tag_value_allocated, tag_value_size, err );
1982  *tag_value_allocated /= sizeof( iBase_EntityHandle );
1983  if( tag_value_size != tag_value_allocated ) *tag_value_size /= sizeof( iBase_EntityHandle );
1984 }
1985 
1987  /*in*/ const iBase_EntityHandle* entity_handles,
1988  /*in*/ const int entity_handles_size,
1989  /*in*/ const iBase_TagHandle tag_handle,
1990  /*inout*/ iBase_EntitySetHandle** tag_value,
1991  /*inout*/ int* tag_value_allocated,
1992  /*out*/ int* tag_value_size,
1993  int* err )
1994 {
1995  CHKTAGTYPE( tag_handle, iBase_ENTITY_SET_HANDLE );
1996  *tag_value_allocated *= sizeof( iBase_EntityHandle );
1997  if( tag_value_size != tag_value_allocated ) *tag_value_size *= sizeof( iBase_EntityHandle );
1998  iMesh_getArrData( instance, entity_handles, entity_handles_size, tag_handle,
1999  reinterpret_cast< void** >( tag_value ), tag_value_allocated, tag_value_size, err );
2000  *tag_value_allocated /= sizeof( iBase_EntityHandle );
2001  if( tag_value_size != tag_value_allocated ) *tag_value_size /= sizeof( iBase_EntityHandle );
2002 }
2003 
2005  /*in*/ const iBase_EntityHandle* entity_handles,
2006  /*in*/ const int entity_handles_size,
2007  /*in*/ const iBase_TagHandle tag_handle,
2008  /*in*/ const void* tag_values,
2009  /*in*/ const int tag_values_size,
2010  int* err )
2011 {
2012  if( 0 == entity_handles_size ) RETURN( iBase_SUCCESS );
2013  CHKNONEMPTY();
2014 
2015  int tag_size;
2016  iMesh_getTagSizeBytes( instance, tag_handle, &tag_size, err );
2017  // Check err manually and just return if not iBase_SUCCESS to not step on
2018  // the error set in iMesh_getTagSizeBytes().
2019  if( iBase_SUCCESS != *err ) return;
2020 
2021  if( tag_values_size != ( tag_size * entity_handles_size ) )
2022  {
2023  ERROR( iBase_BAD_ARRAY_SIZE, "iMesh_setArrData: bad tag_values_size passed." );
2024  }
2025 
2026  ErrorCode result = MOABI->tag_set_data( TAG_HANDLE( tag_handle ), CONST_HANDLE_ARRAY_PTR( entity_handles ),
2027  entity_handles_size, tag_values );CHKERR( result, "iMesh_setArrData didn't succeed." );
2028  RETURN( iBase_SUCCESS );
2029 }
2030 
2032  /*in*/ const iBase_EntityHandle* entity_handles,
2033  /*in*/ const int entity_handles_size,
2034  /*in*/ const iBase_TagHandle tag_handle,
2035  /*in*/ const int* tag_values,
2036  /*in*/ const int tag_values_size,
2037  int* err )
2038 {
2039  CHKTAGTYPE( tag_handle, iBase_INTEGER );
2040  iMesh_setArrData( instance, entity_handles, entity_handles_size, tag_handle,
2041  reinterpret_cast< const char* >( tag_values ), sizeof( int ) * tag_values_size, err );
2042 }
2043 
2045  /*in*/ const iBase_EntityHandle* entity_handles,
2046  /*in*/ const int entity_handles_size,
2047  /*in*/ const iBase_TagHandle tag_handle,
2048  /*in*/ const double* tag_values,
2049  /*in*/ const int tag_values_size,
2050  int* err )
2051 {
2052  CHKTAGTYPE( tag_handle, iBase_DOUBLE );
2053  iMesh_setArrData( instance, entity_handles, entity_handles_size, tag_handle,
2054  reinterpret_cast< const char* >( tag_values ), sizeof( double ) * tag_values_size, err );
2055 }
2056 
2058  /*in*/ const iBase_EntityHandle* entity_handles,
2059  /*in*/ const int entity_handles_size,
2060  /*in*/ const iBase_TagHandle tag_handle,
2061  /*in*/ const iBase_EntityHandle* tag_values,
2062  /*in*/ const int tag_values_size,
2063  int* err )
2064 {
2065  CHKTAGTYPE( tag_handle, iBase_ENTITY_HANDLE );
2066  iMesh_setArrData( instance, entity_handles, entity_handles_size, tag_handle,
2067  reinterpret_cast< const char* >( tag_values ), sizeof( iBase_EntityHandle ) * tag_values_size,
2068  err );
2069 }
2070 
2072  /*in*/ const iBase_EntityHandle* entity_handles,
2073  /*in*/ const int entity_handles_size,
2074  /*in*/ const iBase_TagHandle tag_handle,
2075  /*in*/ const iBase_EntitySetHandle* tag_values,
2076  /*in*/ const int tag_values_size,
2077  int* err )
2078 {
2079  CHKTAGTYPE( tag_handle, iBase_ENTITY_SET_HANDLE );
2080  iMesh_setArrData( instance, entity_handles, entity_handles_size, tag_handle,
2081  reinterpret_cast< const char* >( tag_values ), sizeof( iBase_EntityHandle ) * tag_values_size,
2082  err );
2083 }
2084 
2086  /*in*/ const iBase_EntityHandle* entity_handles,
2087  /*in*/ const int entity_handles_size,
2088  /*in*/ const iBase_TagHandle tag_handle,
2089  int* err )
2090 {
2091  if( 0 == entity_handles_size ) RETURN( iBase_SUCCESS );
2092  CHKNONEMPTY();
2093 
2094  ErrorCode result = MOABI->tag_delete_data( TAG_HANDLE( tag_handle ), CONST_HANDLE_ARRAY_PTR( entity_handles ),
2095  entity_handles_size );
2096 
2097  // don't return an error if the tag simply wasn't set on the entities
2098  if( MB_TAG_NOT_FOUND == result )
2099  RETURN( iBase_SUCCESS );
2100  else
2101  RETURN( iBase_ERROR_MAP[result] );
2102 }
2103 
2105  /*in*/ const iBase_EntityHandle entity_handle,
2106  /*in*/ const iBase_TagHandle tag_handle,
2107  /*out*/ void* tag_value,
2108  /*inout*/ int* tag_value_allocated,
2109  /*out*/ int* tag_value_size,
2110  int* err )
2111 {
2112  iMesh_getArrData( instance, &entity_handle, 1, tag_handle, tag_value, tag_value_allocated, tag_value_size, err );
2113 }
2114 
2116  /*in*/ const iBase_EntityHandle entity_handle,
2117  /*in*/ const iBase_TagHandle tag_handle,
2118  int* out_data,
2119  int* err )
2120 {
2121  CHKTAGTYPE( tag_handle, iBase_INTEGER );
2122  void* val_ptr = out_data;
2123  int val_size = sizeof( int );
2124  iMesh_getArrData( instance, &entity_handle, 1, tag_handle, &val_ptr, &val_size, &val_size, err );
2125 }
2126 
2128  /*in*/ const iBase_EntityHandle entity_handle,
2129  /*in*/ const iBase_TagHandle tag_handle,
2130  double* out_data,
2131  int* err )
2132 {
2133  CHKTAGTYPE( tag_handle, iBase_DOUBLE );
2134  void* val_ptr = out_data;
2135  int val_size = sizeof( double );
2136  iMesh_getArrData( instance, &entity_handle, 1, tag_handle, &val_ptr, &val_size, &val_size, err );
2137 }
2138 
2140  /*in*/ const iBase_EntityHandle entity_handle,
2141  /*in*/ const iBase_TagHandle tag_handle,
2142  iBase_EntityHandle* out_data,
2143  int* err )
2144 {
2145  CHKTAGTYPE( tag_handle, iBase_ENTITY_HANDLE );
2146  void* val_ptr = out_data;
2147  int dum = sizeof( iBase_EntityHandle );
2148  iMesh_getArrData( instance, &entity_handle, 1, tag_handle, &val_ptr, &dum, &dum, err );
2149 }
2150 
2152  /*in*/ const iBase_EntityHandle entity_handle,
2153  /*in*/ const iBase_TagHandle tag_handle,
2154  iBase_EntitySetHandle* out_data,
2155  int* err )
2156 {
2157  CHKTAGTYPE( tag_handle, iBase_ENTITY_SET_HANDLE );
2158  void* val_ptr = out_data;
2159  int dum = sizeof( iBase_EntityHandle );
2160  iMesh_getArrData( instance, &entity_handle, 1, tag_handle, &val_ptr, &dum, &dum, err );
2161 }
2162 
2164  /*in*/ iBase_EntityHandle entity_handle,
2165  /*in*/ const iBase_TagHandle tag_handle,
2166  /*in*/ const void* tag_value,
2167  /*in*/ const int tag_value_size,
2168  int* err )
2169 {
2170  iMesh_setArrData( instance, &entity_handle, 1, tag_handle, tag_value, tag_value_size, err );
2171 }
2172 
2174  /*in*/ iBase_EntityHandle entity_handle,
2175  /*in*/ const iBase_TagHandle tag_handle,
2176  /*in*/ const int tag_value,
2177  int* err )
2178 {
2179  CHKTAGTYPE( tag_handle, iBase_INTEGER );
2180  iMesh_setArrData( instance, &entity_handle, 1, tag_handle, reinterpret_cast< const char* >( &tag_value ),
2181  sizeof( int ), err );
2182 }
2183 
2185 
2186  /*in*/ iBase_EntityHandle entity_handle,
2187  /*in*/ const iBase_TagHandle tag_handle,
2188  /*in*/ const double tag_value,
2189  int* err )
2190 {
2191  CHKTAGTYPE( tag_handle, iBase_DOUBLE );
2192  iMesh_setArrData( instance, &entity_handle, 1, tag_handle, reinterpret_cast< const char* >( &tag_value ),
2193  sizeof( double ), err );
2194 }
2195 
2197  /*in*/ iBase_EntityHandle entity_handle,
2198  /*in*/ const iBase_TagHandle tag_handle,
2199  /*in*/ const iBase_EntityHandle tag_value,
2200  int* err )
2201 {
2202  CHKTAGTYPE( tag_handle, iBase_ENTITY_HANDLE );
2203  iMesh_setArrData( instance, &entity_handle, 1, tag_handle, reinterpret_cast< const char* >( &tag_value ),
2204  sizeof( iBase_EntityHandle ), err );
2205 }
2206 
2208  /*in*/ iBase_EntityHandle entity_handle,
2209  /*in*/ const iBase_TagHandle tag_handle,
2210  /*in*/ const iBase_EntitySetHandle tag_value,
2211  int* err )
2212 {
2213  CHKTAGTYPE( tag_handle, iBase_ENTITY_SET_HANDLE );
2214  iMesh_setArrData( instance, &entity_handle, 1, tag_handle, reinterpret_cast< const char* >( &tag_value ),
2215  sizeof( iBase_EntityHandle ), err );
2216 }
2217 
2219  /*in*/ const iBase_EntityHandle entity_handle,
2220  /*inout*/ iBase_TagHandle** tag_handles,
2221  /*inout*/ int* tag_handles_allocated,
2222  /*out*/ int* tag_handles_size,
2223  int* err )
2224 {
2225  std::vector< Tag > all_tags;
2226 
2227  ErrorCode result = MOABI->tag_get_tags_on_entity( ENTITY_HANDLE( entity_handle ), all_tags );CHKERR( result, "iMesh_getAllTags failed." );
2228 
2229  remove_var_len_tags( MOABI, all_tags );
2230 
2231  // now put those tag handles into sidl array
2232  ALLOC_CHECK_ARRAY_NOFAIL( tag_handles, all_tags.size() );
2233  memcpy( *tag_handles, &all_tags[0], all_tags.size() * sizeof( Tag ) );
2234  *tag_handles_size = all_tags.size();
2235 
2236  RETURN( iBase_SUCCESS );
2237 }
2238 
2240  /*in*/ iBase_EntityHandle entity_handle,
2241  /*in*/ const iBase_TagHandle tag_handle,
2242  int* err )
2243 {
2244  iMesh_rmvArrTag( instance, &entity_handle, 1, tag_handle, err );
2245 }
2246 
2248  /*in*/ const iBase_EntitySetHandle entity_set_handle,
2249  /*in*/ const int requested_entity_type,
2250  /*in*/ const int requested_entity_topology,
2251  /*in*/ const int resilient,
2252  /*out*/ iBase_EntityIterator* entity_iterator,
2253  int* err )
2254 {
2255  iMesh_initEntArrIterRec( instance, entity_set_handle, requested_entity_type, requested_entity_topology, 1,
2256  resilient, false, reinterpret_cast< iBase_EntityArrIterator* >( entity_iterator ), err );
2257 }
2258 
2260  /*in*/ iBase_EntityIterator entity_iterator,
2261  /*out*/ iBase_EntityHandle* entity_handle,
2262  int* is_end,
2263  int* err )
2264 {
2265  int eh_size = 1;
2266  iMesh_getNextEntArrIter( instance, reinterpret_cast< iBase_EntityArrIterator >( entity_iterator ), &entity_handle,
2267  &eh_size, &eh_size, is_end, err );
2268 }
2269 
2271  /*in*/ iBase_EntityIterator entity_iterator,
2272  int* err )
2273 {
2274  iMesh_resetEntArrIter( instance, reinterpret_cast< iBase_EntityArrIterator >( entity_iterator ), err );
2275 }
2276 
2278  /*in*/ iBase_EntityIterator entity_iterator,
2279  int* err )
2280 {
2281  iMesh_endEntArrIter( instance, reinterpret_cast< iBase_EntityArrIterator >( entity_iterator ), err );
2282 }
2283 
2285  /*in*/ const iBase_EntityHandle entity_handle,
2286  int* out_topo,
2287  int* err )
2288 {
2289  *out_topo = tstt_topology_table[MOABI->type_from_handle( ENTITY_HANDLE( entity_handle ) )];
2290  RETURN( iBase_SUCCESS );
2291 }
2292 
2294  /*in*/ const iBase_EntityHandle entity_handle,
2295  int* out_type,
2296  int* err )
2297 {
2298  *out_type = tstt_type_table[MOABI->type_from_handle( ENTITY_HANDLE( entity_handle ) )];
2299  RETURN( iBase_SUCCESS );
2300 }
2301 
2303  /*in*/ const iBase_EntityHandle vertex_handle,
2304  /*out*/ double* x,
2305  /*out*/ double* y,
2306  /*out*/ double* z,
2307  int* err )
2308 {
2309  int order = iBase_BLOCKED;
2310  double xyz[3] = { 0 }, *tmp_xyz = xyz;
2311  int dum = 3;
2312 
2313  iMesh_getVtxArrCoords( instance, &vertex_handle, 1, order, &tmp_xyz, &dum, &dum, err );
2314  if( iBase_SUCCESS == *err )
2315  {
2316  *x = xyz[0];
2317  *y = xyz[1];
2318  *z = xyz[2];
2319  }
2320 }
2321 
2323  /*in*/ const iBase_EntityHandle entity_handle,
2324  /*in*/ const int entity_type_requested,
2325  /*inout*/ iBase_EntityHandle** adj_entity_handles,
2326  /*inout*/ int* adj_entity_handles_allocated,
2327  /*out*/ int* adj_entity_handles_size,
2328  int* err )
2329 {
2330  int offsets[2];
2331  int* offsets_ptr = offsets;
2332  int offset_size, offset_allocated = 2;
2333 
2334  iMesh_getEntArrAdj( instance, &entity_handle, 1, entity_type_requested, adj_entity_handles,
2335  adj_entity_handles_allocated, adj_entity_handles_size, &offsets_ptr, &offset_allocated,
2336  &offset_size, err );
2337 }
2338 
2340  iBase_EntityHandle entity_handle,
2341  int order_adjacent_key,
2342  int requested_entity_type,
2343  iBase_EntityHandle** adj_entities,
2344  int* adj_entities_allocated,
2345  int* adj_entities_size,
2346  int* err )
2347 {
2348  int offsets[2];
2349  int* offsets_ptr = offsets;
2350  int offset_size, offset_allocated = 2;
2351 
2352  iMesh_getEntArr2ndAdj( instance, &entity_handle, 1, order_adjacent_key, requested_entity_type, adj_entities,
2353  adj_entities_allocated, adj_entities_size, &offsets_ptr, &offset_allocated, &offset_size,
2354  err );
2355 }
2356 
2358  /*in*/ const iBase_EntitySetHandle entity_set_1,
2359  /*in*/ const iBase_EntitySetHandle entity_set_2,
2360  /*out*/ iBase_EntitySetHandle* result_entity_set,
2361  int* err )
2362 {
2363  EntityHandle temp_set;
2364  EntityHandle set1 = ENTITY_HANDLE( entity_set_1 ), set2 = ENTITY_HANDLE( entity_set_2 );
2365 
2366  int isList1 = 0, isList2 = 0;
2367  iMesh_isList( instance, entity_set_1, &isList1, err );
2368  if( *err != iBase_SUCCESS ) return;
2369  iMesh_isList( instance, entity_set_2, &isList2, err );
2370  if( *err != iBase_SUCCESS ) return;
2371 
2372  ErrorCode result;
2373  if( isList1 && isList2 )
2374  result = MOABI->create_meshset( MESHSET_ORDERED, temp_set );
2375  else
2376  result = MOABI->create_meshset( MESHSET_SET, temp_set );
2377 
2378  if( MB_SUCCESS != result ) ERROR( result, "iMesh_subtract: couldn't create result set." );
2379 
2380  // if the second set is the root set, the result is always the empty set
2381  if( entity_set_2 )
2382  {
2383  if( !entity_set_1 )
2384  {
2385  // subtracting from the root set, so get everything first...
2386  Range entities;
2387  result = MOABI->get_entities_by_handle( 0, entities );
2388  if( MB_SUCCESS == result ) result = MOABI->add_entities( temp_set, entities );
2389  // ...but not the newly-created set!
2390  if( MB_SUCCESS == result ) result = MOABI->remove_entities( temp_set, &temp_set, 1 );
2391  }
2392  else
2393  result = MOABI->unite_meshset( temp_set, set1 );
2394 
2395  if( MB_SUCCESS == result ) result = MOABI->subtract_meshset( temp_set, set2 );
2396  }
2397 
2398  CHKERR( result, "iMesh_subtract: ERROR subtract failed." );
2399  *result_entity_set = (iBase_EntitySetHandle)temp_set;
2400 
2401  RETURN( iBase_SUCCESS );
2402 }
2403 
2405  /*in*/ const iBase_EntitySetHandle entity_set_1,
2406  /*in*/ const iBase_EntitySetHandle entity_set_2,
2407  /*out*/ iBase_EntitySetHandle* result_entity_set,
2408  int* err )
2409 {
2410  EntityHandle temp_set;
2411  EntityHandle set1 = ENTITY_HANDLE( entity_set_1 ), set2 = ENTITY_HANDLE( entity_set_2 );
2412 
2413  int isList1 = 0, isList2 = 0;
2414  iMesh_isList( instance, entity_set_1, &isList1, err );
2415  if( *err != iBase_SUCCESS ) return;
2416  iMesh_isList( instance, entity_set_2, &isList2, err );
2417  if( *err != iBase_SUCCESS ) return;
2418 
2419  ErrorCode result;
2420  if( isList1 && isList2 )
2421  result = MOABI->create_meshset( MESHSET_ORDERED, temp_set );
2422  else
2423  result = MOABI->create_meshset( MESHSET_SET, temp_set );
2424 
2425  if( MB_SUCCESS != result ) ERROR( result, "iMesh_intersect: couldn't create result set." );
2426 
2427  if( !entity_set_1 && !entity_set_2 )
2428  {
2429  // intersecting the root set with itself, so get everything...
2430  Range entities;
2431  result = MOABI->get_entities_by_handle( 0, entities );
2432  if( MB_SUCCESS == result ) result = MOABI->add_entities( temp_set, entities );
2433  // ...but not the newly-created set!
2434  if( MB_SUCCESS == result ) result = MOABI->remove_entities( temp_set, &temp_set, 1 );
2435  }
2436  else if( !entity_set_1 )
2437  {
2438  result = MOABI->unite_meshset( temp_set, set2 );
2439  }
2440  else if( !entity_set_2 )
2441  {
2442  result = MOABI->unite_meshset( temp_set, set1 );
2443  }
2444  else
2445  {
2446  if( isList1 && isList2 )
2447  {
2448  // ITAPS has very specific rules about the behavior of intersection on
2449  // list-type sets. Since MOAB doesn't (and likely will never) work
2450  // exactly this way, we implement our own algorithm here.
2451 
2452 #ifdef MOAB_HAVE_UNORDERED_MAP
2453  typedef MOAB_UNORDERED_MAP_NS::unordered_map< EntityHandle, size_t > lookup_t;
2454 #else
2455  typedef std::map< EntityHandle, size_t > lookup_t;
2456 #endif
2457 
2458  // First, build a lookup table for the second set.
2459  lookup_t lookup;
2460  {
2461  std::vector< EntityHandle > contents2;
2462  result = MOABI->get_entities_by_handle( set2, contents2 );CHKERR( result, "iMesh_intersect: ERROR intersect failed." );
2463 
2464  for( std::vector< EntityHandle >::iterator i = contents2.begin(); i != contents2.end(); ++i )
2465  {
2466 #ifdef MOAB_HAVE_UNORDERED_MAP
2467  lookup_t::iterator j = lookup.find( *i );
2468 #else
2469  lookup_t::iterator j = lookup.lower_bound( *i );
2470 #endif
2471  if( j != lookup.end() && j->first == *i )
2472  ++j->second;
2473  else
2474  lookup.insert( j, lookup_t::value_type( *i, 1 ) );
2475  }
2476  }
2477 
2478  // Then, iterate over the contents of the first set and check for
2479  // their existence in the second set.
2480  std::vector< EntityHandle > contents1;
2481  result = MOABI->get_entities_by_handle( set1, contents1 );CHKERR( result, "iMesh_intersect: ERROR intersect failed." );
2482 
2483  std::vector< EntityHandle >::iterator w = contents1.begin();
2484  for( std::vector< EntityHandle >::iterator i = contents1.begin(); i != contents1.end(); ++i )
2485  {
2486  lookup_t::iterator j = lookup.find( *i );
2487  if( j != lookup.end() && j->second )
2488  {
2489  --j->second;
2490  *w = *i;
2491  ++w;
2492  }
2493  }
2494 
2495  result = MOABI->add_entities( temp_set, &contents1[0], w - contents1.begin() );
2496  }
2497  else
2498  {
2499  result = MOABI->unite_meshset( temp_set, set1 );
2500  if( MB_SUCCESS == result ) result = MOABI->intersect_meshset( temp_set, set2 );
2501  }
2502  }
2503 
2504  CHKERR( result, "iMesh_intersect: ERROR intersect failed." );
2505  *result_entity_set = (iBase_EntitySetHandle)temp_set;
2506 
2507  RETURN( iBase_SUCCESS );
2508 }
2509 
2511  /*in*/ const iBase_EntitySetHandle entity_set_1,
2512  /*in*/ const iBase_EntitySetHandle entity_set_2,
2513  /*out*/ iBase_EntitySetHandle* result_entity_set,
2514  int* err )
2515 {
2516  EntityHandle temp_set;
2517  EntityHandle set1 = ENTITY_HANDLE( entity_set_1 ), set2 = ENTITY_HANDLE( entity_set_2 );
2518 
2519  int isList1 = 0, isList2 = 0;
2520  iMesh_isList( instance, entity_set_1, &isList1, err );
2521  if( *err != iBase_SUCCESS ) return;
2522  iMesh_isList( instance, entity_set_2, &isList2, err );
2523  if( *err != iBase_SUCCESS ) return;
2524 
2525  ErrorCode result;
2526  if( isList1 && isList2 )
2527  result = MOABI->create_meshset( MESHSET_ORDERED, temp_set );
2528  else
2529  result = MOABI->create_meshset( MESHSET_SET, temp_set );
2530 
2531  if( MB_SUCCESS != result ) ERROR( result, "iMesh_unite: couldn't create result set." );
2532 
2533  if( entity_set_1 && entity_set_2 )
2534  {
2535  result = MOABI->unite_meshset( temp_set, set1 );
2536  if( MB_SUCCESS == result ) result = MOABI->unite_meshset( temp_set, set2 );
2537  }
2538  else
2539  {
2540  // uniting with the root set, so get everything...
2541  Range entities;
2542  result = MOABI->get_entities_by_handle( 0, entities );
2543  if( MB_SUCCESS == result ) result = MOABI->add_entities( temp_set, entities );
2544  // ...but not the newly-created set!
2545  if( MB_SUCCESS == result ) result = MOABI->remove_entities( temp_set, &temp_set, 1 );
2546  }
2547 
2548  CHKERR( result, "iMesh_unite: ERROR unite failed." );
2549 
2550  *result_entity_set = (iBase_EntitySetHandle)temp_set;
2551 
2552  RETURN( iBase_SUCCESS );
2553 }
2554 
2556  /*in*/ const iBase_EntitySetHandle entity_set_handle,
2557  /*in*/ const int entity_type,
2558  /*in*/ const int entity_topology,
2559  /*in*/ const int recursive,
2560  /*out*/ iBase_EntityHandle** entity_handles,
2561  /*out*/ int* entity_handles_allocated,
2562  /*out*/ int* entity_handles_size,
2563  /*out*/ int* err )
2564 {
2567 
2568  bool use_top = false;
2569  // initialize just to get rid of compiler warning
2570  EntityType type = mb_topology_table[iMesh_ALL_TOPOLOGIES];
2571  std::vector< EntityHandle > out_entities;
2572 
2573  if( entity_topology != iMesh_ALL_TOPOLOGIES )
2574  {
2575  type = mb_topology_table[entity_topology];
2576  use_top = true;
2577 
2578  if( entity_type != iBase_ALL_TYPES )
2579  {
2580  if( entity_topology != iMesh_SEPTAHEDRON && entity_type != CN::Dimension( type ) )
2581  ERROR( iBase_BAD_TYPE_AND_TOPO, "type and topology are inconsistant" );
2582 
2583  // Special-case handling for septahedra since we don't support them
2584  else if( entity_topology == iMesh_SEPTAHEDRON && entity_type != iBase_REGION )
2585  ERROR( iBase_BAD_TYPE_AND_TOPO, "type and topology are inconsistant" );
2586  }
2587  }
2588 
2589  EntityHandle handle = ENTITY_HANDLE( entity_set_handle );
2590  ErrorCode result;
2591 
2592  if( use_top )
2593  {
2594  if( entity_topology == iMesh_SEPTAHEDRON )
2595  result = MB_SUCCESS; // MOAB doesn't do septahedrons, so there are never any.
2596  else
2597  result = MOABI->get_entities_by_type( handle, type, out_entities, recursive );
2598  }
2599  else if( entity_type != iBase_ALL_TYPES )
2600  result = MOABI->get_entities_by_dimension( handle, entity_type, out_entities, recursive );
2601  else
2602  result = MOABI->get_entities_by_handle( handle, out_entities, recursive );
2603 
2604  CHKERR( result, "iMesh_GetEntities:ERROR getting entities." );
2605 
2606  // remove entity sets from the result list
2607  std::vector< EntityHandle >::iterator iter, end_iter;
2608  if( iBase_ALL_TYPES == entity_type && iMesh_ALL_TOPOLOGIES == entity_topology )
2609  {
2610  for( iter = out_entities.begin(); iter != out_entities.end() && TYPE_FROM_HANDLE( *iter ) != MBENTITYSET;
2611  ++iter )
2612  ;
2613  for( end_iter = iter; iter != out_entities.end(); ++iter )
2614  if( TYPE_FROM_HANDLE( *iter ) != MBENTITYSET ) *( end_iter++ ) = *iter;
2615  out_entities.erase( end_iter, out_entities.end() );
2616  }
2617 
2618  int num_ents = out_entities.size();
2619 
2620  ALLOC_CHECK_ARRAY_NOFAIL( entity_handles, num_ents );
2621 
2622  int k = 0;
2623 
2624  // filter out entity sets here
2625  for( iter = out_entities.begin(); iter != out_entities.end(); ++iter )
2626  ( *entity_handles )[k++] = (iBase_EntityHandle)*iter;
2627 
2628  // now it's safe to set the size; set it to k, not out_entities.size(), to
2629  // account for sets which might have been removed
2630  *entity_handles_size = k;
2631 
2632  RETURN( iBase_SUCCESS );
2633 }
2634 
2635 /**\brief Get the number of entities with the specified type in the instance or set, recursive
2636  *
2637  * Get the number of entities with the specified type in the instance
2638  * or set. If recursive is passed in non-zero, includes entities in owned sets.
2639  * If entity set handle is zero, return information for instance,
2640  * otherwise for set. Value of entity type must be from the
2641  * iBase_EntityType enumeration. If iBase_ALL_TYPES is specified,
2642  * total number of entities (excluding entity sets) is returned.
2643  * \param instance iMesh instance handle
2644  * \param entity_set_handle Entity set being queried
2645  * \param entity_type Type of entity requested
2646  * \param recursive If non-zero, includes entities in owned sets too
2647  * \param num_type Pointer to number of entities, returned from function
2648  * \param *err Pointer to error type returned from function
2649  */
2651  /*in*/ const iBase_EntitySetHandle entity_set_handle,
2652  /*in*/ const int entity_type,
2653  /*in*/ const int recursive,
2654  /*out*/ int* num_type,
2655  /*out*/ int* err )
2656 {
2658 
2659  *num_type = 0;
2660  ErrorCode result;
2661  if( entity_type == iBase_ALL_TYPES )
2662  {
2663  result = MOABI->get_number_entities_by_handle( ENTITY_HANDLE( entity_set_handle ), *num_type, recursive );
2664  if( MB_SUCCESS == result && !recursive )
2665  {
2666  int num_sets = 0;
2667  result = MOABI->get_number_entities_by_type( ENTITY_HANDLE( entity_set_handle ), MBENTITYSET, num_sets,
2668  recursive );
2669  *num_type -= num_sets;
2670  }
2671  }
2672  else
2673  {
2674  result = MOABI->get_number_entities_by_dimension( ENTITY_HANDLE( entity_set_handle ), entity_type, *num_type,
2675  recursive );
2676  }
2677 
2678  CHKERR( result, "iMesh_entitysetGetNumberEntityOfType: "
2679  "ERROR getting number of entities by type." );
2680 
2681  RETURN( iBase_SUCCESS );
2682 }
2683 
2684 /**\brief Get the number of entities with the specified topology in the instance or set
2685  *
2686  * Get the number of entities with the specified topology in the instance
2687  * or set. If recursive is passed in non-zero, includes entities in owned sets.
2688  * If entity set handle is zero, return information for instance,
2689  * otherwise for set. Value of entity topology must be from the
2690  * iMesh_EntityTopology enumeration. If iMesh_ALL_TOPOLOGIES is specified,
2691  * total number of entities (excluding entity sets) is returned.
2692  * \param instance iMesh instance handle
2693  * \param entity_set_handle Entity set being queried
2694  * \param entity_topology Topology of entity requested
2695  * \param recursive If non-zero, includes entities in owned sets too
2696  * \param num_topo Pointer to number of entities, returned from function
2697  * \param *err Pointer to error type returned from function
2698  */
2700  /*in*/ const iBase_EntitySetHandle entity_set_handle,
2701  /*in*/ const int entity_topology,
2702  /*in*/ const int recursive,
2703  /*out*/ int* num_topo,
2704  /*out*/ int* err )
2705 {
2707 
2708  if( entity_topology == iMesh_SEPTAHEDRON )
2709  {
2710  *num_topo = 0;
2711  RETURN( iBase_SUCCESS );
2712  }
2713 
2714  *num_topo = 0;
2715  ErrorCode result;
2716  if( iMesh_ALL_TOPOLOGIES == entity_topology )
2717  {
2718  result = MOABI->get_number_entities_by_handle( ENTITY_HANDLE( entity_set_handle ), *num_topo, recursive );
2719 
2720  if( !recursive && MB_SUCCESS == result )
2721  { // remove entity sets from count
2722  int num_sets;
2723  result = MOABI->get_number_entities_by_type( ENTITY_HANDLE( entity_set_handle ), MBENTITYSET, num_sets,
2724  recursive );
2725  *num_topo -= num_sets;
2726  }
2727  }
2728  else
2729  {
2730  result = MOABI->get_number_entities_by_type( ENTITY_HANDLE( entity_set_handle ),
2731  mb_topology_table[entity_topology], *num_topo, recursive );
2732  }
2733 
2734  CHKERR( result, "iMesh_entitysetGetNumberEntityOfTopology: ERROR getting "
2735  "number of entities by topology." );
2736  RETURN( iBase_SUCCESS );
2737 }
2738 
2739 /**\brief Get entities with specified type, topology, tag(s) and (optionally) tag value(s)
2740  *
2741  * Get entities with the specified type, topology, tag(s), and optionally tag value(s).
2742  * If tag values pointer is input as zero, entities with specified tag(s) are returned,
2743  * regardless of their value.
2744  * \param instance iMesh instance handle
2745  * \param entity_set_handle Entity set being queried
2746  * \param entity_type Type of entities being requested
2747  * \param entity_topology Topology of entities being requested
2748  * \param tag_handles Array of tag handles
2749  * \param tag_vals Array of tag values (zero if values not requested)
2750  * \param num_tags_vals Number of tags and optionally values
2751  * \param recursive If non-zero, gets entities in owned sets too
2752  * \param *entity_handles Pointer to array of entity handles returned
2753  * from function
2754  * \param *entity_handles_allocated Pointer to allocated size of
2755  * entity_handles array
2756  * \param *entity_handles_size Pointer to occupied size of entity_handles array
2757  * \param *err Pointer to error type returned from function
2758  */
2760  /*in*/ const iBase_EntitySetHandle entity_set_handle,
2761  /*in*/ const int entity_type,
2762  /*in*/ const int entity_topology,
2763  /*in*/ const iBase_TagHandle* tag_handles,
2764  /*in*/ const char* const* tag_vals,
2765  /*in*/ const int num_tags_vals,
2766  /*in*/ const int recursive,
2767  /*out*/ iBase_EntityHandle** entity_handles,
2768  /*out*/ int* entity_handles_allocated,
2769  /*out*/ int* entity_handles_size,
2770  /*out*/ int* err )
2771 {
2774 
2775  bool use_top = false;
2776  // initialize just to get rid of compiler warning
2777  EntityType type = mb_topology_table[iMesh_ALL_TOPOLOGIES];
2778  Range out_entities;
2779 
2780  if( entity_topology != iMesh_ALL_TOPOLOGIES )
2781  {
2782  type = mb_topology_table[entity_topology];
2783  use_top = true;
2784 
2785  if( entity_type != iBase_ALL_TYPES )
2786  {
2787  if( entity_topology != iMesh_SEPTAHEDRON && entity_type != CN::Dimension( type ) )
2788  ERROR( iBase_BAD_TYPE_AND_TOPO, "type and topology are inconsistant" );
2789 
2790  // Special-case handling for septahedra since we don't support them
2791  else if( entity_topology == iMesh_SEPTAHEDRON && entity_type != iBase_REGION )
2792  ERROR( iBase_BAD_TYPE_AND_TOPO, "type and topology are inconsistant" );
2793  }
2794  }
2795 
2796  EntityHandle handle = ENTITY_HANDLE( entity_set_handle );
2797  ErrorCode result = MB_SUCCESS;
2798 
2799  if( use_top )
2800  {
2801  if( entity_topology == iMesh_SEPTAHEDRON )
2802  result = MB_SUCCESS; // MOAB doesn't do septahedrons, so there are never any.
2803  else
2804  result =
2805  MOABI->get_entities_by_type_and_tag( handle, type, (Tag*)tag_handles, (const void* const*)tag_vals,
2806  num_tags_vals, out_entities, Interface::INTERSECT, recursive );
2807  }
2808  else if( entity_type != iBase_ALL_TYPES )
2809  {
2810  // need to loop over all types of this dimension
2811  DimensionPair dimpair = CN::getDimPair( entity_type );
2812  for( EntityType tp = dimpair.first; tp <= dimpair.second; tp++ )
2813  {
2814  Range tmp_range;
2815  ErrorCode tmp_result =
2816  MOABI->get_entities_by_type_and_tag( handle, type, (Tag*)tag_handles, (const void* const*)tag_vals,
2817  num_tags_vals, tmp_range, Interface::INTERSECT, recursive );
2818  if( MB_SUCCESS != tmp_result )
2819  result = tmp_result;
2820  else
2821  out_entities.merge( tmp_range );
2822  }
2823  }
2824  else
2825  result = MOABI->get_entities_by_type_and_tag( handle, type, (Tag*)tag_handles, (const void* const*)tag_vals,
2826  num_tags_vals, out_entities, Interface::INTERSECT, recursive );
2827 
2828  CHKERR( result, "iMesh_GetEntities:ERROR getting entities." );
2829 
2830  ALLOC_CHECK_ARRAY_NOFAIL( entity_handles, out_entities.size() );
2831 
2832  Range::iterator iter = out_entities.begin();
2833  Range::iterator end_iter = out_entities.end();
2834  int k = 0;
2835 
2836  // filter out entity sets here
2837  if( iBase_ALL_TYPES == entity_type && iMesh_ALL_TOPOLOGIES == entity_topology )
2838  {
2839  for( ; iter != end_iter && MOABI->type_from_handle( *iter ) != MBENTITYSET; ++iter )
2840  ( *entity_handles )[k++] = (iBase_EntityHandle)*iter;
2841  }
2842  else
2843  {
2844  for( ; iter != end_iter; ++iter )
2845  ( *entity_handles )[k++] = (iBase_EntityHandle)*iter;
2846  }
2847 
2848  // now it's safe to set the size; set it to k, not out_entities.size(), to
2849  // account for sets which might have been removed
2850  *entity_handles_size = k;
2851 
2852  RETURN( iBase_SUCCESS );
2853 }
2854 
2856  /*in*/ const iBase_EntitySetHandle entity_set_handle,
2857  /*in*/ const iBase_TagHandle* tag_handles,
2858  /*in*/ const char* const* tag_vals,
2859  /*in*/ const int num_tags_vals,
2860  /*in*/ const int recursive,
2861  /*out*/ iBase_EntitySetHandle** set_handles,
2862  /*out*/ int* set_handles_allocated,
2863  /*out*/ int* set_handles_size,
2864  /*out*/ int* err )
2865 {
2866  Range out_entities;
2867 
2868  EntityHandle handle = ENTITY_HANDLE( entity_set_handle );
2869  ErrorCode result;
2870 
2871  result = MOABI->get_entities_by_type_and_tag( handle, MBENTITYSET, (Tag*)tag_handles, (const void* const*)tag_vals,
2872  num_tags_vals, out_entities, Interface::INTERSECT, recursive );CHKERR( result, "ERROR getting entities." );
2873 
2874  ALLOC_CHECK_ARRAY_NOFAIL( set_handles, out_entities.size() );
2875 
2876  std::copy( out_entities.begin(), out_entities.end(), ( (EntityHandle*)*set_handles ) );
2877 
2878  RETURN( iBase_SUCCESS );
2879 }
2880 
2881 void iMesh_MBCNType( /*in*/ const int imesh_entity_topology,
2882  /*out*/ int* mbcn_type )
2883 {
2884  if( iMesh_POINT > imesh_entity_topology || iMesh_ALL_TOPOLOGIES <= imesh_entity_topology )
2885  *mbcn_type = -1;
2886  else
2887  *mbcn_type = mb_topology_table[imesh_entity_topology];
2888 }
2889 
2891  /*in*/ const iBase_TagHandle tag_handle,
2892  iBase_EntityArrIterator entArr_iterator,
2893  /**< [in] Iterator being queried */
2894  void* data,
2895  /**< [out] Pointer to pointer that will be set to tag data memory
2896  \ref trio) */
2897  int* count,
2898  /**< [out] Number of contiguous entities in this subrange */
2899  int* err
2900  /**< [out] Returned Error status (see iBase_ErrorType) */
2901 )
2902 {
2903  MBRangeIter* ri = dynamic_cast< MBRangeIter* >( entArr_iterator );
2904  if( !ri ) CHKERR( MB_FAILURE, "Wrong type of iterator, need a range-based iterator for iMesh_tagIterate." );
2905 
2906  ErrorCode result = MOABI->tag_iterate( TAG_HANDLE( tag_handle ), ri->position(), ri->end(), *count,
2907  *static_cast< void** >( data ) );CHKERR( result, "Problem getting tag iterator." );
2908 
2909  RETURN( iBase_SUCCESS );
2910 }
2911 
2913  iBase_EntityArrIterator entArr_iterator,
2914  /**< [in] Iterator being queried */
2915  iBase_EntityHandle** connect,
2916  /**< [out] Pointer to pointer that will be set to connectivity data memory */
2917  int* verts_per_entity,
2918  /**< [out] Pointer to integer set to number of vertices per entity */
2919  int* count,
2920  /**< [out] Number of contiguous entities in this subrange */
2921  int* err
2922  /**< [out] Returned Error status (see iBase_ErrorType) */
2923 )
2924 {
2925  MBRangeIter* ri = dynamic_cast< MBRangeIter* >( entArr_iterator );
2926  if( !ri ) CHKERR( MB_FAILURE, "Wrong type of iterator, need a range-based iterator for iMesh_connectIterate." );
2927 
2928  ErrorCode result =
2929  MOABI->connect_iterate( ri->position(), ri->end(), reinterpret_cast< EntityHandle*& >( *connect ),
2930  *verts_per_entity, *count );CHKERR( result, "Problem getting connect iterator." );
2931 
2932  RETURN( iBase_SUCCESS );
2933 }
2934 
2936  iBase_EntityArrIterator entArr_iterator,
2937  /**< [in] Iterator being queried */
2938  double** xcoords_ptr,
2939  /**< [out] Pointer to pointer that will be set to x coordinate data memory */
2940  double** ycoords_ptr,
2941  /**< [out] Pointer to pointer that will be set to y coordinate data memory */
2942  double** zcoords_ptr,
2943  /**< [out] Pointer to pointer that will be set to z coordinate data memory */
2944  int* count,
2945  /**< [out] Number of contiguous entities in this subrange */
2946  int* err
2947  /**< [out] Returned Error status (see iBase_ErrorType) */
2948 )
2949 {
2950  MBRangeIter* ri = dynamic_cast< MBRangeIter* >( entArr_iterator );
2951  if( !ri ) CHKERR( MB_FAILURE, "Wrong type of iterator, need a range-based iterator for iMesh_coordsIterate." );
2952 
2953  ErrorCode result =
2954  MOABI->coords_iterate( ri->position(), ri->end(), *xcoords_ptr, *ycoords_ptr, *zcoords_ptr, *count );CHKERR( result, "Problem getting coords iterator." );
2955 
2956  RETURN( iBase_SUCCESS );
2957 }
2958 
2960  /**< [in] iMesh instance handle */
2961  iBase_EntityIterator ent_iterator,
2962  /**< [in] Iterator being queried */
2963  int step_length,
2964  /**< [in] Number of entities to step the iterator */
2965  int* at_end,
2966  /**< [out] Non-zero if iterator is at the end of the iteration */
2967  int* err
2968  /**< [out] Returned Error status (see iBase_ErrorType) */
2969 )
2970 {
2971  iMesh_stepEntArrIter( instance, reinterpret_cast< iBase_EntityArrIterator >( ent_iterator ), step_length, at_end,
2972  err );
2973 }
2974 
2976  /**< [in] iMesh instance handle */
2977  iBase_EntityArrIterator entArr_iterator,
2978  /**< [in] Iterator being queried */
2979  int step_length,
2980  /**< [in] Number of entities to step the iterator */
2981  int* at_end,
2982  /**< [out] Non-zero if iterator is at the end of the iteration */
2983  int* err
2984  /**< [out] Returned Error status (see iBase_ErrorType) */
2985 )
2986 {
2987  bool tmp;
2988  ErrorCode result = entArr_iterator->step( step_length, tmp );CHKERR( result, "Problem stepping iterator." );
2989  *at_end = tmp;
2990  RETURN( iBase_SUCCESS );
2991 }
2992 
2993 /**
2994  * Method: initEntArrIter[]
2995  */
2997  /*in*/ const iBase_EntitySetHandle entity_set_handle,
2998  /*in*/ const int requested_entity_type,
2999  /*in*/ const int requested_entity_topology,
3000  /*in*/ const int requested_array_size,
3001  /*in*/ const int resilient,
3002  /*in*/ const int recursive,
3003  /*out*/ iBase_EntityArrIterator* entArr_iterator,
3004  int* err )
3005 {
3006  CHKENUM( requested_entity_type, iBase_EntityType, iBase_INVALID_ENTITY_TYPE );
3007  CHKENUM( requested_entity_topology, iMesh_EntityTopology, iBase_INVALID_ENTITY_TOPOLOGY );
3008  if( resilient ) ERROR( iBase_NOT_SUPPORTED, "reslient iterators not supported" );
3009 
3010  EntityType req_type = mb_topology_table[requested_entity_topology];
3011 
3012  if( requested_entity_topology != iMesh_ALL_TOPOLOGIES )
3013  {
3014  if( requested_entity_type != iBase_ALL_TYPES )
3015  {
3016  if( requested_entity_topology != iMesh_SEPTAHEDRON && requested_entity_type != CN::Dimension( req_type ) )
3017  ERROR( iBase_BAD_TYPE_AND_TOPO, "type and topology are inconsistant" );
3018 
3019  // Special-case handling for septahedra since we don't support them
3020  else if( requested_entity_topology == iMesh_SEPTAHEDRON && requested_entity_type != iBase_REGION )
3021  ERROR( iBase_BAD_TYPE_AND_TOPO, "type and topology are inconsistant" );
3022  }
3023  }
3024 
3025  ErrorCode result;
3026  unsigned flags;
3027  result = MOABI->get_meshset_options( ENTITY_HANDLE( entity_set_handle ), flags );CHKERR( result, "Invalid entity set handle" );
3028 
3029  if( flags & MESHSET_ORDERED )
3030  *entArr_iterator =
3031  new MBListIter( (iBase_EntityType)requested_entity_type, (iMesh_EntityTopology)requested_entity_topology,
3032  ENTITY_HANDLE( entity_set_handle ), requested_array_size, recursive );
3033  else
3034  *entArr_iterator =
3035  new MBRangeIter( (iBase_EntityType)requested_entity_type, (iMesh_EntityTopology)requested_entity_topology,
3036  ENTITY_HANDLE( entity_set_handle ), requested_array_size, recursive );
3037  result = ( *entArr_iterator )->reset( MOABI );
3038  if( MB_SUCCESS != result ) delete *entArr_iterator;CHKERR( result, "iMesh_initEntArrIter: ERROR getting entities of proper type or topology." );
3039  RETURN( iBase_SUCCESS );
3040 }
3041 
3043  /*in*/ const char* tag_name,
3044  /*in*/ const char* tmp_tag_options,
3045  /*in*/ const int tag_size,
3046  /*in*/ const int tag_type,
3047  /*out*/ iBase_TagHandle* tag_handle,
3048  /*out*/ int* err,
3049  /*in*/ const int tag_name_len,
3050  /*in*/ const int tag_options_len )
3051 {
3052  if( tag_size < 0 ) ERROR( iBase_INVALID_ARGUMENT, "iMesh_createTag: invalid tag size" );
3054 
3055  std::string tmp_tagname( tag_name, tag_name_len );
3056  eatwhitespace( tmp_tagname );
3057 
3058  moab::TagType storage = MB_TAG_SPARSE;
3059  ErrorCode result;
3060 
3061  // declared here 'cuz might have to hold destination of a default value ptr
3062  std::string storage_type;
3063  const void* def_val = NULL;
3064  std::vector< int > def_int;
3065  std::vector< double > def_dbl;
3066  std::vector< moab::EntityHandle > def_handles;
3067  int dum_int;
3068  double dum_dbl;
3069 
3070  if( 0 != tag_options_len )
3071  {
3072  std::string tag_options = filter_options( tmp_tag_options, tmp_tag_options + tag_options_len );
3073  FileOptions opts( tag_options.c_str() );
3074  const char* option_vals[] = { "SPARSE", "DENSE", "BIT", "MESH" };
3077  int opt_num = -1;
3078  result = opts.match_option( "TAG_STORAGE_TYPE", option_vals, opt_num );
3079  if( MB_FAILURE == result )
3080  ERROR( result, "iMesh_createTagWithOptions: option string not recognized." );
3081  else if( MB_SUCCESS == result )
3082  {
3083  assert( opt_num >= 0 && opt_num <= 3 );
3084  storage = opt_types[opt_num];
3085  }
3086 
3087  // now look for default value option; reuse storage_type
3088  storage_type.clear();
3089  result = opts.get_option( "TAG_DEFAULT_VALUE", storage_type );
3090  if( MB_SUCCESS == result )
3091  {
3092  // ok, need to parse the string into a proper default value
3093  switch( tag_type )
3094  {
3095  case iBase_INTEGER:
3096  result = opts.get_int_option( "TAG_DEFAULT_VALUE", dum_int );
3097  def_int.resize( tag_size );
3098  std::fill( def_int.begin(), def_int.end(), dum_int );
3099  def_val = &def_int[0];
3100  break;
3101  case iBase_DOUBLE:
3102  result = opts.get_real_option( "TAG_DEFAULT_VALUE", dum_dbl );
3103  def_dbl.resize( tag_size );
3104  std::fill( def_dbl.begin(), def_dbl.end(), dum_dbl );
3105  def_val = &def_dbl[0];
3106  break;
3107  case iBase_ENTITY_HANDLE:
3108  // for default handle, will have to use int
3109  result = opts.get_int_option( "TAG_DEFAULT_VALUE", dum_int );
3110  if( 0 > dum_int )
3111  ERROR( result, "iMesh_createTagWithOptions: for default handle-type tag, "
3112  "must use non-negative int on input." );
3113  def_handles.resize( tag_size );
3114  std::fill( def_handles.begin(), def_handles.end(), (moab::EntityHandle)dum_int );
3115  def_val = &def_handles[0];
3116  break;
3117  case iBase_BYTES:
3118  if( (int)storage_type.length() < tag_size )
3119  ERROR( result, "iMesh_createTagWithOptions: default value for byte-type "
3120  "tag must be large enough to store tag value." );
3121  def_val = storage_type.c_str();
3122  break;
3123  }
3124  }
3125  }
3126 
3127  moab::Tag new_tag;
3128  result = MOABI->tag_get_handle( tmp_tagname.c_str(), tag_size, mb_data_type_table[tag_type], new_tag,
3129  storage | MB_TAG_EXCL, def_val );
3130 
3131  if( MB_SUCCESS != result )
3132  {
3133  std::string msg( "iMesh_createTag: " );
3134  if( MB_ALREADY_ALLOCATED == result )
3135  {
3136  msg += "Tag already exists with name: \"";
3137  *tag_handle = (iBase_TagHandle)new_tag;
3138  }
3139  else
3140  msg += "Failed to create tag with name: \"";
3141  msg += tag_name;
3142  msg += "\".";
3143  ERROR( result, msg.c_str() );
3144  }
3145 
3146  if( tag_type == iBase_ENTITY_HANDLE )
3147  MBIMESHI->note_ent_handle_tag( new_tag );
3148  else if( tag_type == iBase_ENTITY_SET_HANDLE )
3149  MBIMESHI->note_set_handle_tag( new_tag );
3150 
3151  *tag_handle = (iBase_TagHandle)new_tag;
3152 
3153  RETURN( iBase_SUCCESS );
3154 
3155  /* old implementation:
3156  Tag new_tag;
3157  int this_size = tag_size;
3158 
3159  ErrorCode result = MOABI->tag_get_handle(tmp_tagname.c_str(),
3160  this_size,
3161  mb_data_type_table[tag_type],
3162  new_tag,
3163  MB_TAG_SPARSE|MB_TAG_EXCL);
3164 
3165  if (MB_SUCCESS != result) {
3166  std::string msg("iMesh_createTag: ");
3167  if (MB_ALREADY_ALLOCATED == result) {
3168  msg += "Tag already exists with name: \"";
3169  *tag_handle = (iBase_TagHandle) new_tag;
3170  }
3171  else
3172  msg += "Failed to create tag with name: \"";
3173  msg += tag_name;
3174  msg += "\".";
3175  ERROR(result,msg.c_str());
3176  }
3177 
3178  if (tag_type == iBase_ENTITY_HANDLE)
3179  MBIMESHI->note_ent_handle_tag( new_tag );
3180  else if (tag_type == iBase_ENTITY_SET_HANDLE)
3181  MBIMESHI->note_set_handle_tag( new_tag );
3182 
3183  *tag_handle = (iBase_TagHandle) new_tag;
3184  */
3185 }
3186 
3187 #ifdef __cplusplus
3188 } // extern "C"
3189 #endif
3190 
3191 ErrorCode create_int_ents( MBiMesh* mbimesh, Range& from_ents, const EntityHandle* in_set )
3192 {
3193  // MBiMesh* mbimesh = dynamic_cast<MBiMesh*>(instance);
3194  assert( mbimesh );
3195  assert( mbimesh->AdjTable[10] || mbimesh->AdjTable[5] );
3196  Range int_ents;
3197  ErrorCode result;
3198  Interface* instance = mbimesh->mbImpl;
3199  if( mbimesh->AdjTable[10] )
3200  {
3201  result = instance->get_adjacencies( from_ents, 2, true, int_ents, Interface::UNION );
3202  if( MB_SUCCESS != result ) return result;
3203  unsigned int old_size = from_ents.size();
3204  from_ents.merge( int_ents );
3205  if( old_size != from_ents.size() && in_set )
3206  {
3207  result = instance->add_entities( *in_set, int_ents );
3208  if( MB_SUCCESS != result ) return result;
3209  }
3210  }
3211 
3212  if( mbimesh->AdjTable[5] )
3213  {
3214  int_ents.clear();
3215  result = instance->get_adjacencies( from_ents, 1, true, int_ents, Interface::UNION );
3216  if( MB_SUCCESS != result ) return result;
3217  unsigned int old_size = from_ents.size();
3218  from_ents.merge( int_ents );
3219  if( old_size != from_ents.size() && in_set )
3220  {
3221  result = instance->add_entities( *in_set, int_ents );
3222  if( MB_SUCCESS != result ) return result;
3223  }
3224  }
3225 
3226  return MB_SUCCESS;
3227 }
3228 
3229 void eatwhitespace( std::string& this_string )
3230 {
3231  std::string::size_type p = this_string.find_last_not_of( " " );
3232  if( p != this_string.npos ) this_string.resize( p + 1 );
3233 }
3234 
3236  /*in*/ int* local_dims,
3237  /*in*/ int* global_dims,
3238  /*in*/ double* i_vals,
3239  /*in*/ double* j_vals,
3240  /*in*/ double* k_vals,
3241  /*in*/ int resolve_shared,
3242  /*in*/ int ghost_dim,
3243  /*in*/ int bridge_dim,
3244  /*in*/ int num_layers,
3245  /*in*/ int addl_ents,
3246  /*in*/ int vert_gids,
3247  /*in*/ int elem_gids,
3248  /*inout*/ iBase_EntitySetHandle* set_handle,
3249  /*out*/ int* err )
3250 {
3251  ScdInterface* scdi = NULL;
3252  ErrorCode rval = MOABI->query_interface( scdi );CHKERR( rval, "Couldn't get structured mesh interface." );
3253 
3254  Range tmp_range;
3255  ScdBox* scd_box;
3256  rval =
3257  scdi->construct_box( HomCoord( local_dims[0], local_dims[1], ( -1 != local_dims[2] ? local_dims[2] : 0 ), 1 ),
3258  HomCoord( local_dims[3], local_dims[4], ( -1 != local_dims[5] ? local_dims[5] : 0 ), 1 ),
3259  NULL, 0, scd_box, NULL, NULL, ( vert_gids ? true : false ) );CHKERR( rval, "Trouble creating scd vertex sequence." );
3260 
3261  // set the global box parameters
3262  if( global_dims )
3263  {
3264  for( int i = 0; i < 6; i++ )
3265  scd_box->par_data().gDims[i] = global_dims[i];
3266  }
3267 
3268  tmp_range.insert( scd_box->start_vertex(), scd_box->start_vertex() + scd_box->num_vertices() - 1 );
3269  tmp_range.insert( scd_box->start_element(), scd_box->start_element() + scd_box->num_elements() - 1 );
3270  tmp_range.insert( scd_box->box_set() );
3271 
3272  if( set_handle )
3273  {
3274  if( !( *set_handle ) )
3275  {
3276  // return the new ScdBox's set
3277  *set_handle = reinterpret_cast< iBase_EntitySetHandle >( scd_box->box_set() );
3278  }
3279  else
3280  {
3281  // add the new ScdBox's set to the given file set
3282  EntityHandle s = scd_box->box_set();
3283  rval = MOABI->add_entities( ENTITY_HANDLE( *set_handle ), &s, 1 );CHKERR( rval, "Couldn't add box set to file set." );
3284  }
3285  }
3286 
3287  // get a ptr to global id memory
3288  void* data;
3289  int count;
3290  Range::const_iterator topv, bote, tope;
3291 
3292  Tag gid_tag = 0;
3293  int *v_gid_data = NULL, *e_gid_data = NULL;
3294  if( vert_gids || elem_gids )
3295  {
3296  gid_tag = MOABI->globalId_tag();
3297  }
3298 
3299  if( vert_gids )
3300  {
3301  topv = tmp_range.upper_bound( tmp_range.begin(), tmp_range.end(),
3302  scd_box->start_vertex() + scd_box->num_vertices() );
3303 
3304  rval = MOABI->tag_iterate( gid_tag, tmp_range.begin(), topv, count, data );CHKERR( rval, "Failed to get tag iterator." );
3305  assert( count == scd_box->num_vertices() );
3306  v_gid_data = (int*)data;
3307  }
3308 
3309  if( elem_gids )
3310  {
3311  bote = tmp_range.lower_bound( tmp_range.begin(), tmp_range.end(), scd_box->start_element() );
3312  tope = tmp_range.upper_bound( tmp_range.begin(), tmp_range.end(), *bote + scd_box->num_elements() );
3313 
3314  rval = MOABI->tag_iterate( gid_tag, bote, tope, count, data );CHKERR( rval, "Failed to get tag iterator." );
3315  assert( count == scd_box->num_elements() );
3316  e_gid_data = (int*)data;
3317  }
3318 
3319  if( i_vals || j_vals || k_vals || v_gid_data || e_gid_data )
3320  {
3321 
3322  // set the vertex coordinates
3323  double *xc, *yc, *zc;
3324  rval = scd_box->get_coordinate_arrays( xc, yc, zc );CHKERR( rval, "Couldn't get vertex coordinate arrays." );
3325 
3326  int i, j, k, il, jl, kl;
3327  int dil = local_dims[3] - local_dims[0] + 1;
3328  int djl = local_dims[4] - local_dims[1] + 1;
3329  int di = ( global_dims ? global_dims[3] - global_dims[0] + 1 : dil );
3330  int dj = ( global_dims ? global_dims[4] - global_dims[1] + 1 : djl );
3331  for( kl = local_dims[2]; kl <= local_dims[5]; kl++ )
3332  {
3333  k = kl - local_dims[2];
3334  for( jl = local_dims[1]; jl <= local_dims[4]; jl++ )
3335  {
3336  j = jl - local_dims[1];
3337  for( il = local_dims[0]; il <= local_dims[3]; il++ )
3338  {
3339  i = il - local_dims[0];
3340  unsigned int pos = i + j * dil + k * dil * djl;
3341  xc[pos] = ( i_vals ? i_vals[i] : -1.0 );
3342  yc[pos] = ( j_vals ? j_vals[j] : -1.0 );
3343  zc[pos] = ( -1 == local_dims[2] ? 0.0 : ( k_vals ? k_vals[k] : -1.0 ) );
3344  if( v_gid_data )
3345  {
3346  *v_gid_data = ( -1 != kl ? kl * di * dj : 0 ) + jl * di + il + 1;
3347  v_gid_data++;
3348  }
3349  if( e_gid_data && kl < local_dims[5] && jl < local_dims[4] && il < local_dims[3] )
3350  {
3351  *e_gid_data = ( -1 != kl ? kl * ( di - 1 ) * ( dj - 1 ) : 0 ) + jl * ( di - 1 ) + il + 1;
3352  e_gid_data++;
3353  }
3354  }
3355  }
3356  }
3357  }
3358 
3359 #ifdef MOAB_HAVE_MPI
3360  // do parallel stuff, if requested
3361  if( resolve_shared )
3362  {
3363  ParallelComm* pcomm = ParallelComm::get_pcomm( MOABI, 0 );
3364  if( pcomm )
3365  {
3366 
3367  rval =
3368  pcomm->resolve_shared_ents( 0, MOABI->dimension_from_handle( scd_box->start_element() ), 0, &gid_tag );CHKERR( rval, "Trouble resolving shared vertices." );
3369 
3370  if( -1 != ghost_dim )
3371  {
3372  rval = pcomm->exchange_ghost_cells( ghost_dim, bridge_dim, num_layers, addl_ents, true );CHKERR( rval, "Trouble exchanging ghosts." );
3373  }
3374  }
3375  }
3376 #else
3377  // empty statement to remove compiler warning
3378  if( resolve_shared || ghost_dim || bridge_dim || num_layers || addl_ents )
3379  {
3380  }
3381 #endif
3382 
3383  RETURN( iBase_SUCCESS );
3384 }
3385 
3387  /**< [in] iMesh instance handle */
3388  void** ptrToMem )
3389 {
3390  free( *ptrToMem );
3391  *ptrToMem = 0;
3392  return;
3393 }