iMesh_MOAB.cpp 131 KB
Newer Older
1
#include "moab/MOABConfig.h"
2
#include "iMesh_extensions.h"
's avatar
committed
3 4
#include "moab/Core.hpp"
#include "moab/Range.hpp"
5
#include "moab/CN.hpp"
's avatar
committed
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"
's avatar
committed
12
#define IS_BUILDING_MB
's avatar
committed
13
#include "Internals.hpp"
's avatar
committed
14
#undef IS_BUILDING_MB
15

16
#ifdef MOAB_HAVE_MPI
's avatar
committed
17
#include "moab_mpi.h"
18
#include "moab/ParallelComm.hpp"
19
#endif
20

21 22
#define STRINGIFY_(X) #X
#define STRINGIFY(X) STRINGIFY_(X)
23 24
#ifdef MOAB_HAVE_UNORDERED_MAP
# include STRINGIFY(MOAB_HAVE_UNORDERED_MAP)
25 26 27 28
#else
# include <map>
#endif

29
#include <iostream>
30
#include <cassert>
31
#include <cctype>
's avatar
committed
32 33 34
#include <cstring>
#include <stdarg.h>
#include <stdio.h>
35 36
#define MIN(a,b) (a < b ? a : b)

Jacob Becker's avatar
Jacob Becker committed
37 38 39 40
#ifdef _MSC_VER
# define snprintf(A,B,C,D) _snprintf((A),(B),(C),(D))
#endif

41 42 43
static ErrorCode create_int_ents(MBiMesh * mbimesh,
				 Range &from_ents,
				 const EntityHandle* in_set = 0);
's avatar
committed
44 45 46 47 48 49
#define HANDLE_ARRAY_PTR(array) reinterpret_cast<EntityHandle*>(array)
#define CONST_HANDLE_ARRAY_PTR(array) reinterpret_cast<const EntityHandle*>(array)
#define TAG_HANDLE(handle) reinterpret_cast<Tag>(handle)
#define CONST_TAG_HANDLE(handle) static_cast<const Tag>(handle)
#define ENTITY_HANDLE(handle) reinterpret_cast<EntityHandle>(handle)
#define CONST_ENTITY_HANDLE(handle) reinterpret_cast<const EntityHandle>(handle)
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
#define CAST_TO_VOID(ptr) reinterpret_cast<void*>(ptr)

// map from MB's entity type to TSTT's entity topology
const iMesh_EntityTopology tstt_topology_table[] =
{
  iMesh_POINT,          // MBVERTEX
  iMesh_LINE_SEGMENT,   // MBEDGE
  iMesh_TRIANGLE,       // MBTRI
  iMesh_QUADRILATERAL,  // MBQUAD
  iMesh_POLYGON,        // MBPOLYGON
  iMesh_TETRAHEDRON,    // MBTET
  iMesh_PYRAMID,        // MBPYRAMID
  iMesh_PRISM,          // MBPRISM
  iMesh_ALL_TOPOLOGIES, // MBKNIFE
  iMesh_HEXAHEDRON,     // MBHEX
  iMesh_POLYHEDRON,     // MBPOLYHEDRON
  iMesh_ALL_TOPOLOGIES, // MBENTITYSET
  iMesh_ALL_TOPOLOGIES, // MBMAXTYPE
};

// map from MB's entity type to TSTT's entity type
const iBase_EntityType tstt_type_table[] =
{
  iBase_VERTEX,         // MBVERTEX
  iBase_EDGE,           // MBEDGE
  iBase_FACE,           // MBTRI
  iBase_FACE,           // MBQUAD
  iBase_FACE,           // MBPOLYGON
  iBase_REGION,         // MBTET
  iBase_REGION,         // MBPYRAMID
  iBase_REGION,         // MBPRISM
  iBase_REGION,         // MBKNIFE
  iBase_REGION,         // MBHEX
  iBase_REGION,         // MBPOLYHEDRON
  iBase_ALL_TYPES, // MBENTITYSET
  iBase_ALL_TYPES  // MBMAXTYPE
};

// map to MB's entity type from TSTT's entity topology
's avatar
committed
89
const EntityType mb_topology_table[] =
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
{
  MBVERTEX,
  MBEDGE,
  MBPOLYGON,
  MBTRI,
  MBQUAD,
  MBPOLYHEDRON,
  MBTET,
  MBHEX,
  MBPRISM,
  MBPYRAMID,
  MBMAXTYPE,
  MBMAXTYPE
};

// map from TSTT's tag types to MOAB's
Jim Porter's avatar
Jim Porter committed
106
const DataType mb_data_type_table[] =
107
{
's avatar
committed
108
  MB_TYPE_OPAQUE,
109 110 111
  MB_TYPE_INTEGER,
  MB_TYPE_DOUBLE ,
  MB_TYPE_HANDLE ,
's avatar
committed
112
  MB_TYPE_HANDLE
113 114 115
};

// map from MOAB's tag types to tstt's
Jim Porter's avatar
Jim Porter committed
116
const iBase_TagValueType tstt_data_type_table[] =
117 118 119 120 121 122 123 124
{
  iBase_BYTES,
  iBase_INTEGER,
  iBase_DOUBLE,
  iBase_BYTES,
  iBase_ENTITY_HANDLE
};

Jim Porter's avatar
Jim Porter committed
125
const iBase_ErrorType iBase_ERROR_MAP[MB_FAILURE+1] =
126 127 128 129 130 131 132 133 134 135 136 137
{
  iBase_SUCCESS, // MB_SUCCESS = 0,
  iBase_INVALID_ENTITY_HANDLE, // MB_INDEX_OUT_OF_RANGE,
  iBase_INVALID_ENTITY_TYPE, // MB_TYPE_OUT_OF_RANGE,
  iBase_MEMORY_ALLOCATION_FAILED, // MB_MEMORY_ALLOCATION_FAILED,
  iBase_INVALID_ENTITY_HANDLE, // MB_ENTITY_NOT_FOUND,
  iBase_NOT_SUPPORTED, // MB_MULTIPLE_ENTITIES_FOUND,
  iBase_TAG_NOT_FOUND, // MB_TAG_NOT_FOUND,
  iBase_FILE_NOT_FOUND, // MB_FILE_DOES_NOT_EXIST,
  iBase_FILE_WRITE_ERROR, // MB_FILE_WRITE_ERROR,
  iBase_NOT_SUPPORTED, // MB_NOT_IMPLEMENTED,
  iBase_TAG_ALREADY_EXISTS, // MB_ALREADY_ALLOCATED,
Tim Tautges's avatar
Tim Tautges committed
138 139
  iBase_FAILURE, // MB_VARIABLE_DATA_LENGTH,
  iBase_FAILURE, // MB_INVALID_SIZE,
's avatar
committed
140
  iBase_NOT_SUPPORTED, // MB_UNSUPPORTED_OPERATION,
's avatar
committed
141
  iBase_INVALID_ARGUMENT, // MB_UNHANDLED_OPTION
142
  iBase_INVALID_ENTITY_TYPE, // MB_STRUCTURED_MESH
143 144 145
  iBase_FAILURE // MB_FAILURE};
};

146
// Return data about a list of handles for use in check_handle_tag_type.
Jim Porter's avatar
Jim Porter committed
147
// Set output arguments to true if the list contains the corresponding
148 149
// type of handle.  Leave them unmodified if it does not.
static inline void ht_content_type( const std::vector<EntityHandle>& h,
150
                                    bool &saw_ent, bool &saw_set, bool &saw_root )
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
{
  std::vector<EntityHandle>::const_iterator i;
  for (i = h.begin(); i != h.end(); ++i) {
    if (*i == 0)
      saw_root = true;
    else if (TYPE_FROM_HANDLE(*i) == MBENTITYSET)
      saw_set = true;
    else
      saw_ent = true;
  }
}

// Scan all tag data to try to guess whether the MOAB tag with
// data of type MB_TYPE_HANDLE is iBase_ENTITY_HANDLE or
// iBase_ENTITY_SET_HANDLE.
static ErrorCode check_handle_tag_type( Tag t, MBiMesh* mbi )
{
  Interface* mb = mbi->mbImpl;
  ErrorCode rval;
  int size;
  DataType type;
  rval = mb->tag_get_data_type( t, type );
  if (MB_SUCCESS != rval) return rval;
  if (MB_TYPE_HANDLE != type) return MB_TYPE_OUT_OF_RANGE;
175
  rval = mb->tag_get_length( t, size );
176 177
  if (MB_SUCCESS != rval) return rval;
  std::vector<EntityHandle> data(size);
Jim Porter's avatar
Jim Porter committed
178

179 180 181 182 183 184
    // check for global/mesh value
  bool saw_set = false, saw_ent = false, saw_root = false;
  EntityHandle root = 0;
  rval = mb->tag_get_data( t, &root, 1, &data[0] );
  if (MB_SUCCESS == rval)
    ht_content_type( data, saw_ent, saw_set, saw_root );
Jim Porter's avatar
Jim Porter committed
185

186 187 188 189
    // check default value
  rval = mb->tag_get_default_value( t, &data[0] );
  if (MB_SUCCESS == rval)
    ht_content_type( data, saw_ent, saw_set, saw_root );
Jim Porter's avatar
Jim Porter committed
190

191 192 193 194 195 196 197 198 199
    // check all tagged entities
  Range r;
  rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, &t, 0, 1, r );
  if (MB_SUCCESS != rval) return rval;
  for (Range::iterator i = r.begin(); i != r.end(); ++i) {
    rval = mb->tag_get_data( t, &*i, 1, &data[0] );
    if (MB_SUCCESS != rval) return rval;
    ht_content_type( data, saw_ent, saw_set, saw_root );
  }
Jim Porter's avatar
Jim Porter committed
200

201 202 203 204
    // If tag values were only entities, note type accordingly.
    // Similarly if all are entity sets, note accordingly.
    // Because root set (zero handle) is sometimes used to mean NULL
    // rather than the actual root set, treat that specially.  If
Jim Porter's avatar
Jim Porter committed
205 206 207
    // all values are either root set or an entity handle, then
    // treat as if all values were non-set handles.
  if (saw_set && !saw_ent)
208 209 210 211 212 213 214 215 216 217 218 219 220
    mbi->note_set_handle_tag( t );
  else if (!saw_set && saw_ent)
    mbi->note_ent_handle_tag( t );
  else if (saw_root && !saw_ent)
    mbi->note_set_handle_tag( t );

  return MB_SUCCESS;
}

static void remove_var_len_tags( Interface* mb, std::vector<Tag>& tags )
{
  int size;
  size_t r, w = 0;
Jim Porter's avatar
Jim Porter committed
221
  for (r = 0; r < tags.size(); ++r)
222
    if (MB_SUCCESS == mb->tag_get_length( tags[r], size ))
223
      tags[w++] = tags[r];
224
  tags.resize(w);
225
}
226

227 228 229
// modify the adjacency table to match the ITAPS spec's expectations
static void munge_adj_table(int *adjTable, int geom_dim)
{
230
    // If geom_dim is 2, 3D adjacencies are unavailable. This may change!
231 232 233 234 235 236
  if (geom_dim == 2) {
    for (size_t i = 0; i < 16; ++i) {
      if (i % 4 == 3 || i >= 12)
        adjTable[i] = iBase_UNAVAILABLE;
    }
  }
237 238 239 240 241 242

    // Ensure that diagonal entries are only available/unavailable.
  for (size_t i = 0; i < 16; i+=5) {
    if (adjTable[i] != iBase_UNAVAILABLE)
      adjTable[i] = iBase_AVAILABLE;
  }
243 244
}

's avatar
committed
245 246 247 248
#ifdef __cplusplus
extern "C" {
#endif

249
  static void eatwhitespace(std::string &this_string);
250

251
  void iMesh_getErrorType(iMesh_Instance instance, int *error_type)
252
  {
253 254 255 256
    if (instance == NULL)
      *error_type = iBase_FAILURE;
    else
      *error_type = MBIMESHI->lastErrorType;
257
  }
Jim Porter's avatar
Jim Porter committed
258

259
  void iMesh_getDescription(iMesh_Instance instance, char *descr, int descr_len)
260
  {
261 262 263 264 265 266 267 268 269
    if (instance == NULL) {
      strcpy(descr, "iMesh_getDescription: Invalid instance");
    }
    else {
      unsigned int len = MIN(strlen(MBIMESHI->lastErrorDescription),
                             static_cast<unsigned int>(descr_len));
      strncpy(descr, MBIMESHI->lastErrorDescription, len);
      descr[len] = '\0';
    }
270
  }
271

Jim Porter's avatar
Jim Porter committed
272 273
  void iMesh_newMesh(const char *options,
                     iMesh_Instance *instance, int *err, int options_len)
274
  {
275 276
    std::string tmp_options = filter_options(options, options+options_len);
    FileOptions opts(tmp_options.c_str());
277

278 279
    MBiMesh **mbi = reinterpret_cast<MBiMesh**>(instance);
    *mbi = NULL;
280

's avatar
committed
281
    ErrorCode result = opts.get_null_option("PARALLEL");
282
    if (MB_SUCCESS == result) {
283
#ifdef MOAB_HAVE_MPI
284 285 286 287 288
      int flag = 1;
      int retval = MPI_Initialized(&flag);
      if (MPI_SUCCESS != retval || !flag) {
        int argc = 0;
        char **argv = NULL;
Jim Porter's avatar
Jim Porter committed
289

290 291
          // mpi not initialized yet - initialize here
        retval = MPI_Init(&argc, &argv);
292
        assert(MPI_SUCCESS == retval);
293
      }
294
      *mbi = new (std::nothrow) MBiMesh(NULL);
295
#else
296 297
        //mError->set_last_error( "PARALLEL option not valid, this instance"
        //                        " compiled for serial execution.\n" );
298
      *mbi = new (std::nothrow) MBiMesh(NULL);
299 300 301
      *err = (*mbi)->set_last_error(MB_NOT_IMPLEMENTED,
                                    "Not configured with parallel support");
      return;
302
#endif
303
    }
304
    else {
305
      *mbi = new (std::nothrow) MBiMesh(NULL);
306 307
    }
    if (NULL == *mbi) {
308 309
      *err = iBase_FAILURE;
      return;
310
    }
Jim Porter's avatar
Jim Porter committed
311

312
    *err = iBase_SUCCESS;
313
  }
314

Jim Porter's avatar
Jim Porter committed
315
  void iMesh_dtor(iMesh_Instance instance, int *err)
316
  {
317
    delete MBIMESHI;
318
    *err = iBase_SUCCESS;
319
  }
320

321
  void iMesh_load(iMesh_Instance instance,
's avatar
committed
322
                  const iBase_EntitySetHandle handle,
Jim Porter's avatar
Jim Porter committed
323 324
                  const char *name, const char *options,
                  int *err, int name_len, int options_len)
325 326
  {
      // get filename, option & null-terminate
327 328
    std::string filename(name, name_len);
    eatwhitespace(filename);
329

330
    std::string opts = filter_options(options, options+options_len);
Jim Porter's avatar
Jim Porter committed
331

's avatar
committed
332
    Range orig_ents;
333
    ErrorCode result = MOABI->get_entities_by_handle( 0, orig_ents );
's avatar
committed
334
    CHKERR(result,"Internal error");
Jim Porter's avatar
Jim Porter committed
335

's avatar
committed
336
    const EntityHandle* file_set = 0;
337
    if (handle != 0 /*root_set*/) {
's avatar
committed
338
      const iBase_EntitySetHandle* ptr = &handle;
's avatar
committed
339
      file_set = reinterpret_cast<const EntityHandle*>(ptr);
340
    }
Jim Porter's avatar
Jim Porter committed
341

342
    result = MOABI->load_file(filename.c_str(), file_set, opts.c_str());
's avatar
committed
343

's avatar
committed
344
    CHKERR(result, "iMesh_load:ERROR loading a mesh.");
345

346
      // create interior edges/faces if requested
347
    if (MBIMESHI->AdjTable[5] || MBIMESHI->AdjTable[10]) {
's avatar
committed
348
      Range set_ents;
349
      result = MOABI->get_entities_by_handle(0, set_ents);
's avatar
committed
350
      CHKERR(result,"");
351 352 353 354
      Range sets;
      result = MOABI->get_entities_by_type(0, MBENTITYSET, sets);
      CHKERR(result,"");
      set_ents = subtract( set_ents, sets );
355
      set_ents = subtract( set_ents, orig_ents );
356
      result = create_int_ents(MBIMESHI, set_ents, file_set);
's avatar
committed
357
      CHKERR(result,"");
358
    }
's avatar
committed
359
    RETURN(iBase_SUCCESS);
360 361
  }

362
  void iMesh_save(iMesh_Instance instance,
's avatar
committed
363
                  const iBase_EntitySetHandle handle,
Jim Porter's avatar
Jim Porter committed
364 365
                  const char *name, const char *options,
                  int *err, const int name_len, int options_len)
366 367
  {
      // get filename & attempt to NULL-terminate
368 369 370
    std::string filename( name, name_len );
    eatwhitespace(filename);
    std::string opts = filter_options(options, options+options_len);
371

's avatar
committed
372
    EntityHandle set = ENTITY_HANDLE(handle);
373
    ErrorCode result = MOABI->write_file(filename.c_str(), NULL, opts.c_str(),
374
                                       &set, 1);
375

's avatar
committed
376 377
    CHKERR(result, "iMesh_save:ERROR saving a mesh.");
    RETURN(iBase_SUCCESS);
's avatar
committed
378 379
  }

380
  void iMesh_getRootSet(iMesh_Instance instance,
Jim Porter's avatar
Jim Porter committed
381
                        iBase_EntitySetHandle *root_set, int *err)
382 383
  {
    *root_set = 0;
384
      //return CAST_TO_VOID(MOABI->get_root_set());
385 386
    RETURN(iBase_SUCCESS);
  }
387

388 389 390
  void iMesh_getGeometricDimension(iMesh_Instance instance,
                                   int *geom_dim, int *err)
  {
391
    MOABI->get_dimension(*geom_dim);
392
    RETURN(iBase_SUCCESS);
393 394
  }

395 396 397
  void iMesh_setGeometricDimension(iMesh_Instance instance,
                                   int geom_dim, int *err)
  {
398
    ErrorCode rval = MOABI->set_dimension(geom_dim);
's avatar
committed
399
    CHKERR(rval,"iMesh_setGeometricDimension: failed");
400 401

    RETURN(iBase_SUCCESS);
402 403
  }

404
  void iMesh_getDfltStorage(iMesh_Instance instance,
405 406 407 408
                            int *order, int *err)
  {
    *order = iBase_BLOCKED;
    RETURN(iBase_SUCCESS);
409
  }
Jim Porter's avatar
Jim Porter committed
410

411 412
  void iMesh_getAdjTable (iMesh_Instance instance,
                          int** adjacency_table,
Jim Porter's avatar
Jim Porter committed
413
                          /*inout*/ int* adjacency_table_allocated,
414 415
                          /*out*/ int* adjacency_table_size, int *err)
  {
416 417 418
    int geom_dim;
    iMesh_getGeometricDimension(instance, &geom_dim, err);

419
    ALLOC_CHECK_ARRAY_NOFAIL(adjacency_table, 16);
420
    memcpy(*adjacency_table, MBIMESHI->AdjTable, 16*sizeof(int));
421
    munge_adj_table(*adjacency_table, geom_dim);
's avatar
committed
422
    RETURN(iBase_SUCCESS);
423
  }
424

425 426
  void iMesh_setAdjTable (iMesh_Instance instance,
                          int* adj_table,
Jim Porter's avatar
Jim Porter committed
427
                          /*inout*/ int adj_table_size,
428 429 430 431 432 433
                          int *err)
  {
    if (16 != adj_table_size) {
      RETURN(iBase_INVALID_ARGUMENT);
    }

434 435 436
    int geom_dim;
    iMesh_getGeometricDimension(instance, &geom_dim, err);

437
    memcpy(MBIMESHI->AdjTable, adj_table, 16*sizeof(int));
438
    munge_adj_table(adj_table, geom_dim);
439 440 441
    RETURN(iBase_SUCCESS);
  }

442 443 444 445 446 447 448
  void iMesh_getNumOfType(iMesh_Instance instance,
                          /*in*/ const iBase_EntitySetHandle entity_set_handle,
                          /*in*/ const int entity_type,
                          int *num_type, int *err)
  {
    iMesh_getNumOfTypeRec(instance, entity_set_handle, entity_type, false,
                          num_type, err);
449
  }
Jim Porter's avatar
Jim Porter committed
450

451 452 453 454 455 456 457
  void iMesh_getNumOfTopo(iMesh_Instance instance,
                          /*in*/ const iBase_EntitySetHandle entity_set_handle,
                          /*in*/ const int entity_topology,
                          int *num_topo, int *err)
  {
    iMesh_getNumOfTopoRec(instance, entity_set_handle, entity_topology,
                          false, num_topo, err);
458
  }
459

460 461 462
  void iMesh_optimize( iMesh_Instance instance,
                       int* handles_invalidated,
                       int* err )
463
  {
464 465
    // TODO: implement this for real
    *handles_invalidated = 0;
466
    RETURN(iBase_SUCCESS);
467 468
  }

469 470 471 472 473 474
  void iMesh_getEntities(iMesh_Instance instance,
                         /*in*/ const iBase_EntitySetHandle entity_set_handle,
                         /*in*/ const int entity_type,
                         /*in*/ const int entity_topology,
                         /*inout*/ iBase_EntityHandle** entity_handles,
                         /*inout*/ int* entity_handles_allocated,
Jim Porter's avatar
Jim Porter committed
475 476
                         /*out*/ int* entity_handles_size,
                         int *err)
477 478 479 480 481 482 483 484 485 486
  {
    iMesh_getEntitiesRec(instance, entity_set_handle, entity_type,
                         entity_topology, false,
                         entity_handles, entity_handles_allocated, entity_handles_size,
                         err);
  }

  void iMesh_getVtxArrCoords (iMesh_Instance instance,
                              /*in*/ const iBase_EntityHandle* vertex_handles,
                              /*in*/ const int vertex_handles_size,
's avatar
committed
487
                              /*inout*/ int storage_order,
488 489
                              /*inout*/ double** coords,
                              /*inout*/ int* coords_allocated,
Jim Porter's avatar
Jim Porter committed
490
                              /*out*/ int* coords_size, int *err)
491
  {
492
    int geom_dim;
493
    MOABI->get_dimension(geom_dim);
494

495
      // make sure we can hold them all
496
    ALLOC_CHECK_ARRAY(coords, geom_dim*vertex_handles_size);
Jim Porter's avatar
Jim Porter committed
497

498 499
      // now get all the coordinates
      // coords will come back interleaved by default
's avatar
committed
500
    ErrorCode result;
's avatar
committed
501
    if (storage_order == iBase_INTERLEAVED) {
502
      if (3 == geom_dim) {
Jim Porter's avatar
Jim Porter committed
503
        result = MOABI->get_coords(CONST_HANDLE_ARRAY_PTR(vertex_handles),
504 505 506 507
                                 vertex_handles_size, *coords);
      }
      else {
        std::vector<double> dum_coords(3*vertex_handles_size);
Jim Porter's avatar
Jim Porter committed
508
        result = MOABI->get_coords(CONST_HANDLE_ARRAY_PTR(vertex_handles),
509 510 511 512 513 514 515 516
                                 vertex_handles_size,
                                 &dum_coords[0]);

        for (int i = 0; i < vertex_handles_size; i++) {
          for (int j = 0; j < geom_dim; j++)
            (*coords)[geom_dim*i + j] = dum_coords[3*i + j];
        }
      }
517
    }
518 519
    else {
      std::vector<double> dum_coords(3*vertex_handles_size);
Jim Porter's avatar
Jim Porter committed
520
      result = MOABI->get_coords(CONST_HANDLE_ARRAY_PTR(vertex_handles),
521 522
                               vertex_handles_size,
                               &dum_coords[0]);
's avatar
committed
523 524
      CHKERR(result,"iMesh_getVtxArrCoords: problem getting vertex coords");

525 526 527
      for (int i = 0; i < vertex_handles_size; i++) {
        for (int j = 0; j < geom_dim; j++)
          (*coords)[i + vertex_handles_size*j] = dum_coords[3*i + j];
528 529
      }
    }
Jim Porter's avatar
Jim Porter committed
530

531
    KEEP_ARRAY(coords);
532 533
    RETURN(iBase_SUCCESS);
  }
534 535 536 537

/**
 * Method:  initEntArrIter[]
 */
538 539 540 541 542
  void iMesh_initEntArrIter (iMesh_Instance instance,
                             /*in*/ const iBase_EntitySetHandle entity_set_handle,
                             /*in*/ const int requested_entity_type,
                             /*in*/ const int requested_entity_topology,
                             /*in*/ const int requested_array_size,
Jim Porter's avatar
Jim Porter committed
543
                             /*in*/ const int resilient,
544
                             /*out*/ iBase_EntityArrIterator* entArr_iterator,
Jim Porter's avatar
Jim Porter committed
545
                             int *err)
546
  {
Tim Tautges's avatar
Tim Tautges committed
547 548 549
    iMesh_initEntArrIterRec(instance, entity_set_handle, requested_entity_type, 
                            requested_entity_topology, requested_array_size, resilient, false,
                            entArr_iterator, err);
550
  }
551 552 553 554

/**
 * Method:  getEntArrNextIter[]
 */
555
  void iMesh_getNextEntArrIter (iMesh_Instance instance,
556
                                /*in*/ iBase_EntityArrIterator entArr_iterator,
557 558 559
                                /*inout*/ iBase_EntityHandle** entity_handles,
                                /*inout*/ int* entity_handles_allocated,
                                /*out*/ int* entity_handles_size,
Jim Porter's avatar
Jim Porter committed
560
                                int *has_data, int *err)
561
  {
562
      // check the size of the destination array
563 564 565 566
    ALLOC_CHECK_ARRAY_NOFAIL(entity_handles, entArr_iterator->array_size());
    entArr_iterator->get_entities( dynamic_cast<Core*>(MOABI), 
             (EntityHandle*)*entity_handles, *entity_handles_size );
    *has_data = (*entity_handles_size != 0);
567 568
    RETURN(iBase_SUCCESS);
  }
569 570 571 572

/**
 * Method:  resetEntArrIter[]
 */
573
  void iMesh_resetEntArrIter (iMesh_Instance instance,
Jim Porter's avatar
Jim Porter committed
574
                              /*in*/ iBase_EntityArrIterator entArr_iterator, int *err)
575
  {
576 577
    ErrorCode result = entArr_iterator->reset( MOABI );
    CHKERR(result,"Re-query of iterator data for iMesh_resetEntArrIter failed");
578 579
    RETURN(iBase_SUCCESS);
  }
580

581
  void iMesh_endEntArrIter (iMesh_Instance instance,
Jim Porter's avatar
Jim Porter committed
582
                            /*in*/ iBase_EntityArrIterator entArr_iterator, int *err)
583
  {
584
    delete entArr_iterator;
585 586
    RETURN(iBase_SUCCESS);
  }
587

588 589 590 591 592
  void iMesh_getEntArrTopo(iMesh_Instance instance,
                           /*in*/ const iBase_EntityHandle* entity_handles,
                           /*in*/ const int entity_handles_size,
                           /*inout*/ int** topology,
                           /*inout*/ int* topology_allocated,
Jim Porter's avatar
Jim Porter committed
593
                           /*out*/ int* topology_size, int *err)
594 595
  {
      // go through each entity and look up its type
596
    ALLOC_CHECK_ARRAY_NOFAIL(topology, entity_handles_size);
597

598
    for (int i = 0; i < entity_handles_size; i++)
Jim Porter's avatar
Jim Porter committed
599
      (*topology)[i] =
600
        tstt_topology_table[MOABI->type_from_handle(ENTITY_HANDLE(entity_handles[i]))];
601

602
    *topology_size = entity_handles_size;
603

604 605
    RETURN(iBase_SUCCESS);
  }
Jim Porter's avatar
Jim Porter committed
606

607 608 609 610 611
  void iMesh_getEntArrType(iMesh_Instance instance,
                           /*in*/ const iBase_EntityHandle* entity_handles,
                           /*in*/ const int entity_handles_size,
                           /*inout*/ int** etype,
                           /*inout*/ int* etype_allocated,
Jim Porter's avatar
Jim Porter committed
612
                           /*out*/ int* etype_size, int *err)
613 614
  {
      // go through each entity and look up its type
615
    ALLOC_CHECK_ARRAY_NOFAIL(etype, entity_handles_size);
616

617
    for (int i = 0; i < entity_handles_size; i++)
Jim Porter's avatar
Jim Porter committed
618
      (*etype)[i] =
619
        tstt_type_table[MOABI->type_from_handle(ENTITY_HANDLE(entity_handles[i]))];
620

621
    *etype_size = entity_handles_size;
622

623 624
    RETURN(iBase_SUCCESS);
  }
625

626 627 628 629 630 631 632 633 634
  void iMesh_getEntArrAdj(iMesh_Instance instance,
                          /*in*/ const iBase_EntityHandle* entity_handles,
                          /*in*/ const int entity_handles_size,
                          /*in*/ const int entity_type_requested,
                          /*inout*/ iBase_EntityHandle** adjacentEntityHandles,
                          /*inout*/ int* adjacentEntityHandles_allocated,
                          /*out*/ int* adjacentEntityHandles_size,
                          /*inout*/ int** offset,
                          /*inout*/ int* offset_allocated,
Jim Porter's avatar
Jim Porter committed
635
                          /*out*/ int* offset_size, int *err)
636
  {
's avatar
committed
637
    ErrorCode result = MB_SUCCESS;
638

639
    ALLOC_CHECK_ARRAY(offset, entity_handles_size+1);
Jim Porter's avatar
Jim Porter committed
640

's avatar
committed
641 642
    const EntityHandle* entity_iter = (const EntityHandle*)entity_handles;
    const EntityHandle* const entity_end = entity_iter + entity_handles_size;
643 644
    int* off_iter = *offset;
    int prev_off = 0;
Jim Porter's avatar
Jim Porter committed
645

's avatar
committed
646 647 648
    std::vector<EntityHandle> conn_storage;
    std::vector<EntityHandle> adj_ents;
    const EntityHandle *connect;
649
    int num_connect;
Jim Porter's avatar
Jim Porter committed
650

's avatar
committed
651
    EntityHandle* array; // ptr to working array of result handles
652 653
    int array_alloc;       // allocated size of 'array'
    const bool allocated_array = !*adjacentEntityHandles_allocated || !*adjacentEntityHandles;
654
    if (allocated_array) {
655 656 657 658
      array = 0;
      array_alloc = 0;
    }
    else {
's avatar
committed
659
      array = reinterpret_cast<EntityHandle*>(*adjacentEntityHandles);
660
      array_alloc = *adjacentEntityHandles_allocated;
661
    }
Jim Porter's avatar
Jim Porter committed
662

663 664 665 666
    for ( ; entity_iter != entity_end; ++entity_iter)
    {
      *off_iter = prev_off;
      off_iter++;
Jim Porter's avatar
Jim Porter committed
667

's avatar
committed
668 669
      if (iBase_VERTEX == entity_type_requested &&
          TYPE_FROM_HANDLE(*entity_iter) != MBPOLYHEDRON) {
670 671
        if (CN::Dimension(TYPE_FROM_HANDLE(*entity_iter)) == 0)
          continue;
672
        result = MOABI->get_connectivity(*entity_iter, connect, num_connect, false, &conn_storage);
673 674 675
        if (MB_SUCCESS != result) {
          if (allocated_array)
            free(array);
676
          ERROR(result, "iMesh_getEntArrAdj: trouble getting adjacency list.");
677
        }
's avatar
committed
678 679
      }
      else if (iBase_ALL_TYPES == entity_type_requested) {
680
        adj_ents.clear();
's avatar
committed
681
        for (int dim = 0; dim < 4; ++dim) {
682
          if (CN::Dimension(TYPE_FROM_HANDLE(*entity_iter)) == dim)
's avatar
committed
683
            continue;
684
          result = MOABI->get_adjacencies( entity_iter, 1, dim, false, adj_ents, Interface::UNION );
685 686 687
          if (MB_SUCCESS != result) {
            if (allocated_array)
              free(array);
688
            ERROR(result, "iMesh_getEntArrAdj: trouble getting adjacency list.");
689
          }
's avatar
committed
690
        }
691 692
        connect = &adj_ents[0];
        num_connect = adj_ents.size();
's avatar
committed
693 694
      }
      else {
695 696
        if (CN::Dimension(TYPE_FROM_HANDLE(*entity_iter)) == entity_type_requested)
          continue;
697
        adj_ents.clear();
Jim Porter's avatar
Jim Porter committed
698
        result = MOABI->get_adjacencies( entity_iter, 1,
699
                                       entity_type_requested, false, adj_ents );
700 701 702
        if (MB_SUCCESS != result) {
          if (allocated_array)
            free(array);
703
          ERROR(result, "iMesh_getEntArrAdj: trouble getting adjacency list.");
704
        }
705 706
        connect = &adj_ents[0];
        num_connect = adj_ents.size();
707
      }
Jim Porter's avatar
Jim Porter committed
708

709 710 711 712
      if (prev_off + num_connect <= array_alloc) {
        std::copy(connect, connect+num_connect, array+prev_off);
      }
      else if (allocated_array) {
713 714 715
          // if array is not allocated yet, guess at initial size
          // as the number of adjacencies for the first entity times
          // the number of input entities.  This will result in a single
Jim Porter's avatar
Jim Porter committed
716
          // exact allocation if one input entity or typical queries
717 718
          // such as connectivity of a non-mixed mesh or regions adjacent
          // to faces.
Jim Porter's avatar
Jim Porter committed
719
        if (!array_alloc)
720 721
          array_alloc = entity_handles_size * num_connect;
        else
Jim Porter's avatar
Jim Porter committed
722
          array_alloc = std::max(array_alloc*2, prev_off+num_connect);
723 724 725
        EntityHandle* new_array = (EntityHandle*)realloc( array, array_alloc*sizeof(EntityHandle) );
        if (!new_array) {
          free(array);
726 727
          RETURN(iBase_MEMORY_ALLOCATION_FAILED);
        }
728 729
        else
          array = new_array;
730 731 732 733 734
        std::copy(connect, connect+num_connect, array+prev_off);
      }
      // else do nothing.  Will catch error later when comparing
      //  occupied to allocated sizes.  Continue here because
      //  must pass back required size.
Jim Porter's avatar
Jim Porter committed
735

736
      prev_off += num_connect;
737
    }
738
    *off_iter = prev_off;
739
    *adjacentEntityHandles_size = prev_off;
740

741
    if (*adjacentEntityHandles_size > array_alloc) {
742 743
      if (allocated_array)
        free(array);
744 745 746 747 748 749
      RETURN(iBase_BAD_ARRAY_SIZE);
    }
    else if (allocated_array) {
      *adjacentEntityHandles = reinterpret_cast<iBase_EntityHandle*>(array);
      *adjacentEntityHandles_allocated = array_alloc;
    }
750

751
    KEEP_ARRAY(offset);
752 753
    RETURN(iBase_SUCCESS);
  }
754

755 756 757
  void iMesh_getEntArr2ndAdj( iMesh_Instance instance,
                              iBase_EntityHandle const* entity_handles,
                              int entity_handles_size,
758
                              int bridge_entity_type,
759 760 761 762 763 764 765 766 767
                              int requested_entity_type,
                              iBase_EntityHandle** adj_entity_handles,
                              int* adj_entity_handles_allocated,
                              int* adj_entity_handles_size,
                              int** offset,
                              int* offset_allocated,
                              int* offset_size,
                              int* err )
  {
768 769 770
    CHKENUM(bridge_entity_type, iBase_EntityType, iBase_INVALID_ENTITY_TYPE);
    CHKENUM(requested_entity_type, iBase_EntityType, iBase_INVALID_ENTITY_TYPE);

's avatar
committed
771
    ErrorCode result = MB_SUCCESS;
772

773 774
    ALLOC_CHECK_ARRAY(offset, entity_handles_size+1);

's avatar
committed
775 776
    const EntityHandle* entity_iter = (const EntityHandle*)entity_handles;
    const EntityHandle* const entity_end = entity_iter + entity_handles_size;
777 778
    int* off_iter = *offset;
    int prev_off = 0;
Jim Porter's avatar
Jim Porter committed
779

's avatar
committed
780
    std::vector<EntityHandle> all_adj_ents;
781
    MeshTopoUtil mtu(MOABI);
Jim Porter's avatar
Jim Porter committed
782

783 784 785 786 787 788 789
    int min_bridge = iBase_VERTEX, max_bridge = iBase_REGION;
    int min_req    = iBase_VERTEX, max_req    = iBase_REGION;
    if (iBase_ALL_TYPES != bridge_entity_type)
      min_bridge = max_bridge = bridge_entity_type;
    if (iBase_ALL_TYPES != requested_entity_type)
      min_req = max_req = requested_entity_type;

790 791 792 793
    for ( ; entity_iter != entity_end; ++entity_iter)
    {
      *off_iter = prev_off;
      off_iter++;
's avatar
committed
794
      Range adj_ents;
795

796 797 798 799 800 801 802 803 804 805 806 807 808
      int source = CN::Dimension(TYPE_FROM_HANDLE(*entity_iter));
      for (int bridge = min_bridge; bridge <= max_bridge; ++bridge) {
        if (source == bridge)
          continue;
        for (int requested = min_req; requested <= max_req; ++requested) {
          if (bridge == requested)
            continue;
          result = mtu.get_bridge_adjacencies( *entity_iter,
                                               bridge,
                                               requested, adj_ents );
          CHKERR(result, "iMesh_getEntArr2ndAdj: trouble getting adjacency list.");
        }
      }
809 810 811 812

      std::copy(adj_ents.begin(), adj_ents.end(), std::back_inserter(all_adj_ents));
      prev_off += adj_ents.size();
    }