root/cgm/cgm_apps/TSTT/TSTTG_CGM.cpp @ 1040

Revision 1040, 105.2 KB (checked in by tautges, 2 years ago)

Version 10.2 of cgm.

Line 
1#include "TSTTG_CGM.h"
2
3#include <iostream>
4#include <math.h>
5
6const bool debug = false;
7
8#define CHECK_SIZE(array, type, this_size)  \
9  if (0 == array ## _allocated || array ## _allocated < this_size) {\
10    if (NULL != array) free(array); \
11    array = (type*)malloc(this_size*sizeof(type));\
12    array ## _allocated=this_size;\
13    if (NULL == array) {TSTTG_processError(TSTTB_MEMORY_ALLOCATION_FAILED, \
14          "Couldn't allocate array.");RETURN(TSTTB_MEMORY_ALLOCATION_FAILED); }\
15  }; \
16  array ## _size = this_size;
17
18// TAG_CHECK_SIZE is like CHECK_SIZE except it checks for and makes the allocated memory
19// size a multiple of sizeof(void*), and the pointer is assumed to be type char*
20#define TAG_CHECK_SIZE(array, allocated, size)  \
21  if (allocated < size) {\
22    if (NULL != array) free(array); \
23    allocated=size; \
24    if (allocated%sizeof(void*) != 0) allocated=(size/sizeof(void*)+1)*sizeof(void*);\
25    array = (char*)malloc(allocated); \
26    if (NULL == array) {TSTTG_processError(TSTTB_MEMORY_ALLOCATION_FAILED, \
27          "Couldn't allocate array.");RETURN(TSTTB_MEMORY_ALLOCATION_FAILED); }\
28  }
29#define TAG_HANDLE(handle) reinterpret_cast<int>(handle)
30#define CONST_TAG_HANDLE(handle) reinterpret_cast<const int>(const_cast<TSTTG_TagHandle>(handle))
31
32#define ENTITY_HANDLE(handle) reinterpret_cast<RefEntity*>(handle)
33#define SET_HANDLE(handle) reinterpret_cast<RefGroup*>(handle)
34
35#define CONST_ENTITY_HANDLE(handle) reinterpret_cast<const RefEntity*>(handle)
36#define CONST_SET_HANDLE(handle) reinterpret_cast<const RefGroup*>(handle)
37
38#define ENTITY_HANDLE_ARRAY(array) reinterpret_cast<RefEntity**>(array)
39#define SET_HANDLE_ARRAY(array) reinterpret_cast<RefGroup**>(array)
40
41#define CONST_ENTITY_HANDLE_ARRAY(array) reinterpret_cast<const RefEntity**>(array)
42#define CONST_SET_HANDLE_ARRAY(array) reinterpret_cast<const RefGroup**>(array)
43
44#define ENTITY_HANDLE_ARRAY_PTR(array) reinterpret_cast<RefEntity***>(array)
45#define SET_HANDLE_ARRAY_PTR(array) reinterpret_cast<RefGroup***>(array)
46
47#define CAST_TO_VOID(ptr) reinterpret_cast<void*>(ptr)
48#define TAG_HANDLE_ARRAY_INOUT(a) reinterpret_cast<int**>(a), a ## _allocated, a ## _size
49
50#define TM reinterpret_cast<CGMTagManager*>(instance)
51
52// map from CGM's dimension to TSTT's entity type
53const TSTTG_GentityType tsttg_type_table[] =
54{
55  TSTTG_VERTEX,         // RefVertex
56  TSTTG_EDGE,           // RefEdge
57  TSTTG_FACE,           // RefFace
58  TSTTG_REGION          // RefVolume
59};
60
61const TSTTG_TagValueType tstt_tag_value_table[] = 
62{
63  TSTTG_BYTES,
64  TSTTG_INTEGER,
65  TSTTG_DOUBLE,
66  TSTTG_ENTITY_HANDLE
67};
68
69const double RAD_TO_DEG = 180.0 / acos(-1.0);
70const double DEG_TO_RAD = 1.0 / RAD_TO_DEG;
71
72#include "CATSTT.hpp"
73#include "RefEntityFactory.hpp"
74#include "BasicTopologyEntity.hpp"
75#include "RefGroup.hpp"
76#include "Body.hpp"
77#include "RefVertex.hpp"
78#include "RefEdge.hpp"
79#include "RefFace.hpp"
80#include "RefVolume.hpp"
81#include "CubitVector.hpp"
82
83#include "FacetQueryEngine.hpp"
84#include "AcisQueryEngine.hpp"
85#include "AcisModifyEngine.hpp"
86#include "CGMApp.hpp"
87#include "GeometryQueryTool.hpp"
88#include "GeometryModifyTool.hpp"
89#include "Surface.hpp"
90#include "BasicTopologyEntity.hpp"
91#include "CubitFile.hpp"
92#include "MergeTool.hpp"
93
94// declare private-type functions here, so they aren't visible outside
95// this implementation file
96void TSTTG_get_adjacent_entities(const RefEntity *from, const int to_dim,
97                                 DLIList<RefEntity*> &adj_ents);
98
99#define gqt GeometryQueryTool::instance()
100#define gmt GeometryModifyTool::instance()
101
102const char *TSTTG_entity_type_names[] = {"vertex", "curve", "surface", "volume", "body"};
103
104TSTTB_Error TSTTG_LAST_ERROR;
105
106// user defined constructor
107enum TSTTB_ErrorType
108TSTTG_ctor(TSTTG_Instance *instance) 
109{
110    // initialize CGM
111  CGMApp::instance()->startup(0, NULL);
112
113    // assume for now we want acis
114  AcisQueryEngine::instance();
115  AcisModifyEngine::instance();
116
117  CGMTagManager *tm = new CGMTagManager();
118
119  CGMApp::instance()->attrib_manager()->silent_flag(true);
120  CGMApp::instance()->attrib_manager()->auto_flag(true);
121
122    // return the tagmanager as the instance
123  *instance = tm;
124
125  RETURN(TSTTB_SUCCESS);
126}
127
128enum TSTTB_ErrorType
129TSTTG_dtor(TSTTG_Instance instance) 
130{
131  if (NULL != TM) delete TM;
132 
133    // shut down CGM
134  CGMApp::instance()->shutdown();
135
136  RETURN(TSTTB_SUCCESS);
137}
138
139// user defined static methods: (none)
140
141// user defined non-static methods:
142/**
143 * Load a model specified by name. Which formats are supported and the
144 * specific meaning of this name string (e.g. file name, model name,
145 * etc.) are implementation-dependent.  Options are also implementation-
146 * dependent.
147 * @param name Name of the model
148 * @param options String options
149 */
150enum TSTTB_ErrorType
151TSTTG_gLoad (TSTTG_Instance instance,
152             /*in*/ const char *name,
153             /*in*/ CONST_ARRAY_IN_DECL(char*, options))
154{
155    // process options
156  bool parallel = false;
157  int par_load_option = -1;
158  for (int i = 0; i < options_size; i++) {
159    if (!strcmp(options[i], "PARALLEL") || !strcmp(options[i], "parallel")) {
160      parallel = true;
161    }
162   
163      // look for parallel load option
164    if (!strcmp(options[i], "GEOM_BCAST") || !strcmp(options[i], "geom_bcast"))
165      par_load_option = 0;
166   
167    if (!strcmp(options[i], "GEOM_BCAST_AND_DELETE") || !strcmp(options[i], "geom_bcast_and_delete"))
168      par_load_option = 1;
169   
170    if (!strcmp(options[i], "GEOM_SCATTER") || !strcmp(options[i], "geom_scatter"))
171      par_load_option = 2;
172  }
173   
174  if (strstr(name, ".cub") != NULL) {
175    return TSTTG_load_cub_geometry(name);
176  }
177 
178  CubitStatus status = gqt->read_geometry_file(name);
179  if (CUBIT_SUCCESS != status) 
180    TSTTG_processError(TSTTB_FILE_NOT_FOUND, "Trouble loading geometry file.");
181
182  RETURN(TSTTB_SUCCESS);
183}
184
185// user defined non-static methods:
186/**
187 * Save a model to file specified by name. Which formats are supported and the
188 * specific meaning of this name string (e.g. file name, model name,
189 * etc.) are implementation-dependent.  Options are also implementation-
190 * dependent.
191 * @param name Name of the model
192 * @param options String options
193 */
194enum TSTTB_ErrorType
195TSTTG_gSave (TSTTG_Instance instance,
196             /*in*/ const char *name,
197             /*in*/ CONST_ARRAY_IN_DECL(char*, options))
198{
199    // process options (none right now...)
200  DLIList<RefEntity*> bodies;
201  int num_ents_exported;
202  CubitString cubit_version(" (TSTTG)");
203  CubitStatus status = gqt->export_solid_model(bodies, name, "ACIS_SAT",
204                                               num_ents_exported, cubit_version);
205  if (CUBIT_SUCCESS != status) 
206    TSTTG_processError(TSTTB_FAILURE, "Trouble saving geometry file.");
207
208  RETURN(TSTTB_SUCCESS);
209}
210
211enum TSTTB_ErrorType
212TSTTG_load_cub_geometry(const char *name) 
213{
214  FILE *cubfile = fopen(name, "rb");
215  if (NULL == cubfile) RETURN(TSTTB_FILE_NOT_FOUND);
216
217    // first get the length
218  int result = fseek(cubfile, 0, SEEK_END);
219  if (result) {
220    TSTTG_processError(TSTTB_FAILURE, "Couldn't seek to end of .cub file.");
221    RETURN(TSTTB_FAILURE);
222  }
223 
224  long endpos = ftell(cubfile);
225 
226  char magic_str[4] = {'\0', '\0', '\0', '\0'};
227  fread(magic_str, 1, 4, cubfile);
228  if (!strcmp(magic_str, "CUBE")) {
229    TSTTG_processError(TSTTB_NOT_SUPPORTED, "Wrong magic string in .cub file.");
230    RETURN(TSTTB_NOT_SUPPORTED);
231  }
232 
233    // get the model header
234  result = fseek(cubfile, 4, SEEK_SET);
235  if (result) {
236    TSTTG_processError(TSTTB_FAILURE, "Seek failed reading cub file header.");
237    RETURN(TSTTB_FAILURE);
238  }
239  int header[6];
240  fread(header, 4, 6, cubfile);
241  int num_models = header[2];
242  int model_table_offset = header[3];
243
244    // get the model table
245  int model_entries[36], model_offset[6], 
246    model_length[6], model_type[6];
247  if (num_models > 6) {
248    TSTTG_processError(TSTTB_INVALID_ARGUMENT, "Too many models in .cub file.");
249    RETURN(TSTTB_INVALID_ARGUMENT);
250  }
251
252  if (model_table_offset+24*num_models-1 > endpos) {
253    TSTTG_processError(TSTTB_FAILURE, "Reading model table will go past end of file.");
254    RETURN(TSTTB_FAILURE);
255  }
256   
257  result = fseek(cubfile, model_table_offset, SEEK_SET);
258  if (result) {
259    TSTTG_processError(TSTTB_FAILURE, "Seek failed seeking to model table.");
260    RETURN(TSTTB_FAILURE);
261  }
262  fread(model_entries, 4, 6*num_models, cubfile);
263  for (int i = 0; i < num_models; i++) {
264    model_type[i] = model_entries[6*i];
265    model_offset[i] = model_entries[6*i+1];
266    model_length[i] = model_entries[6*i+2];
267  }
268 
269    // now read the actual models
270  const char *model_type_str[6] = {"", "ACIS_SAT", "", "FACET", "", "GRANITE"};
271  for (int i = 0; i < num_models; i++) {
272    if ((1 != model_type[i] && 3 != model_type[i] && 5 != model_type[i]) ||
273        model_length[i] == 0) continue;
274
275    if (model_offset[i] > endpos) {
276      TSTTG_processError(TSTTB_FAILURE, "Reading actual model will go past end of file.");
277      RETURN(TSTTB_FAILURE);
278    }
279    result = fseek(cubfile, model_offset[i], SEEK_SET);
280    if (result) {
281      TSTTG_processError(TSTTB_FAILURE, "Seek failed seeking to a model.");
282      RETURN(TSTTB_FAILURE);
283    }
284      // if the type is facet, need special handling
285    if (3 == model_type[i]) {
286        // first create an instance of the facet engine
287      FacetQueryEngine::instance();
288        // now copy the file contents to a scratch file
289      fclose(cubfile);
290      cubfile = tmpfile();
291      NCubitFile::CCubitFile ccf;
292      ccf.Open(name, NULL, NULL);
293      ccf.BeginReadGeomModel(3, cubfile);
294      ccf.EndReadGeomModel();
295    }
296
297    CubitStatus status = gqt->import_temp_geom_file(cubfile, model_type_str[model_type[i]]);
298    if (CUBIT_SUCCESS != status) {
299      std::string msg = std::string("Trouble loading geometry file of type ") + 
300        model_type_str[model_type[i]] + std::string(".");
301      TSTTG_processError(TSTTB_FAILURE, msg.c_str());
302    }
303
304      // finish up if reading a facet file
305    if (3 == model_type[i]) {
306      fclose(cubfile);
307      cubfile = fopen(name, "rb");
308      if (NULL == cubfile) 
309        RETURN(TSTTB_SUCCESS);
310    }
311  }
312
313  if (NULL != cubfile) fclose(cubfile);
314
315  RETURN(TSTTB_SUCCESS);
316}
317                               
318/**
319 * Initialize an iterator over gentities of a specified dimension.
320 * @param gentity_dimension Dimension of gentities to be iterated over
321 * @param gentity_iterator Iterator initialized by this function
322 */
323
324enum TSTTB_ErrorType
325TSTTG_gentityIteratorInit (TSTTG_Instance instance,
326                           /*in*/ const int gentity_dimension,
327                           /*out*/ TSTTG_GentityIterator *gentity_iterator)
328{
329  RETURN(TSTTB_NOT_SUPPORTED);
330}
331
332/**
333 * Get the next entity for this iterator.
334 * @param gentity_iterator Iterator being iterated over
335 * @param gentity_handle Next gentity
336 * @return If true, there are more gentities, if false, this is the last one
337 */
338bool
339TSTTG_gentityIteratorNext (TSTTG_Instance instance,
340                           /*inout*/ TSTTG_GentityIterator *gentity_iterator,
341                           /*out*/ TSTTG_GentityHandle *gentity_handle
342                           )
343{
344  TSTTG_processError(TSTTB_NOT_SUPPORTED, "Operation not supported.");
345  return false;
346}
347
348/**
349 * Reset an iterator back to the first gentity
350 * @param gentity_iterator Iterator reset by this function
351 */
352enum TSTTB_ErrorType
353TSTTG_gentityIteratorReset(TSTTG_Instance instance,
354                           /*inout*/ TSTTG_GentityIterator *gentity_iterator
355                           )
356{
357  RETURN(TSTTB_NOT_SUPPORTED);
358}
359
360/**
361 * Delete an iterator
362 * @param gentity_iterator Iterator deleted by this function
363 */
364enum TSTTB_ErrorType
365TSTTG_gentityIteratorDelete (TSTTG_Instance instance,
366                             /*in*/ TSTTG_CGentityIterator Gentity_dim_iterator)
367{
368  RETURN(TSTTB_NOT_SUPPORTED);
369}
370
371/**
372 *   Returns true if the gentity_sets are related through a parent/child
373 *   relationship.
374 */
375bool
376TSTTG_isChildOf (TSTTG_Instance instance,
377                 /*in*/ TSTTG_CGentitySetHandle parent_entity_set,
378                 /*in*/ TSTTG_CGentitySetHandle child_entity_set)
379{
380  std::vector<RefGroup*> *par1, *ch1, *par2, *ch2;
381  TM->pc_list(const_cast<RefGroup*>(CONST_SET_HANDLE(parent_entity_set)), par1, ch1, false);
382  if (NULL == ch1 || ch1->empty()) return false;
383  TM->pc_list(const_cast<RefGroup*>(CONST_SET_HANDLE(child_entity_set)), par2, ch2, false);
384  if (NULL == par2 || par2->empty()) return false;
385 
386  const RefGroup *group1 = CONST_SET_HANDLE(parent_entity_set);
387  const RefGroup *group2 = CONST_SET_HANDLE(child_entity_set);
388  if ((std::find(ch1->begin(), ch1->end(), group2) != ch1->end())
389      || (std::find(par2->begin(), par2->end(), group1) != par2->end()))
390    return true;
391 
392  else return false;
393}
394
395/**
396 *   Recursively gets the children of this gentity_set up to num_hops
397 *   levels; if num_hops is set to -1 all children are returned
398 */
399enum TSTTB_ErrorType
400TSTTG_getChldn (TSTTG_Instance instance,
401                /*in*/ TSTTG_CGentitySetHandle from_entity_set,
402                /*in*/ const int num_hops,
403                /*inout*/ ARRAY_INOUT_DECL(TSTTG_GentitySetHandle, 
404                                           entity_set_handles))
405{
406  std::vector<RefGroup*> group_ptrs;
407  const RefGroup *this_grp = CONST_SET_HANDLE(from_entity_set);
408  TM->get_pc_groups(const_cast<RefGroup*>(this_grp), 1, num_hops, group_ptrs);
409  CHECK_SIZE(*entity_set_handles, TSTTG_GentityHandle, 
410             (int)group_ptrs.size());
411
412  std::copy(group_ptrs.begin(), group_ptrs.end(), *entity_set_handles);
413 
414  RETURN(TSTTB_SUCCESS);
415}
416
417/**
418 *   Recursively gets the parents of this gentity_set up to num_hops
419 *   levels; if num_hops is set to -1 all parents are returned
420 */
421enum TSTTB_ErrorType
422TSTTG_getPrnts (TSTTG_Instance instance,
423                /*in*/ TSTTG_CGentitySetHandle from_entity_set,
424                /*in*/ const int num_hops,
425                /*inout*/ ARRAY_INOUT_DECL(TSTTG_GentitySetHandle, entity_set_handles))
426{
427  std::vector<RefGroup*> group_ptrs;
428  const RefGroup *this_grp = CONST_SET_HANDLE(from_entity_set);
429  TM->get_pc_groups(const_cast<RefGroup*>(this_grp), 0, num_hops, group_ptrs);
430  CHECK_SIZE(*entity_set_handles, TSTTG_GentityHandle, 
431             (int)group_ptrs.size());
432
433  std::copy(group_ptrs.begin(), group_ptrs.end(), *entity_set_handles);
434  RETURN(TSTTB_SUCCESS);
435}
436
437/**
438 *   Returns the number of immediate children in the gentity_set (one
439 *   level down only)
440 */
441int
442TSTTG_getNumChld (TSTTG_Instance instance,
443                  /*in*/ TSTTG_CGentitySetHandle entity_set,
444                  /*in*/ const int num_hops)
445{
446    // HJK: num_hops has to be handled
447  if (1 < num_hops) {
448    TSTTG_processError(TSTTB_NOT_SUPPORTED, "Num_hops argument not yet supported.");
449    return -1;
450  }
451
452  std::vector<RefGroup*> *my_children = TM->pc_list(const_cast<RefGroup*>(CONST_SET_HANDLE(entity_set)), 1, false);
453  if (NULL == my_children || my_children->empty()) return 0;
454  else return my_children->size();
455}
456
457/**
458 *   Returns the number of immediate parents to the gentity_set (one
459 *   level up only)
460 */
461int
462TSTTG_getNumPrnt (TSTTG_Instance instance,
463                  /*in*/ TSTTG_CGentitySetHandle entity_set,
464                  /*in*/ const int num_hops)
465{
466    // HJK: num_hops has to be handled
467  if (1 < num_hops) {
468    TSTTG_processError(TSTTB_NOT_SUPPORTED, "Num_hops argument not yet supported.");
469    return -1;
470  }
471
472  std::vector<RefGroup*> *my_parents = TM->pc_list(const_cast<RefGroup*>(CONST_SET_HANDLE(entity_set)), 0, false);
473  if (NULL == my_parents || my_parents->empty()) return 0;
474  else return my_parents->size();
475}
476
477/**
478 *   Add a parent to the gentity_set
479 */
480enum TSTTB_ErrorType
481TSTTG_addPrntChld (TSTTG_Instance instance,
482                   /*inout*/ TSTTG_GentitySetHandle *parent_entity_set,
483                   /*inout*/ TSTTG_GentitySetHandle *child_entity_set)
484{
485  std::vector<RefGroup*> *my_parents = 
486    TM->pc_list(SET_HANDLE(*child_entity_set), 0, true);
487  std::vector<RefGroup*> *my_children = 
488    TM->pc_list(SET_HANDLE(*parent_entity_set), 1, true);
489  RefGroup *par_group = SET_HANDLE(*parent_entity_set);
490  RefGroup *child_group = SET_HANDLE(*child_entity_set);
491  my_parents->push_back(par_group);
492  my_children->push_back(child_group);
493  RETURN(TSTTB_SUCCESS);
494}
495
496/**
497 *   Remove a parent/child link between gentity_sets
498 */
499enum TSTTB_ErrorType
500TSTTG_rmvPrntChld (TSTTG_Instance instance,
501                   /*inout*/ TSTTG_GentitySetHandle *parent_entity_set,
502                   /*inout*/ TSTTG_GentitySetHandle *child_entity_set)
503{
504  RefGroup *parent = reinterpret_cast<RefGroup *>(*parent_entity_set);
505  RefGroup *child = reinterpret_cast<RefGroup *>(*child_entity_set);
506  std::vector<RefGroup*> *children = TM->pc_list(parent, 1, false),
507    *parents = TM->pc_list(child, 0, false);
508  if (NULL == children || NULL == parents) {
509    RETURN(TSTTB_INVALID_ARGUMENT);
510  }
511 
512  children->erase(std::remove(children->begin(), children->end(), child), children->end());
513  parents->erase(std::remove(parents->begin(), parents->end(), parent), parents->end());
514  RETURN(TSTTB_SUCCESS);
515}
516
517/**
518 * Return gentities of specified dimension in this set, or in whole model.
519 * @param set_handle Entity set being queried (if 0, whole model)
520 * @param gentity_dimension Dimension of entities being queried
521 * @param gentity_handles Gentity handles
522 */
523enum TSTTB_ErrorType
524TSTTG_gentitysetGetGentitiesOfType (TSTTG_Instance instance,
525                                    /*in*/ TSTTG_CGentitySetHandle set_handle,
526                                    /*in*/ const TSTTG_GentityType gentity_type,
527                                    /*out*/ ARRAY_INOUT_DECL(TSTTG_GentityHandle, gentity_handles))
528{
529  const RefGroup *this_set = CONST_SET_HANDLE(set_handle);
530  static DLIList<RefEntity*> dim_entities;
531  dim_entities.clean_out();
532  if (0 == this_set) {
533    if (gentity_type == TSTTG_ALL_TYPES) {
534      for (int i = 0; i < 4; i++) {
535        static DLIList<RefEntity*> temp_entities;
536        RefEntityFactory::instance()->ref_entity_list(TSTTG_entity_type_names[i], 
537                                                      temp_entities, CUBIT_FALSE);
538        dim_entities += temp_entities;
539      }
540    }
541    else {
542      RefEntityFactory::instance()->ref_entity_list(TSTTG_entity_type_names[gentity_type], 
543                                                    dim_entities, CUBIT_FALSE);
544    }
545  }
546  else {
547    static DLIList<CubitEntity*> centities;
548    static DLIList<RefEntity*> entities;
549    centities.clean_out();
550    entities.clean_out();
551    const_cast<RefGroup*>(this_set)->get_child_entities(centities);
552    CAST_LIST(centities, entities, RefEntity);
553    if (gentity_type == 4) {
554      dim_entities += entities;
555    }
556    else {
557      entities.reset();
558      int num_ents = entities.size();
559      for (int i = 0; i < num_ents; i++) {
560        if (entities.get()->dimension() == gentity_type)
561          dim_entities.append(entities.get_and_step());
562        else
563          entities.step();
564      }
565    }
566  }
567   
568  CHECK_SIZE(*gentity_handles, TSTTG_GentityHandle, dim_entities.size());
569  dim_entities.copy_to((RefEntity**)*gentity_handles);
570  RETURN(TSTTB_SUCCESS);
571}
572
573/**
574 * Return number of gentities of specified dimension in this set, or in
575 * whole model.
576 * @param set_handle Entity set being queried (if 0, whole model)
577 * @param gentity_dimension Dimension of entities being queried
578 * @return Number of entities
579 */
580int
581TSTTG_gentitysetGetNumberGentitiesOfType (TSTTG_Instance instance,
582                                          /*in*/ TSTTG_CGentitySetHandle set_handle,
583                                          /*in*/ const TSTTG_GentityType gentity_type)
584{
585  const RefGroup *this_set = CONST_SET_HANDLE(set_handle);
586  static DLIList<RefEntity*> *dim_entities = NULL;
587  if (NULL == dim_entities) dim_entities = new DLIList<RefEntity*>();
588  dim_entities->clean_out();
589  if (0 == this_set) {
590    RefEntityFactory::instance()->ref_entity_list(TSTTG_entity_type_names[gentity_type], 
591                                                  *dim_entities, CUBIT_FALSE);
592  }
593  else {
594    static DLIList<CubitEntity*> centities;
595    static DLIList<RefEntity*> entities;
596    centities.clean_out();
597    entities.clean_out();
598    const_cast<RefGroup*>(this_set)->get_child_entities(centities);
599    CAST_LIST(centities, entities, RefEntity);
600    entities.reset();
601    int num_ents = entities.size();
602    for (int i = 0; i < num_ents; i++) {
603      if (entities.get()->dimension() == gentity_type)
604        dim_entities->append(entities.get_and_step());
605      else
606        entities.step();
607    }
608  }
609   
610  return dim_entities->size();
611}
612
613/**
614 *    Returns an integer array of topological dimensions for an input
615 *    array of entity handles.
616 */
617enum TSTTB_ErrorType
618TSTTG_gentityGetType (TSTTG_Instance instance,
619                      /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, gentity_handles),
620                      /*inout*/ ARRAY_INOUT_DECL(TSTTG_GentityType, gtype))
621{
622    // go through each entity and look up its dimension
623  CHECK_SIZE(*gtype, TSTTG_GentityType, gentity_handles_size);
624
625  const RefEntity **tmp_handles = CONST_ENTITY_HANDLE_ARRAY(gentity_handles);
626 
627  for (int i = 0; i < gentity_handles_size; i++) {
628    (*gtype)[i] = (TSTTG_GentityType) tmp_handles[i]->dimension();
629  }
630
631  RETURN(TSTTB_SUCCESS);
632}
633
634/**
635 * Get the adjacent entities of a given dimension.
636 * @param gentity_handle Entity for which adjacencies are requested
637 * @param to_dimension Target dimension of adjacent entities
638 * @param adj_gentities List returned with adjacent entities
639 */
640enum TSTTB_ErrorType
641TSTTG_gentityGetAdjacencies (TSTTG_Instance instance,
642                             /*in*/ TSTTG_CGentityHandle gentity_handle,
643                             /*in*/ const int to_dimension,
644                             /*inout*/ ARRAY_INOUT_DECL(TSTTG_GentityHandle, adj_gentities))
645{
646  const RefEntity *tmp_hndl = CONST_ENTITY_HANDLE(gentity_handle);
647
648  if (tmp_hndl->dimension() == to_dimension) {
649    TSTTG_processError(TSTTB_INVALID_ARGUMENT, "Can't get adjacencies to entities of same dimension.");
650    return TSTTB_INVALID_ARGUMENT;
651  }
652
653  static DLIList<RefEntity*> tmp_ents;
654  TSTTG_get_adjacent_entities(tmp_hndl, to_dimension, tmp_ents);
655
656  CHECK_SIZE(*adj_gentities, TSTTG_GentityHandle, (int) tmp_ents.size());
657  tmp_ents.copy_to((RefEntity**)*adj_gentities);
658  RETURN(TSTTB_SUCCESS);
659}
660
661void TSTTG_get_adjacent_entities(const RefEntity *from, const int to_dim,
662                                 DLIList<RefEntity*> &adj_ents) 
663{
664  TopologyEntity *topo_ent = const_cast<TopologyEntity*>(dynamic_cast<const TopologyEntity*>(from));
665  if (NULL == topo_ent) return;
666 
667  adj_ents.clean_out();
668  static DLIList<RefVertex*> tmp_verts;
669  static DLIList<RefEdge*> tmp_edges;
670  static DLIList<RefFace*> tmp_faces;
671  static DLIList<RefVolume*> tmp_volumes;
672  switch (to_dim) {
673    case 0:
674      tmp_verts.clean_out();
675      topo_ent->ref_vertices(tmp_verts);
676      CAST_LIST_TO_PARENT(tmp_verts, adj_ents);
677      break;
678    case 1:
679      tmp_edges.clean_out();
680      topo_ent->ref_edges(tmp_edges);
681      CAST_LIST_TO_PARENT(tmp_edges, adj_ents);
682      break;
683    case 2:
684      tmp_faces.clean_out();
685      topo_ent->ref_faces(tmp_faces);
686      CAST_LIST_TO_PARENT(tmp_faces, adj_ents);
687      break;
688    case 3:
689      tmp_volumes.clean_out();
690      topo_ent->ref_volumes(tmp_volumes);
691      CAST_LIST_TO_PARENT(tmp_volumes, adj_ents);
692      break;
693  }
694}
695 
696/**
697 * Get the "2nd order" adjacent entities, through a specified "bridge"
698 * dimension, of a target dimension.  For example, given a region, return
699 * the regions (to_dimension=3) sharing an edge (bridge_dimension=1)
700 * with that region.  bridge_dimension must be less than dimension of
701 * gentity_handle, and to_dimension must be greater than bridge dimension.
702 *
703 * @param gentity_handle Entity for which 2nd order adjacencies are requested
704 * @param to_dimension Target dimension of 2nd order adjacent entities
705 * @param bridge_dimension Dimension of "bridge" entities
706 * @param adj_gentities List returned with 2nd order adjacent entities
707 */
708enum TSTTB_ErrorType
709TSTTG_gentityGet2OAdjacencies (TSTTG_Instance instance,
710                               /*in*/ TSTTG_CGentityHandle gentity_handle,
711                               /*in*/ const int bridge_dimension,
712                               /*in*/ const int to_dimension,
713                               /*out*/ ARRAY_INOUT_DECL(TSTTG_GentityHandle, adjacent_gentities))
714{
715    // for better or worse, go to cgm as quickly as possible, to avoid working with
716    // sidl arrays
717  const RefEntity *gentity = CONST_ENTITY_HANDLE(gentity_handle);
718  DLIList<RefEntity*> to_ents, bridge_ents, tmp_ents;
719
720  TSTTG_get_adjacent_entities(gentity, bridge_dimension, bridge_ents);
721 
722  for (int i = bridge_ents.size(); i > 0; i--) {
723    TSTTG_get_adjacent_entities(bridge_ents.get_and_step(), to_dimension, tmp_ents);
724    to_ents += tmp_ents;
725    tmp_ents.clean_out();
726  }
727 
728  to_ents.uniquify_unordered();
729
730  CHECK_SIZE(*adjacent_gentities, TSTTG_GentityHandle, (int) to_ents.size());
731  to_ents.copy_to((RefEntity**)*adjacent_gentities);
732
733  RETURN(TSTTB_SUCCESS);
734}
735
736/**
737 * Return whether or not entities are adjacent.
738 * @param gentity_handle1 1st entity
739 * @param gentity_handle2 2nd entity
740 * @param are_adjacent If true, entities are adjacent
741 */
742enum TSTTB_ErrorType
743TSTTG_gentityIsAdjacent (TSTTG_Instance instance,
744                         /*in*/ TSTTG_CGentityHandle gentity_handle1,
745                         /*in*/ TSTTG_CGentityHandle gentity_handle2,
746                         /*out*/ bool *are_adjacent)
747{
748  const TopologyEntity *ent1 = dynamic_cast<const TopologyEntity*>(CONST_ENTITY_HANDLE(gentity_handle1));
749  const TopologyEntity *ent2 = dynamic_cast<const TopologyEntity*>(CONST_ENTITY_HANDLE(gentity_handle2));
750  if (ent1 != NULL && ent2 != NULL)
751    *are_adjacent = const_cast<TopologyEntity*>(ent1)->is_directly_related(const_cast<TopologyEntity*>(ent2));
752  else *are_adjacent = false;
753  RETURN(TSTTB_SUCCESS);
754}
755
756/**
757 *
758 *   Create a tag handle with a given name, size (in bytes), and
759 *   default value.  The tag name is a unique string; if it duplicates
760 *   an existing tag name, an error is returned.  The tag_handle is
761 *   returned as an opaque value which is not associated with any mesh
762 *   gentities until explicitly done so through one of the 'AddTag'
763 *   functions defined later.  The implementation is assumed to
764 *   allocate memory as needed to store the tag data.
765 */
766enum TSTTB_ErrorType
767TSTTG_createTag (TSTTG_Instance instance,
768                 /*in*/ const char *tag_name,
769                 /*in*/ const int tag_size,
770                 /*in*/ const TSTTG_TagValueType tag_type,
771                 /*out*/ TSTTG_TagHandle *tag_handle)
772{
773  int new_tag;
774  int this_size = tag_size;
775  switch (tag_type) {
776    case TSTTG_INTEGER:
777      this_size *= sizeof(int);
778      break;
779    case TSTTG_DOUBLE:
780      this_size *= sizeof(double);
781      break;
782    case TSTTG_ENTITY_HANDLE:
783      this_size *= sizeof(TSTTG_GentityHandle);
784      break;
785    case TSTTG_BYTES:
786      break;
787  }
788  TM->createTag(tag_name, this_size, tag_type, NULL, &new_tag);
789  *tag_handle = (TSTTG_TagHandle) new_tag;
790  RETURN(TSTTB_SUCCESS);
791}
792
793/**
794 *   Delete a tag handle and the data associated with that tag.  The
795 *   deletion can be forced or not forced.  If the deletion is forced,
796 *   the tag and all of its associated data are deleted from the
797 *   implementation even if the tag is still associated with mesh
798 *   gentities.  If the deletion is not forced, the tag will not be
799 *   deleted if it is still associated with one or more mesh gentities.
800 *   In this case an error is returned asking the user to remove the
801 *   tag from that gentity before deleting it.  If the underlying
802 *   implementation does not support the requested deletion mechanism,
803 *   an error will be returned.
804 */
805enum TSTTB_ErrorType
806TSTTG_destroyTag (TSTTG_Instance instance,
807                  /*in*/ const TSTTG_TagHandle tag_handle,
808                  /*in*/ const bool forced)
809{
810  TM->destroyTag(CONST_TAG_HANDLE(tag_handle), forced);
811  RETURN(TSTTB_SUCCESS);
812}
813
814/**
815 *   Get the tag name associated with a given tag handle.
816 */
817const char *
818TSTTG_getTagName (TSTTG_Instance instance,
819                  /*in*/ const TSTTG_TagHandle tag_handle)
820{
821  return TM->getTagName(CONST_TAG_HANDLE(tag_handle));
822}
823
824/**
825 *   Get the size of the data associated with a given tag handle.
826 */
827int
828TSTTG_getTagSizeValues (TSTTG_Instance instance,
829                        /*in*/ const TSTTG_TagHandle tag_handle)
830{
831  int this_size = TM->getTagSize(CONST_TAG_HANDLE(tag_handle));
832  switch (TSTTG_getTagType(instance, tag_handle)) {
833    case TSTTG_INTEGER:
834      this_size /= sizeof(int);
835      break;
836    case TSTTG_DOUBLE:
837      this_size /= sizeof(double);
838      break;
839    case TSTTG_ENTITY_HANDLE:
840      this_size /= sizeof(TSTTG_GentityHandle);
841      break;
842    case TSTTG_BYTES:
843      break;
844  }
845  return this_size;
846}
847
848/**
849 *   Get the size of the data associated with a given tag handle.
850 */
851int
852TSTTG_getTagSizeBytes (TSTTG_Instance instance,
853                       /*in*/ const TSTTG_TagHandle tag_handle)
854{
855  return TM->getTagSize(CONST_TAG_HANDLE(tag_handle));
856}
857
858TSTTG_TagValueType
859TSTTG_getTagType (TSTTG_Instance instance,
860                    /*in*/ const TSTTG_TagHandle tag_handle)
861{
862  return (TSTTG_TagValueType) TM->getTagType(CONST_TAG_HANDLE(tag_handle));
863}
864
865/**
866 *     Get the tag handle associated with a given string name.
867 */
868TSTTG_TagHandle
869TSTTG_getTagHandle (TSTTG_Instance instance,
870                    /*in*/ const char *tag_name)
871{
872  return (TSTTG_TagHandle) TM->getTagHandle(tag_name);
873}
874
875enum TSTTB_ErrorType
876TSTTG_rmvArrTag (TSTTG_Instance instance,
877                 /*in*/ ARRAY_IN_DECL(TSTTG_GentityHandle, entity_handles),
878                 /*in*/ const TSTTG_TagHandle tag_handle) 
879{
880  RefEntity **tmp_entity_handles = ENTITY_HANDLE_ARRAY(entity_handles); 
881  TM->rmvArrTag(tmp_entity_handles, entity_handles_size, CONST_TAG_HANDLE(tag_handle));
882  RETURN(TSTTB_SUCCESS);
883}
884
885/**
886 *   Allows the user to disassociate the tag referenced by the tag
887 *   handle from the specified gentities. The tag data is not deleted in
888 *   this call, but can be deleted later using the deleteTag function
889 *   defined above.
890 */
891enum TSTTB_ErrorType
892TSTTG_rmvTag (TSTTG_Instance instance,
893              /*in*/ TSTTG_GentityHandle entity_handle,
894              /*in*/ const TSTTG_TagHandle tag_handle)
895{
896  RefEntity *tmp_entity = ENTITY_HANDLE(entity_handle);
897  TM->rmvArrTag(&tmp_entity, 1, CONST_TAG_HANDLE(tag_handle));
898  RETURN(TSTTB_SUCCESS);
899}
900
901/**
902 *   Get all tag handles associated with a given gentity.
903 */
904enum TSTTB_ErrorType
905TSTTG_getAllTags (TSTTG_Instance instance,
906                  /*in*/ TSTTG_CGentityHandle entity_handle,
907                  /*inout*/ ARRAY_INOUT_DECL(TSTTG_TagHandle, tag_handles))
908{
909  TM->getAllTags(CONST_SET_HANDLE(entity_handle), 
910                 TAG_HANDLE_ARRAY_INOUT(tag_handles));
911  RETURN(TSTTB_SUCCESS);
912}
913
914enum TSTTB_ErrorType
915TSTTG_getArrData (TSTTG_Instance instance,
916                    /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, entity_handles),
917                    /*in*/ const TSTTG_TagHandle tag_handle,
918                    /*inout*/ ARRAY_INOUT_DECL(char, tag_value))
919{
920  const RefEntity **tmp_entity_handles = CONST_ENTITY_HANDLE_ARRAY(entity_handles); 
921  TM->getArrData(tmp_entity_handles, entity_handles_size,
922                 CONST_TAG_HANDLE(tag_handle), 
923                 ARRAY_INOUT(tag_value));
924  RETURN(TSTTB_SUCCESS);
925}
926
927
928enum TSTTB_ErrorType
929TSTTG_getIntArrData (TSTTG_Instance instance,
930                       /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, entity_handles),
931                       /*in*/ const TSTTG_TagHandle tag_handle,
932                       /*inout*/ ARRAY_INOUT_DECL(int, tag_value))
933{
934  *tag_value_allocated *= sizeof(int);
935  *tag_value_size *= sizeof(int);
936  TSTTB_ErrorType retval = TSTTG_getArrData(instance, entity_handles, 
937                                           entity_handles_size, tag_handle,
938                                           reinterpret_cast<char**>(tag_value), 
939                                           tag_value_allocated, 
940                                           tag_value_size);
941  *tag_value_allocated /= sizeof(int);
942  *tag_value_size /= sizeof(int);
943  return retval;
944}
945
946
947enum TSTTB_ErrorType
948TSTTG_getDblArrData (TSTTG_Instance instance,
949                       /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, entity_handles),
950                       /*in*/ const TSTTG_TagHandle tag_handle,
951                       /*inout*/ ARRAY_INOUT_DECL(double, tag_value))
952{
953  *tag_value_allocated *= sizeof(double);
954  *tag_value_size *= sizeof(double);
955  TSTTB_ErrorType retval = TSTTG_getArrData(instance, entity_handles, 
956                                           entity_handles_size, tag_handle,
957                                           reinterpret_cast<char**>(tag_value), 
958                                           tag_value_allocated, tag_value_size);
959  *tag_value_allocated /= sizeof(double);
960  *tag_value_size /= sizeof(double);
961  return retval;
962}
963
964enum TSTTB_ErrorType
965TSTTG_getEHArrData (TSTTG_Instance instance,
966                      /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, entity_handles),
967                      /*in*/ const TSTTG_TagHandle tag_handle,
968                      /*inout*/ ARRAY_INOUT_DECL(void*, tag_value))
969{
970  *tag_value_allocated *= sizeof(TSTTG_GentityHandle);
971  *tag_value_size *= sizeof(TSTTG_GentityHandle);
972  TSTTB_ErrorType retval = TSTTG_getArrData(instance, entity_handles, 
973                                           entity_handles_size, tag_handle,
974                                           reinterpret_cast<char**>(tag_value), 
975                                           tag_value_allocated, 
976                                           tag_value_size);
977  *tag_value_allocated /= sizeof(TSTTG_GentityHandle);
978  *tag_value_size /= sizeof(TSTTG_GentityHandle);
979  return retval;
980}
981
982enum TSTTB_ErrorType
983TSTTG_setArrData (TSTTG_Instance instance,
984                    /*in*/ ARRAY_IN_DECL(TSTTG_GentityHandle, entity_handles),
985                    /*in*/ const TSTTG_TagHandle tag_handle,
986                    /*in*/ CONST_ARRAY_IN_DECL(char, tag_value))
987{
988  CubitStatus status = TM->setArrData(ENTITY_HANDLE_ARRAY(entity_handles),
989                                      entity_handles_size,
990                                      TAG_HANDLE(tag_handle), 
991                                      ARRAY_IN(tag_value));
992
993  if (CUBIT_SUCCESS == status) {
994    RETURN(TSTTB_SUCCESS);
995  }
996  else {
997    RETURN(TSTTB_FAILURE);
998  }
999}
1000
1001enum TSTTB_ErrorType
1002TSTTG_setIntArrData (TSTTG_Instance instance,
1003                       /*in*/ ARRAY_IN_DECL(TSTTG_GentityHandle, entity_handles),
1004                       /*in*/ const TSTTG_TagHandle tag_handle,
1005                       /*in*/ CONST_ARRAY_IN_DECL(int, tag_value))
1006{
1007  return TSTTG_setArrData(instance, entity_handles, 
1008                          entity_handles_size, tag_handle, 
1009                          reinterpret_cast<const char*>(tag_value), 
1010                          sizeof(int)*tag_value_size);
1011}
1012
1013enum TSTTB_ErrorType
1014TSTTG_setDblArrData (TSTTG_Instance instance,
1015                       /*in*/ ARRAY_IN_DECL(TSTTG_GentityHandle, entity_handles),
1016                       /*in*/ const TSTTG_TagHandle tag_handle,
1017                       /*in*/ CONST_ARRAY_IN_DECL(double, tag_value))
1018{
1019  return TSTTG_setArrData(instance, entity_handles, 
1020                   entity_handles_size, tag_handle, 
1021                          reinterpret_cast<const char*>(tag_value), 
1022                          sizeof(double)*tag_value_size);
1023}
1024
1025enum TSTTB_ErrorType
1026TSTTG_setEHArrData (TSTTG_Instance instance,
1027                      /*in*/ ARRAY_IN_DECL(TSTTG_GentityHandle, entity_handles),
1028                      /*in*/ const TSTTG_TagHandle tag_handle,
1029                      /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, tag_values))
1030{
1031  return TSTTG_setArrData(instance, entity_handles, 
1032                   entity_handles_size, tag_handle, 
1033                          reinterpret_cast<const char*>(tag_values), 
1034                          sizeof(TSTTG_GentityHandle)*tag_values_size);
1035}
1036
1037/**
1038 *   Allows the user to retrieve an array of tag values associated with
1039 *   a tag handle from an input array of gentity handles
1040 */
1041enum TSTTB_ErrorType
1042TSTTG_getData (TSTTG_Instance instance,
1043               /*in*/ TSTTG_CGentityHandle entity_handle,
1044               /*in*/ const TSTTG_TagHandle tag_handle,
1045               /*inout*/ ARRAY_INOUT_DECL(char, tag_value))
1046{
1047  const RefEntity *tmp_entity = CONST_ENTITY_HANDLE(entity_handle);
1048  TM->getArrData(&tmp_entity, 1, CONST_TAG_HANDLE(tag_handle), 
1049                 ARRAY_INOUT(tag_value));
1050  RETURN(TSTTB_SUCCESS);
1051}
1052
1053int
1054TSTTG_getIntData (TSTTG_Instance instance,
1055                  /*in*/ TSTTG_CGentityHandle entity_handle,
1056                  /*in*/ const TSTTG_TagHandle tag_handle ) 
1057{
1058  int val;
1059  char *val_ptr = reinterpret_cast<char*>(&val);
1060  int val_size = sizeof(int);
1061  TSTTG_getArrData(instance, &entity_handle, 1, 
1062                   tag_handle, &val_ptr, &val_size, &val_size);
1063  return val;
1064}
1065
1066double
1067TSTTG_getDblData (TSTTG_Instance instance,
1068                  /*in*/ TSTTG_CGentityHandle entity_handle,
1069                  /*in*/ const TSTTG_TagHandle tag_handle ) 
1070{
1071  double val;
1072  char *val_ptr = reinterpret_cast<char*>(&val);
1073  int val_size = sizeof(double);
1074  TSTTG_getArrData(instance, &entity_handle, 1, 
1075                   tag_handle, &val_ptr, &val_size, &val_size);
1076  return val;
1077}
1078
1079TSTTG_GentityHandle
1080TSTTG_getEHData (TSTTG_Instance instance,
1081                 /*in*/ TSTTG_CGentityHandle entity_handle,
1082                 /*in*/ const TSTTG_TagHandle tag_handle ) 
1083{
1084  TSTTG_GentityHandle val;
1085  char *val_ptr = reinterpret_cast<char*>(&val);
1086  int dum = sizeof(TSTTG_GentityHandle);
1087  TSTTG_getArrData(instance, &entity_handle, 1, 
1088                   tag_handle, &val_ptr, &dum, &dum);
1089  return val;
1090}
1091
1092/**
1093 *   Allows the user to set the tag data values on an array of gentity
1094 *   handles
1095 */
1096enum TSTTB_ErrorType
1097TSTTG_setData (TSTTG_Instance instance,
1098               /*in*/ TSTTG_GentityHandle entity_handle,
1099               /*in*/ const TSTTG_TagHandle tag_handle,
1100               /*in*/ CONST_ARRAY_IN_DECL(char, tag_value))
1101{
1102  RefEntity *tmp_entity = ENTITY_HANDLE(entity_handle);
1103  TM->setArrData(&tmp_entity, 1, 
1104                 CONST_TAG_HANDLE(tag_handle), 
1105                 ARRAY_IN(tag_value));
1106  RETURN(TSTTB_SUCCESS);
1107}
1108
1109TSTTB_ErrorType
1110TSTTG_setIntData (TSTTG_Instance instance,
1111                  /*in*/ TSTTG_GentityHandle entity_handle,
1112                  /*in*/ const TSTTG_TagHandle tag_handle,
1113                  /*in*/ const int tag_value ) 
1114{
1115  return TSTTG_setArrData(instance, &entity_handle, 1, 
1116                          tag_handle, 
1117                          reinterpret_cast<const char*>(&tag_value), 
1118                          sizeof(int));
1119}
1120
1121TSTTB_ErrorType
1122TSTTG_setDblData (TSTTG_Instance instance,
1123                   
1124                  /*in*/ TSTTG_GentityHandle entity_handle,
1125                  /*in*/ const TSTTG_TagHandle tag_handle,
1126                  /*in*/ const double tag_value ) 
1127{
1128  return TSTTG_setArrData(instance, &entity_handle, 1, 
1129                          tag_handle, 
1130                          reinterpret_cast<const char*>(&tag_value), 
1131                          sizeof(double));
1132}
1133
1134TSTTB_ErrorType
1135TSTTG_setEHData (TSTTG_Instance instance,
1136                 /*in*/ TSTTG_GentityHandle entity_handle,
1137                 /*in*/ const TSTTG_TagHandle tag_handle,
1138                 /*in*/ TSTTG_CGentityHandle tag_value ) 
1139{
1140  return TSTTG_setArrData(instance, &entity_handle, 1, 
1141                          tag_handle, reinterpret_cast<const char*>(&tag_value), 
1142                          sizeof(TSTTG_GentityHandle));
1143}
1144
1145/**
1146 *   Remove the tag associated with the tag_handle from the mesh or
1147 *   gentity_set.  The tag data is not destroyed in this function, but
1148 *   can be destroyed using the deleteTag function.
1149 */
1150enum TSTTB_ErrorType
1151TSTTG_rmvEntSetTag (TSTTG_Instance instance,
1152                    /*in*/ TSTTG_GentitySetHandle entity_set,
1153                    /*in*/ const TSTTG_TagHandle tag_handle)
1154{
1155    // have to go through RefEntity* so that RefEntity** gets set right
1156  RefEntity *tmp_entity = SET_HANDLE(entity_set);
1157  TM->rmvArrTag(&tmp_entity, 1, CONST_TAG_HANDLE(tag_handle));
1158  RETURN(TSTTB_SUCCESS);
1159}
1160
1161/**
1162 *   Get all tag handles associated with a given mesh or gentity_set.
1163 */
1164enum TSTTB_ErrorType
1165TSTTG_getAllEntSetTags (TSTTG_Instance instance,
1166                        /*in*/ TSTTG_CGentitySetHandle entity_set,
1167                        /*inout*/ ARRAY_INOUT_DECL(TSTTG_TagHandle, tag_handles))
1168{
1169    // have to go through RefEntity* so that RefEntity** gets set right
1170  const RefEntity *tmp_entity = CONST_SET_HANDLE(entity_set);
1171  TM->getAllTags(tmp_entity,TAG_HANDLE_ARRAY_INOUT(tag_handles));
1172  RETURN(TSTTB_SUCCESS);
1173}
1174
1175/**
1176 *   Get the tag data associated with a tag handle from the mesh or
1177 *   gentity_set.  It is assumed that the tag_value argument is
1178 *   allocated by the application before being passed into the getTag
1179 *   function.
1180 */
1181enum TSTTB_ErrorType
1182TSTTG_getEntSetData (TSTTG_Instance instance,
1183                     /*in*/ TSTTG_CGentitySetHandle entity_set,
1184                     /*in*/ const TSTTG_TagHandle tag_handle,
1185                     /*inout*/ ARRAY_INOUT_DECL(char, tag_value))
1186{
1187    // have to go through RefEntity* so that RefEntity** gets set right
1188  const RefEntity *tmp_entity = CONST_SET_HANDLE(entity_set);
1189  TM->getArrData(&tmp_entity, 1, CONST_TAG_HANDLE(tag_handle), 
1190                 ARRAY_INOUT(tag_value));
1191  RETURN(TSTTB_SUCCESS);
1192}
1193
1194int
1195TSTTG_getEntSetIntData (TSTTG_Instance instance,
1196                        /*in*/ TSTTG_CGentityHandle entity_set,
1197                        /*in*/ const TSTTG_TagHandle tag_handle ) 
1198{
1199  int tag_value;
1200  char *tag_ptr = reinterpret_cast<char*>(&tag_value);
1201  int tag_size = 4;
1202  TSTTG_getEntSetData(instance, entity_set, tag_handle, &tag_ptr, 
1203                      &tag_size, &tag_size);
1204  return tag_value;
1205}
1206
1207double
1208TSTTG_getEntSetDblData (TSTTG_Instance instance,
1209                        /*in*/ TSTTG_CGentityHandle entity_set,
1210                        /*in*/ const TSTTG_TagHandle tag_handle ) 
1211{
1212  double tag_value;
1213  char *tag_ptr = reinterpret_cast<char*>(&tag_value);
1214  int tag_size = 8;
1215  TSTTG_getEntSetData(instance, entity_set, tag_handle, &tag_ptr, 
1216                      &tag_size, &tag_size);
1217  return tag_value;
1218}
1219
1220TSTTG_GentityHandle
1221TSTTG_getEntSetEHData (TSTTG_Instance instance,
1222                       /*in*/ TSTTG_CGentityHandle entity_set,
1223                       /*in*/ const TSTTG_TagHandle tag_handle ) 
1224{
1225  TSTTG_GentityHandle tag_value;
1226  char* tag_ptr = reinterpret_cast<char*>(&tag_value);
1227  int tag_size;
1228  TSTTG_getEntSetData(instance, entity_set, tag_handle, &tag_ptr, 
1229                      &tag_size, &tag_size);
1230  return tag_value;
1231}
1232
1233/**
1234 *   Set the tag data associated with a given tag handle on the mesh or
1235 *   gentity_set
1236 */
1237enum TSTTB_ErrorType
1238TSTTG_setEntSetData (TSTTG_Instance instance,
1239                     /*in*/ TSTTG_GentitySetHandle entity_set,
1240                     /*in*/ const TSTTG_TagHandle tag_handle,
1241                     /*in*/ CONST_ARRAY_IN_DECL(char, tag_value))
1242{
1243    // have to go through RefEntity* so that RefEntity** gets set right
1244  RefEntity *tmp_entity = SET_HANDLE(entity_set);
1245  TM->setArrData(&tmp_entity, 1, CONST_TAG_HANDLE(tag_handle), 
1246                 ARRAY_IN(tag_value));
1247  RETURN(TSTTB_SUCCESS);
1248}
1249
1250TSTTB_ErrorType
1251TSTTG_setEntSetIntData (TSTTG_Instance instance,
1252                          /*in*/ TSTTG_GentityHandle entity_set,
1253                          /*in*/ const TSTTG_TagHandle tag_handle,
1254                          /*in*/ const int tag_value ) 
1255{
1256  return TSTTG_setEntSetData(instance, entity_set, tag_handle, 
1257                             reinterpret_cast<const char*>(&tag_value), 
1258                             sizeof(int));
1259}
1260
1261TSTTB_ErrorType
1262TSTTG_setEntSetDblData (TSTTG_Instance instance,
1263                          /*in*/ TSTTG_GentityHandle entity_set,
1264                          /*in*/ const TSTTG_TagHandle tag_handle,
1265                          /*in*/ const double tag_value ) 
1266{
1267  return TSTTG_setEntSetData(instance, entity_set, tag_handle, 
1268                             reinterpret_cast<const char*>(&tag_value),
1269                             sizeof(double));
1270}
1271
1272TSTTB_ErrorType
1273TSTTG_setEntSetEHData (TSTTG_Instance instance,
1274                         /*in*/ TSTTG_GentitySetHandle entity_set,
1275                         /*in*/ const TSTTG_TagHandle tag_handle,
1276                         /*in*/ TSTTG_CGentityHandle tag_value ) 
1277{
1278  return TSTTG_setEntSetData(instance, entity_set, tag_handle, 
1279                             reinterpret_cast<const char*>(&tag_value), 
1280                             sizeof(TSTTG_GentityHandle));
1281}
1282
1283/**
1284 * Return a points on specified entities closest to specified points
1285 * in space.  Input coordinates and output points are interleaved in
1286 * the arrays.
1287 * @param gentity_handles The gentities being queried
1288 * @param near_coordinates Input coordinates
1289 * @param on_coordinates Closest point on gentity
1290 */
1291enum TSTTB_ErrorType
1292TSTTG_gentityClosestPoint (TSTTG_Instance instance,
1293                           /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, gentity_handles),
1294                           /*in*/ CONST_ARRAY_IN_DECL(double, near_coordinates),
1295                           /*out*/ ARRAY_INOUT_DECL(double, on_coordinates))
1296{
1297  const RefEntity **handle_array = CONST_ENTITY_HANDLE_ARRAY(gentity_handles);
1298
1299    // check or pre-allocate the coordinate arrays
1300  CHECK_SIZE(*on_coordinates, double, 3*gentity_handles_size);
1301 
1302  CubitVector dumvec;
1303  const RefEdge *this_edge;
1304  const RefFace *this_face;
1305  Surface *this_surf;
1306  CubitStatus status = CUBIT_SUCCESS, temp_status;
1307
1308  const double *near_vec = near_coordinates;
1309  double *on_vec = *on_coordinates;
1310
1311  for (int i = 0; i < gentity_handles_size; i++) {
1312    const RefEntity *this_entity = handle_array[i];
1313 
1314    switch (this_entity->dimension()) {
1315      case 0:
1316        dynamic_cast<const RefVertex*>(this_entity)->coordinates().get_xyz(&on_vec[3*i]);
1317        break;
1318      case 1:
1319        this_edge = dynamic_cast<const RefEdge*>(this_entity);
1320        if (NULL == this_edge) status = CUBIT_FAILURE;
1321        else {
1322          if (debug) {
1323            std::cout << "Edge " << this_edge->id() << " closest point to (" 
1324                      << near_vec[3*i] << ", " << near_vec[3*i+1] << ", " << near_vec[3*i+2] 
1325                      << ") is ";
1326          }
1327       
1328          temp_status = 
1329            const_cast<RefEdge*>(this_edge)->closest_point(CubitVector(&near_vec[3*i]), dumvec);
1330          if (temp_status != CUBIT_SUCCESS) status = temp_status;
1331          else dumvec.get_xyz(&on_vec[3*i]);
1332        }
1333        if (debug) {
1334          std::cout << on_vec[3*i] << ", " << on_vec[3*i+1] << ", " << on_vec[3*i+2] 
1335                    << ")" << std::endl;
1336        }
1337        break;
1338      case 2:
1339        this_face = dynamic_cast<const RefFace*>(this_entity);
1340        if (NULL != this_face) this_surf = const_cast<RefFace*>(this_face)->get_surface_ptr();
1341     
1342        if (NULL == this_face) status = CUBIT_FAILURE;
1343        else {
1344          temp_status = 
1345            this_surf->closest_point(CubitVector(&near_vec[3*i]), &dumvec);
1346          if (temp_status != CUBIT_SUCCESS) status = temp_status;
1347          else dumvec.get_xyz(&on_vec[3*i]);
1348        }
1349        break;
1350      case 3:
1351          // just copy over the coordinates
1352        on_vec[3*i] = near_vec[3*i];
1353        on_vec[3*i+1] = near_vec[3*i+1];
1354        on_vec[3*i+2] = near_vec[3*i+2];
1355        break;
1356    }
1357  }
1358 
1359  if (status == CUBIT_FAILURE) {
1360    TSTTG_processError(TSTTB_FAILURE, "Problems getting closest point for some entity.");
1361    RETURN(TSTTB_FAILURE);
1362  }
1363
1364  RETURN(TSTTB_SUCCESS);
1365}
1366
1367/**
1368 * Return a points on specified entities closest to specified points
1369 * in space, and normals at that point.  Input coordinates and output points are
1370 * interleaved in
1371 * the arrays.
1372 * @param gentity_handles The gentities being queried
1373 * @param near_coordinates Input coordinates
1374 * @param on_coordinates Closest point on gentity
1375 */
1376enum TSTTB_ErrorType
1377TSTTG_gentityClosestPointAndNormal (TSTTG_Instance instance,
1378                                    /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, gentity_handles),
1379                                    /*in*/ CONST_ARRAY_IN_DECL(double, near_coordinates),
1380                                    /*out*/ ARRAY_INOUT_DECL(double, on_coordinates),
1381                                    /*out*/ ARRAY_INOUT_DECL(double, normals))
1382{
1383  const RefEntity **handle_array = CONST_ENTITY_HANDLE_ARRAY(gentity_handles);
1384
1385    // check or pre-allocate the coordinate arrays
1386  CHECK_SIZE(*on_coordinates, double, 3*gentity_handles_size);
1387  CHECK_SIZE(*normals, double, 3*gentity_handles_size);
1388 
1389  CubitVector dumvec, dumnormal;
1390  const RefEdge *this_edge;
1391  const RefFace *this_face;
1392  Surface *this_surf;
1393  CubitStatus status = CUBIT_SUCCESS, temp_status;
1394
1395  const double *near_vec = near_coordinates;
1396  double *on_vec = *on_coordinates;
1397  double *normals_vec = *normals;
1398
1399  for (int i = 0; i < gentity_handles_size; i++) {
1400    const RefEntity *this_entity = handle_array[i];
1401 
1402    switch (this_entity->dimension()) {
1403      case 0:
1404        dynamic_cast<const RefVertex*>(this_entity)->coordinates().get_xyz(&on_vec[3*i]);
1405        normals_vec[3*i] = normals_vec[3*i+1] = normals_vec[3*i+2] = 0.0;
1406        break;
1407      case 1:
1408        this_edge = dynamic_cast<const RefEdge*>(this_entity);
1409        if (NULL == this_edge) status = CUBIT_FAILURE;
1410        else {
1411          if (debug) {
1412            std::cout << "Edge " << this_edge->id() << " closest point to (" 
1413                      << near_vec[3*i] << ", " << near_vec[3*i+1] << ", " << near_vec[3*i+2] 
1414                      << ") is ";
1415          }
1416       
1417          temp_status = 
1418            const_cast<RefEdge*>(this_edge)->closest_point(CubitVector(&near_vec[3*i]), dumvec);
1419          if (temp_status != CUBIT_SUCCESS) status = temp_status;
1420          else dumvec.get_xyz(&on_vec[3*i]);
1421          normals_vec[3*i] = normals_vec[3*i+1] = normals_vec[3*i+2] = 0.0;
1422        }
1423        if (debug) {
1424          std::cout << on_vec[3*i] << ", " << on_vec[3*i+1] << ", " << on_vec[3*i+2] 
1425                    << ")" << std::endl;
1426        }
1427        break;
1428      case 2:
1429        this_face = dynamic_cast<const RefFace*>(this_entity);
1430     
1431        if (NULL == this_face) 
1432          status = CUBIT_FAILURE;
1433        else {
1434          this_surf = const_cast<RefFace*>(this_face)->get_surface_ptr();
1435          temp_status = 
1436            this_surf->closest_point(CubitVector(&near_vec[3*i]), &dumvec, &dumnormal);
1437          if (temp_status != CUBIT_SUCCESS) 
1438            status = temp_status;
1439          else {
1440            if (this_surf->bridge_sense() == CUBIT_REVERSED)
1441              dumnormal = -dumnormal;
1442            dumvec.get_xyz(&on_vec[3*i]);
1443            dumnormal.get_xyz(&normals_vec[3*i]);
1444          }
1445        }
1446        break;
1447      case 3:
1448          // just copy over the coordinates
1449        on_vec[3*i] = near_vec[3*i];
1450        on_vec[3*i+1] = near_vec[3*i+1];
1451        on_vec[3*i+2] = near_vec[3*i+2];
1452        normals_vec[3*i] = normals_vec[3*i+1] = normals_vec[3*i+2] = 0.0;
1453        break;
1454    }
1455  }
1456 
1457  if (status == CUBIT_FAILURE) {
1458    TSTTG_processError(TSTTB_FAILURE, "Problems getting closest point for some entity.");
1459    RETURN(TSTTB_FAILURE);
1460  }
1461
1462  RETURN(TSTTB_SUCCESS);
1463}
1464
1465/**
1466 * Return the normals at point on specified entities.  Returns error
1467 * if any input entity is not a gface.  Input coordinates and normals
1468 * are interleaved in the arrays.
1469 * @param gentity_handles The gentities being queried
1470 * @param coordinates Input coordinates, interleaved
1471 * @param normals The normals at the specified points, interleaved
1472 */
1473enum TSTTB_ErrorType
1474TSTTG_gentityNormal (TSTTG_Instance instance,
1475                     /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, gentity_handles),
1476                     /*in*/ CONST_ARRAY_IN_DECL(double, coordinates),
1477                     /*out*/ ARRAY_INOUT_DECL(double, normals))
1478{
1479  const RefEntity **handle_array = CONST_ENTITY_HANDLE_ARRAY(gentity_handles);
1480
1481    // check or pre-allocate the coordinate arrays
1482  CHECK_SIZE(*normals, double, 3*gentity_handles_size);
1483 
1484  CubitVector dumvec;
1485  const RefFace *this_face;
1486
1487  const double *coord_vec = coordinates;
1488  double *normal_vec = *normals;
1489
1490  for (int i = 0; i < gentity_handles_size; i++) {
1491    this_face = dynamic_cast<const RefFace*>(handle_array[i]);
1492    if (NULL == this_face) {
1493      TSTTG_processError(TSTTB_INVALID_ENTITY_TYPE, "Entities passed into gentityNormal must be faces.");
1494      continue;
1495    }
1496    else {
1497      dumvec = const_cast<RefFace*>(this_face)->normal_at(CubitVector(&coord_vec[3*i]));
1498      dumvec.get_xyz(&normal_vec[3*i]);
1499    }
1500  }
1501
1502  RETURN(TSTTB_SUCCESS);
1503}
1504
1505/**
1506 * Return the tangent at point on specified entities.  Returns error
1507 * if any input entity is not a gedge.  Input coordinates and tangents
1508 * are interleaved in the arrays.
1509 * @param gentity_handles The gentities being queried
1510 * @param coordinates Input coordinates, interleaved
1511 * @param tangents The tangents at the specified points, interleaved
1512 */
1513enum TSTTB_ErrorType
1514TSTTG_gentityTangent (TSTTG_Instance instance,
1515                      /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, gentity_handles),
1516                      /*in*/ CONST_ARRAY_IN_DECL(double, coordinates),
1517                      /*out*/ ARRAY_INOUT_DECL(double, tangents))
1518{
1519  const RefEntity **handle_array = CONST_ENTITY_HANDLE_ARRAY(gentity_handles);
1520
1521    // check or pre-allocate the coordinate arrays
1522  CHECK_SIZE(*tangents, double, 3*gentity_handles_size);
1523 
1524  CubitVector dumvec;
1525  const RefEdge *this_edge;
1526
1527  const double *coord_vec = coordinates;
1528  double *tangent_vec = *tangents;
1529
1530  for (int i = 0; i < gentity_handles_size; i++) {
1531    this_edge = dynamic_cast<const RefEdge*>(handle_array[i]);
1532    if (NULL == this_edge) {
1533      TSTTG_processError(TSTTB_INVALID_ENTITY_TYPE, "Entities passed into gentityTangent must be edges.");
1534      continue;
1535    }
1536    else {
1537      const_cast<RefEdge*>(this_edge)->tangent(CubitVector(&coord_vec[3*i]), dumvec);
1538      dumvec.get_xyz(&tangent_vec[3*i]);
1539    }
1540  }
1541
1542  RETURN(TSTTB_SUCCESS);
1543}
1544
1545/**
1546 * Return the bounding boxex of given entities; coordinates returned
1547 * interleaved.
1548 * @param gentity_handles The gentities being queried
1549 * @param min_corners Minimum corner coordinates of the boxes, interleaved
1550 * @param max_corners Maximum corner coordinates of the boxes, interleaved
1551 */
1552enum TSTTB_ErrorType
1553TSTTG_gentityBoundingBox (TSTTG_Instance instance,
1554                          /*in*/ ARRAY_IN_DECL(TSTTG_GentityHandle, gentity_handles),
1555                          /*out*/ ARRAY_INOUT_DECL(double, min_corner),
1556                          /*out*/ ARRAY_INOUT_DECL(double, max_corner))
1557{
1558  CubitBox temp_box;
1559  RefEntity **handle_array = ENTITY_HANDLE_ARRAY(gentity_handles);
1560
1561    // check or pre-allocate the coordinate arrays
1562  CHECK_SIZE(*min_corner, double, 3*gentity_handles_size);
1563  CHECK_SIZE(*max_corner, double, 3*gentity_handles_size);
1564 
1565  double *min_vec = *min_corner;
1566  double *max_vec = *max_corner;
1567
1568  for (int i = 0; i < gentity_handles_size; i++) {
1569    BasicTopologyEntity *this_bte = dynamic_cast<BasicTopologyEntity*>(handle_array[i]);
1570    if (NULL != this_bte)
1571      temp_box = this_bte->bounding_box();
1572    else {
1573      Body *this_body = dynamic_cast<Body*>(handle_array[i]);
1574      if (NULL != this_body)
1575        temp_box = this_body->bounding_box();
1576      else {
1577        TSTTG_processError(TSTTB_INVALID_ENTITY_TYPE, "Entities passed into gentityBoundingBox must be vertex, edge, face, or region.");
1578        continue;
1579      }
1580    }
1581
1582    temp_box.minimum().get_xyz(&min_vec[3*i]);
1583    temp_box.maximum().get_xyz(&max_vec[3*i]);
1584  }
1585
1586  RETURN(TSTTB_SUCCESS);
1587}
1588
1589/**
1590 * Return the coordinates of the specified vertices; returns error if any
1591 * of the entities are not gvertices.  Coordinates returned interleaved.
1592 * @param gentity_handles The gentities being queried
1593 * @param coordinates The coordinates of the gvertices, interleaved.
1594 */
1595enum TSTTB_ErrorType
1596TSTTG_getGvertexCoordinates (TSTTG_Instance instance,
1597                             /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, gentity_handles),
1598                             /*out*/ ARRAY_INOUT_DECL(double, coordinates))
1599{
1600  const RefEntity **handle_array = CONST_ENTITY_HANDLE_ARRAY(gentity_handles);
1601
1602    // check or pre-allocate the coordinate arrays
1603  CHECK_SIZE(*coordinates, double, 3*gentity_handles_size);
1604 
1605  CubitVector dumvec;
1606  const RefVertex *this_vertex;
1607
1608  double *coord_vec = *coordinates;
1609
1610  for (int i = 0; i < gentity_handles_size; i++) {
1611    this_vertex = dynamic_cast<const RefVertex*>(handle_array[i]);
1612    if (NULL == this_vertex) {
1613      TSTTG_processError(TSTTB_INVALID_ENTITY_TYPE, "Entities passed into getGvertexCoordinates must be vertices.");
1614      continue;
1615    }
1616    else {
1617      dumvec = this_vertex->coordinates();
1618      dumvec.get_xyz(&coord_vec[3*i]);
1619    }
1620  }
1621
1622  RETURN(TSTTB_SUCCESS);
1623}
1624
1625/**
1626 * Return the sense of a gface with respect to a gregion.  Sense is either
1627 * forward (=1), reverse (=-1), both (=2), or unknown (=0).  Error is returned
1628 * if first entity is not a gface or second entity is not a gregion.
1629 * @param gface Gface whose sense is being queried.
1630 * @param gregion Gregion gface is being queried with respect to
1631 */
1632int
1633TSTTG_getGnormalSense (TSTTG_Instance instance,
1634                       /*in*/ TSTTG_CGentityHandle gface,
1635                       /*in*/ TSTTG_CGentityHandle gregion)
1636{
1637  const RefFace *face_ent = dynamic_cast<const RefFace*>(CONST_ENTITY_HANDLE(gface));
1638  if (NULL == face_ent) {
1639    TSTTG_processError(TSTTB_INVALID_ENTITY_TYPE, "1st argument to getGnormalSense must be a face.");
1640    return 0;
1641  }
1642  const RefVolume *volume_ent = dynamic_cast<const RefVolume*>(CONST_ENTITY_HANDLE(gregion));
1643  if (NULL == face_ent) {
1644    TSTTG_processError(TSTTB_INVALID_ENTITY_TYPE, "2nd argument to getGnormalSense must be a region.");
1645    return 0;
1646  }
1647  CubitSense this_sense = const_cast<RefFace*>(face_ent)->sense(const_cast<RefVolume*>(volume_ent));
1648  int tstt_sense = 0;
1649  if (CUBIT_FORWARD == this_sense) tstt_sense = 1;
1650  else if (CUBIT_REVERSED == this_sense) tstt_sense = -1;
1651 
1652  return tstt_sense;
1653}
1654
1655/**
1656 * Return the sense of a gedge with respect to a gface.  Sense is either
1657 * forward (=1), reverse (=-1), both (=2), or unknown (=0).  Error is returned
1658 * if first entity is not a gedge or second entity is not a gface.
1659 * @param gedge Gedge whose sense is being queried.
1660 * @param gface Gface gedge is being queried with respect to
1661 */
1662int
1663TSTTG_getGtangentSense (TSTTG_Instance instance,
1664                        /*in*/ TSTTG_CGentityHandle gedge,
1665                        /*in*/ TSTTG_CGentityHandle gface)
1666{
1667  const RefEdge *edge_ent = dynamic_cast<const RefEdge*>(CONST_ENTITY_HANDLE(gedge));
1668  if (NULL == edge_ent) {
1669    TSTTG_processError(TSTTB_INVALID_ENTITY_TYPE, "1st argument to getGtangentSense must be an edge.");
1670    return 0;
1671  }
1672  const RefFace *face_ent = dynamic_cast<const RefFace*>(CONST_ENTITY_HANDLE(gface));
1673  if (NULL == face_ent) {
1674    TSTTG_processError(TSTTB_INVALID_ENTITY_TYPE, "2nd argument to getGtangentSense must be a face.");
1675    return 0;
1676  }
1677  CubitSense this_sense = const_cast<RefEdge*>(edge_ent)->sense(const_cast<RefFace*>(face_ent));
1678  int tstt_sense = 0;
1679  if (CUBIT_FORWARD == this_sense) tstt_sense = 1;
1680  else if (CUBIT_REVERSED == this_sense) tstt_sense = -1;
1681 
1682  return tstt_sense;
1683}
1684
1685/**
1686 * Return the sense of a gedge with respect to a specified order of
1687 * vertices bounding the gedge.  Sense is either forward (=1), reverse (=-1),
1688 * or unknown (=0).  Error is returned if any gentities are not the expected
1689 * type or if the gedge is bounded by only one gvertex (in this case, use
1690 * getGtangentSense).
1691 * @param gedge Gedge whose sense is being queried.
1692 * @param gvertex1 First gvertex
1693 * @param gvertex2 Second gvertex
1694 */
1695int
1696TSTTG_getGvertexTangentSense (TSTTG_Instance instance,
1697                              /*in*/ TSTTG_CGentityHandle gedge,
1698                              /*in*/ TSTTG_CGentityHandle gvertex1,
1699                              /*in*/ TSTTG_CGentityHandle gvertex2)
1700{
1701  const RefEdge *this_edge = dynamic_cast<const RefEdge*>(CONST_ENTITY_HANDLE(gedge));
1702  const RefVertex *vertex1 = dynamic_cast<const RefVertex*>(CONST_ENTITY_HANDLE(gvertex1));
1703  const RefVertex *vertex2 = dynamic_cast<const RefVertex*>(CONST_ENTITY_HANDLE(gvertex2));
1704  if (NULL == this_edge || NULL == vertex1 || NULL == vertex2) {
1705    TSTTG_processError(TSTTB_INVALID_ENTITY_TYPE, "Bad entity argument to getGvertexTangentSense.");
1706    return 0;
1707  }
1708  else if (const_cast<RefEdge*>(this_edge)->start_vertex() == vertex1 &&
1709           const_cast<RefEdge*>(this_edge)->end_vertex() == vertex2)
1710      // forward sense
1711    return 1;
1712  else if (const_cast<RefEdge*>(this_edge)->start_vertex() == vertex2 &&
1713           const_cast<RefEdge*>(this_edge)->end_vertex() == vertex1)
1714    return -1;
1715  else
1716    return 0;
1717}
1718
1719/**
1720 * Returns the number of gentity_sets contained in a given model or
1721 * gentity_set one level deep
1722 * @param gentity_set_handle Gentity set being queried
1723 * @return Number of entity sets in gentity_set_handle
1724 */
1725int
1726TSTTG_getNumEntSets (TSTTG_Instance instance,
1727                     /*in*/ TSTTG_CGentitySetHandle entity_set,
1728                     /*in*/ int num_hops)
1729{
1730    // HJK: num_hops has to be handled
1731  if (1 < num_hops) {
1732    TSTTG_processError(TSTTB_NOT_SUPPORTED, "Num_hops argument not yet supported.");
1733    return -1;
1734  }
1735 
1736  const RefGroup *this_set = CONST_SET_HANDLE(entity_set);
1737  if (NULL == this_set)
1738    return RefEntityFactory::instance()->num_ref_groups();
1739  else {
1740    DLIList<RefEntity*> tmp_ents;
1741    DLIList<RefGroup*> groups;
1742    const_cast<RefGroup*>(this_set)->get_child_ref_entities(tmp_ents);
1743    CAST_LIST(tmp_ents, groups, RefGroup);
1744    return groups.size();
1745  }
1746
1747  return -1;
1748}
1749
1750/**
1751 * Returns the gentity_set handles contained in a given model or
1752 * gentity_set one level deep
1753 * @param gentity_set_handle Gentity set being queried
1754 * @param contained_gentity_set_handles Number of entity sets in
1755 *  gentity_set_handle
1756 */
1757enum TSTTB_ErrorType
1758TSTTG_getEntSets (TSTTG_Instance instance,
1759                  /*in*/ TSTTG_CGentitySetHandle entity_set,
1760                  /*in*/ const int num_hops,
1761                  /*inout*/ ARRAY_INOUT_DECL(TSTTG_GentitySetHandle, 
1762                                             contained_entity_set_handles))
1763{
1764  if (1 < num_hops) {
1765    TSTTG_processError(TSTTB_NOT_SUPPORTED, "Num_hops argument not yet supported.");
1766    RETURN(TSTTB_NOT_SUPPORTED);
1767  }
1768
1769  const RefGroup *this_set = CONST_SET_HANDLE(entity_set);
1770  DLIList<RefEntity*> tmp_ents;
1771  DLIList<RefGroup*> groups;
1772  if (NULL == this_set)
1773    RefEntityFactory::instance()->ref_groups(groups);
1774  else {
1775    const_cast<RefGroup*>(this_set)->get_child_ref_entities(tmp_ents);
1776    CAST_LIST(tmp_ents, groups, RefGroup);
1777  }
1778 
1779  CHECK_SIZE(*contained_entity_set_handles, TSTTG_GentitySetHandle, groups.size());
1780
1781  groups.copy_to(*SET_HANDLE_ARRAY_PTR(contained_entity_set_handles));
1782 
1783  RETURN(TSTTB_SUCCESS);
1784}
1785
1786/**
1787 * This function allows a new gentity_set to be created.  The user may
1788 * set the multiset, ordered, isMesh, flags as needed; otherwise default values
1789 * (all false) will be used.  On creation, Gentitysets are empty of
1790 * entities and contained in the parent geometry interface.  They must be
1791 * explicitly filled with entities using the addGentities call and
1792 * relationships with other Gentitysets must be done through the
1793 * addGentityset and parent/child relationship calls.
1794 * @param multiset If true, gentities can appear more than once in this gentity_set
1795 * @param ordered If true, order of addition and removal is maintained for
1796 *   this gentity_set
1797 * @param gentity_set_created Gentity_set created by this function
1798 */
1799enum TSTTB_ErrorType
1800TSTTG_createEntSet (TSTTG_Instance instance,
1801                    /*in*/ bool isList,
1802                    /*out*/ TSTTG_GentitySetHandle *entity_set)
1803{
1804  *entity_set = RefEntityFactory::instance()->construct_RefGroup();
1805    // need to set a tag denoting multiset or not...
1806  RETURN(TSTTB_SUCCESS);
1807}
1808
1809/**
1810 *   Destroy the gentity set.  This method only destroys the grouping of
1811 *   gentities, not the gentities themselves.
1812 * @param gentity_set Gentity_set to be destroyed
1813 */
1814enum TSTTB_ErrorType
1815TSTTG_destroyEntSet (TSTTG_Instance instance,
1816                     /*in*/ TSTTG_GentitySetHandle entity_set)
1817{
1818  if (NULL == entity_set) {
1819    TSTTG_processError(TSTTB_INVALID_ARGUMENT, "Can't destroy interface set.");
1820  }
1821     
1822  RefGroup::delete_group(SET_HANDLE(entity_set));
1823  RETURN(TSTTB_SUCCESS);
1824}
1825
1826bool
1827TSTTG_isList (TSTTG_Instance instance,
1828                /*in*/ TSTTG_CGentitySetHandle entity_set) 
1829{
1830  return true;
1831}
1832
1833/**
1834 *   Allows the user to explicitly add one or more gentity_sets to
1835 *   another.  This automatically sets the contained in relationship,
1836 *   but not the parent/child relationships.  All gentity_set handles
1837 *   are automatically contained in the parent mesh interface, so
1838 *   passing in NULL as the first argument results in no action.
1839 * @param gentity_set Set to which other sets are being added
1840 * @param gentity_set_handles Sets added to gentity_set
1841 */
1842enum TSTTB_ErrorType
1843TSTTG_addEntSet (TSTTG_Instance instance,
1844                 /*in*/ TSTTG_CGentitySetHandle entity_set_to_add,
1845                 /*inout*/ TSTTG_GentitySetHandle *entity_set_handle)
1846{
1847  const RefEntity *tmp_ent = CONST_SET_HANDLE(entity_set_to_add);
1848  return TSTTG_addEntToSet(instance, tmp_ent, entity_set_handle);
1849}
1850
1851/**
1852 *   Allows the user to remove one or more gentity_sets from another
1853 *   gentity_set.  Users cannot delete a contained in relationship of an
1854 *   gentity set with the parent mesh interface so passing in a NULL
1855 *   value for the first argument results in no action.
1856 * @param gentity_set Set from which other sets are being removed
1857 * @param gentity_set_handles Sets being removed from gentity_set
1858 */
1859enum TSTTB_ErrorType
1860TSTTG_rmvEntSet (TSTTG_Instance instance,
1861                 /*in*/ TSTTG_CGentitySetHandle entity_set_to_remove,
1862                 /*inout*/ TSTTG_GentitySetHandle *entity_set_handle)
1863{
1864  const RefEntity *tmp_ent = CONST_SET_HANDLE(entity_set_to_remove);
1865  return TSTTG_rmvEntFromSet(instance, tmp_ent, entity_set_handle);
1866}
1867
1868/**
1869 *   Allows the user to explicitly add one or more gentity_sets to
1870 *   another.  This automatically sets the contained in relationship,
1871 *   but not the parent/child relationships.  All gentity_set handles
1872 *   are automatically contained in the parent mesh interface, so
1873 *   passing in NULL as the first argument results in no action.
1874 * @param gentity_set Set to which other sets are being added
1875 * @param gentity_set_handles Sets added to gentity_set
1876 */
1877enum TSTTB_ErrorType
1878TSTTG_addEntToSet (TSTTG_Instance instance,
1879                 /*in*/ TSTTG_CGentityHandle entity_to_add,
1880                 /*inout*/ TSTTG_GentitySetHandle *entity_set_handle)
1881{
1882  if (NULL == entity_to_add) RETURN(TSTTB_INVALID_ARGUMENT);
1883 
1884  CubitStatus status = SET_HANDLE(*entity_set_handle)->
1885    add_ref_entity(const_cast<RefEntity*>(CONST_ENTITY_HANDLE(entity_to_add)));
1886 
1887  if (CUBIT_SUCCESS != status)
1888    TSTTG_processError(TSTTB_FAILURE, "Problem adding entity to another set.");
1889
1890  RETURN(TSTTB_SUCCESS);
1891}
1892
1893/**
1894 *   Allows the user to remove one or more gentity_sets from another
1895 *   gentity_set.  Users cannot delete a contained in relationship of an
1896 *   gentity set with the parent mesh interface so passing in a NULL
1897 *   value for the first argument results in no action.
1898 * @param gentity_set Set from which other sets are being removed
1899 * @param gentity_set_handles Sets being removed from gentity_set
1900 */
1901enum TSTTB_ErrorType
1902TSTTG_rmvEntFromSet (TSTTG_Instance instance,
1903                     /*in*/ TSTTG_CGentityHandle entity_to_remove,
1904                     /*inout*/ TSTTG_GentitySetHandle *entity_set_handle)
1905{
1906  if (NULL == *entity_set_handle) RETURN(TSTTB_INVALID_ARGUMENT);
1907 
1908  CubitStatus status = SET_HANDLE(*entity_set_handle)->
1909    remove_ref_entity(const_cast<RefEntity*>(CONST_ENTITY_HANDLE(entity_to_remove)));
1910  if (CUBIT_SUCCESS != status) {
1911    TSTTG_processError(TSTTB_FAILURE, "Problem removing entity from a set.");
1912    RETURN(TSTTB_FAILURE);
1913  }
1914 
1915  RETURN(TSTTB_SUCCESS);
1916}
1917
1918bool
1919TSTTG_isEntContained (TSTTG_Instance instance,
1920                      /*in*/ TSTTG_CGentitySetHandle containing_entity_set,
1921                      /*in*/ TSTTG_CGentityHandle contained_entity) 
1922{
1923  if (NULL == containing_entity_set && NULL != contained_entity) return true;
1924
1925  DLIList<RefGroup*> containing_groups;
1926  RefEntity *contained_entity_temp = const_cast<RefEntity*>(CONST_ENTITY_HANDLE(contained_entity));
1927  RefGroup::get_groups_within(contained_entity_temp, containing_groups, CUBIT_FALSE);
1928  if (containing_groups.size() > 0 &&
1929      containing_groups.move_to(const_cast<RefGroup*>(CONST_SET_HANDLE(containing_entity_set)))) return true;
1930 
1931  return false;
1932 
1933  RETURN(TSTTB_SUCCESS);
1934}
1935
1936bool
1937TSTTG_isEntSetContained (TSTTG_Instance instance,
1938                         /*in*/ TSTTG_CGentitySetHandle containing_entity_set,
1939                         /*in*/ TSTTG_CGentitySetHandle contained_entity_set) 
1940{
1941  if (NULL == containing_entity_set && NULL != contained_entity_set) return true;
1942
1943  DLIList<RefGroup*> containing_groups;
1944  RefGroup *contained_set = const_cast<RefGroup*>(CONST_SET_HANDLE(contained_entity_set));
1945  RefGroup::get_groups_within(const_cast<RefGroup*>(contained_set), containing_groups, 
1946                              CUBIT_FALSE);
1947  if (containing_groups.size() > 0 &&
1948      containing_groups.move_to(const_cast<RefGroup*>(CONST_SET_HANDLE(containing_entity_set)))) return true;
1949 
1950  return false;
1951 
1952  RETURN(TSTTB_SUCCESS);
1953}
1954
1955/**
1956 *   Add existing gentities to the gentity_set (do not create them).
1957 *   Note that if a gentity of dimension d>0 is added to the gentityset,
1958 *   the lower-dimensional gentities that bound it are not
1959 *   automatically associated with the gentityset.
1960 * @param gentity_set Set being added to
1961 * @param gentity_handles Gentities being added to gentity_set
1962 */
1963enum TSTTB_ErrorType
1964TSTTG_addEntArrToSet (TSTTG_Instance instance,
1965                      /*in*/ ARRAY_IN_DECL(TSTTG_GentityHandle, entity_handles),
1966                      /*inout*/ TSTTG_GentitySetHandle *entity_set)
1967{
1968  if (NULL == entity_set) RETURN(TSTTB_INVALID_ARGUMENT);
1969
1970  RefGroup *this_set = SET_HANDLE(*entity_set);
1971  RefEntity **ent_array = ENTITY_HANDLE_ARRAY(entity_handles);
1972  CubitStatus status = CUBIT_SUCCESS, tmp_status;
1973  for (int i = 0; i < entity_handles_size; i++) {
1974    tmp_status = this_set->add_ref_entity(ent_array[i]);
1975    if (CUBIT_SUCCESS != tmp_status) status = tmp_status;
1976  }
1977
1978  if (CUBIT_SUCCESS != status) {
1979    TSTTG_processError(TSTTB_FAILURE, "Problem adding entities to a set.");
1980    RETURN(TSTTB_FAILURE);
1981  }
1982 
1983  RETURN(TSTTB_SUCCESS);
1984}
1985
1986/**
1987 *   Remove existing gentities from the gentity_set (do not delete them)
1988 * @param gentity_set Set being removed from
1989 * @param gentity_handles Gentities being removed from gentity_set
1990 */
1991enum TSTTB_ErrorType
1992TSTTG_rmvEntArrFromSet (TSTTG_Instance instance,
1993                        /*in*/ ARRAY_IN_DECL(TSTTG_GentityHandle, entity_handles),
1994                        /*inout*/ TSTTG_GentitySetHandle *entity_set)
1995{
1996  if (NULL == entity_set) RETURN(TSTTB_INVALID_ARGUMENT);
1997
1998  RefGroup *this_set = SET_HANDLE(*entity_set);
1999  RefEntity **ent_array = ENTITY_HANDLE_ARRAY(entity_handles);
2000  CubitStatus status = CUBIT_SUCCESS, tmp_status;
2001  for (int i = 0; i < entity_handles_size; i++) {
2002    tmp_status = this_set->remove_ref_entity(ent_array[i]);
2003    if (CUBIT_SUCCESS != tmp_status) status = tmp_status;
2004  }
2005
2006  if (CUBIT_SUCCESS != status) {
2007    TSTTG_processError(TSTTB_FAILURE, "Problem removing entities from a set.");
2008    RETURN(TSTTB_FAILURE);
2009  }
2010 
2011  RETURN(TSTTB_SUCCESS);
2012}
2013
2014/**
2015 * Return the relative and absolute tolerances at the modeler level.  If
2016 * model does not have a modeler-wide tolerance, zero is returned for both
2017 * values.
2018 * @param relative_tolerance Relative tolerance for model as a whole
2019 * @param absolute_tolerance Absolute tolerance for model as a whole
2020 */
2021enum TSTTB_ErrorType
2022TSTTG_getGtolerance (TSTTG_Instance instance,
2023                     /*out*/ double *relative_tolerance,
2024                     /*out*/ double *absolute_tolerance)
2025{
2026  *absolute_tolerance = gqt->get_sme_resabs_tolerance();
2027  *relative_tolerance = 0.0;
2028  RETURN(TSTTB_SUCCESS);
2029}
2030
2031/**
2032 * Return the relative and absolute tolerances for specified gentities.  If
2033 * a gentity does not have a specific tolerance, zero is returned for both
2034 * values.
2035 * @param gentity_handles Gentities being queried
2036 * @param relative_tolerances Relative tolerances
2037 * @param absolute_tolerances Absolute tolerances
2038 */
2039enum TSTTB_ErrorType
2040TSTTG_getGentityTolerance (TSTTG_Instance instance,
2041                           /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, gentity_handles),
2042                           /*out*/ ARRAY_INOUT_DECL(double, relative_tolerances),
2043                           /*out*/ ARRAY_INOUT_DECL(double, absolute_tolerances))
2044{
2045  CHECK_SIZE(*relative_tolerances, double, gentity_handles_size);
2046  CHECK_SIZE(*absolute_tolerances, double, gentity_handles_size);
2047  double dum_abs_tol = gqt->get_sme_resabs_tolerance();
2048  for (int i = 0; i < gentity_handles_size; i++) {
2049    (*relative_tolerances[i]) = 0.0;
2050    (*absolute_tolerances[i]) = dum_abs_tol;
2051  }
2052  RETURN(TSTTB_SUCCESS);
2053}
2054
2055/**
2056 * Return whether a given gentity is parametric or not.  If a gentity
2057 * is not parametric, all of the following functions will return an error
2058 * when called on that entity.
2059 * @param gentity_handle Gentity being queried.
2060 */
2061int
2062TSTTG_gentityIsParametric (TSTTG_Instance instance,
2063                           /*in*/ TSTTG_CGentityHandle gentity_handle)
2064{
2065  const RefFace *this_face = dynamic_cast<const RefFace*>(CONST_ENTITY_HANDLE(gentity_handle));
2066  if (NULL != this_face)
2067    return const_cast<RefFace*>(this_face)->is_parametric();
2068
2069  const RefEdge *this_edge = dynamic_cast<const RefEdge*>(CONST_ENTITY_HANDLE(gentity_handle));
2070  if (NULL != this_edge)
2071    return true;
2072
2073    // must not be either; return false
2074  return false;
2075}
2076
2077/**
2078 * Given sets of parametric coordinates, return the corresponding real
2079 * space coordinates on the gentities.  Input and output coordinates are
2080 * interleaved.
2081 * @param gentity_handles Gentities being queried.
2082 * @param uv Input parametric coordinates
2083 * @param xyz Output real space coordinates
2084 */
2085enum TSTTB_ErrorType
2086TSTTG_gentityUvToXyz (TSTTG_Instance instance,
2087                      /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, gentity_handles),
2088                      /*in*/ CONST_ARRAY_IN_DECL(double, uv),
2089                      /*out*/ ARRAY_INOUT_DECL(double, coordinates))
2090{
2091  const RefEntity **handle_array = CONST_ENTITY_HANDLE_ARRAY(gentity_handles);
2092
2093    // check or pre-allocate the coordinate arrays
2094  CHECK_SIZE(*coordinates, double, 3*gentity_handles_size);
2095 
2096  CubitVector dumvec;
2097  CubitStatus status = CUBIT_SUCCESS, temp_status;
2098
2099  const double *uv_vec = uv;
2100  double *coord_vec = *coordinates;
2101
2102  for (int i = 0; i < gentity_handles_size; i++) {
2103    const RefEdge *this_edge = dynamic_cast<const RefEdge*>(handle_array[i]);
2104    if (NULL != this_edge) {
2105      temp_status = const_cast<RefEdge*>(this_edge)->position_from_u(uv_vec[2*i], dumvec); 
2106      if (CUBIT_SUCCESS == temp_status)
2107        dumvec.get_xyz(&coord_vec[3*i]);
2108      else status = temp_status;
2109      continue;
2110    }
2111    const RefFace *this_face = dynamic_cast<const RefFace*>(handle_array[i]);
2112    if (NULL != this_face) {
2113      dumvec = const_cast<RefFace*>(this_face)->position_from_u_v(uv_vec[2*i], uv_vec[2*i+1]);
2114      dumvec.get_xyz(&coord_vec[3*i]);
2115      continue;
2116    }
2117      // if we got here, zero out the points
2118    coord_vec[3*i] = coord_vec[3*i+1] = coord_vec[3*i+2] = 0.0;
2119    status = CUBIT_FAILURE;
2120  }
2121
2122  if (CUBIT_FAILURE == status) {
2123    TSTTG_processError(TSTTB_FAILURE, "Problem getting xyz from uv.");
2124    RETURN(TSTTB_FAILURE);
2125  }
2126 
2127  RETURN(TSTTB_SUCCESS);
2128}
2129
2130/**
2131 * Given sets of real space coordinates, return the corresponding
2132 * parametric coordinates on the gentities.  Input and output coordinates
2133 * are interleaved.
2134 * @param gentity_handles Gentities being queried.
2135 * @param xyz Input real space coordinates
2136 * @param uv Output parametric coordinates
2137 */
2138enum TSTTB_ErrorType
2139TSTTG_gentityXyzToUv (TSTTG_Instance instance,
2140                      /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, gentity_handles),
2141                      /*in*/ CONST_ARRAY_IN_DECL(double, coordinates),
2142                      /*out*/ ARRAY_INOUT_DECL(double, uv))
2143{
2144  const RefEntity **handle_array = CONST_ENTITY_HANDLE_ARRAY(gentity_handles);
2145
2146    // check or pre-allocate the coordinate arrays
2147  CHECK_SIZE(*uv, double, 2*gentity_handles_size);
2148 
2149  CubitStatus status = CUBIT_SUCCESS, temp_status;
2150
2151  double *uv_vec = *uv;
2152  const double *coord_vec = coordinates;
2153
2154  for (int i = 0; i < gentity_handles_size; i++) {
2155    const RefEdge *this_edge = dynamic_cast<const RefEdge*>(handle_array[i]);
2156    if (NULL != this_edge) {
2157      uv_vec[2*i] = const_cast<RefEdge*>(this_edge)->u_from_position(CubitVector(&coord_vec[3*i])); 
2158      continue;
2159    }
2160    const RefFace *this_face = dynamic_cast<const RefFace*>(handle_array[i]);
2161    if (NULL != this_face) {
2162      temp_status = const_cast<RefFace*>(this_face)->u_v_from_position(CubitVector(&coord_vec[3*i]),
2163                                                 uv_vec[2*i], uv_vec[2*i+1]);
2164      continue;
2165    }
2166      // if we got here, zero out the points
2167    uv_vec[2*i] = uv_vec[2*i+1] = 0.0;
2168    status = CUBIT_FAILURE;
2169  }
2170
2171  if (CUBIT_FAILURE == status) {
2172    TSTTG_processError(TSTTB_FAILURE, "Problem getting uv from xyz.");
2173    RETURN(TSTTB_FAILURE);
2174  }
2175 
2176  RETURN(TSTTB_SUCCESS);
2177}
2178
2179/**
2180 * Return the uv range of the specified gentities.  Parameters are interleaved.
2181 * @param gentity_handles Gentities being queried.
2182 * @param uv_min Minimum parameters of gentities, interleaved
2183 * @param uv_max Maximum parameters of gentities, interleaved
2184 */
2185enum TSTTB_ErrorType
2186TSTTG_gentityUvRange (TSTTG_Instance instance,
2187                      /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, gentity_handles),
2188                      /*out*/ ARRAY_INOUT_DECL(double, uv_min),
2189                      /*out*/ ARRAY_INOUT_DECL(double, uv_max))
2190{
2191  const RefEntity **handle_array = CONST_ENTITY_HANDLE_ARRAY(gentity_handles);
2192
2193    // check or pre-allocate the coordinate arrays
2194  CHECK_SIZE(*uv_min, double, 2*gentity_handles_size);
2195  CHECK_SIZE(*uv_max, double, 2*gentity_handles_size);
2196 
2197  CubitStatus status = CUBIT_SUCCESS;
2198
2199  double *uvmin_vec = *uv_min;
2200  double *uvmax_vec = *uv_max;
2201
2202  for (int i = 0; i < gentity_handles_size; i++) {
2203    const RefEdge *this_edge = dynamic_cast<const RefEdge*>(handle_array[i]);
2204    if (NULL != this_edge) {
2205      CubitBoolean result = const_cast<RefEdge*>(this_edge)->get_param_range(uvmin_vec[2*i], uvmax_vec[2*i]);
2206      if (!result) status = CUBIT_FAILURE;
2207      continue;
2208    }
2209    const RefFace *this_face = dynamic_cast<const RefFace*>(handle_array[i]);
2210    if (NULL != this_face) {
2211      CubitBoolean result = const_cast<RefFace*>(this_face)->get_param_range_U(uvmin_vec[2*i], uvmax_vec[2*i]);
2212      if (!result) status = CUBIT_FAILURE;
2213      result = const_cast<RefFace*>(this_face)->get_param_range_V(uvmin_vec[2*i+1], uvmax_vec[2*i+1]);
2214      if (!result) status = CUBIT_FAILURE;
2215      continue;
2216    }
2217      // if we got here, zero out the points
2218    uvmin_vec[2*i] = uvmin_vec[2*i+1] = uvmax_vec[2*i] = uvmax_vec[2*i+1] = 0.0;
2219    status = CUBIT_FAILURE;
2220  }
2221
2222  if (CUBIT_FAILURE == status) {
2223    TSTTG_processError(TSTTB_FAILURE, "Problem getting uv range.");
2224    RETURN(TSTTB_FAILURE);
2225  }
2226 
2227  RETURN(TSTTB_SUCCESS);
2228}
2229
2230/**
2231 * Given source gentities, parametric positions on those gentities, and
2232 * bounding gentities, return the parametric positions on the bounding
2233 * gentities.  If a source gentity is a gvertex, parametric positions for
2234 * that entry are ignored.  In cases where multiple source entities are
2235 * input, two input and output parameters per gentity is assumed, even if
2236 * input consists only of gedges or gvertices.
2237 * @param src_gentity_handles Source gentities
2238 * @param src_uv Uv positions on source gentities
2239 * @param trg_gentity_handles Target gentities
2240 * @param trg_uv Uv positions on target gentities
2241 */
2242enum TSTTB_ErrorType
2243TSTTG_Greparam_edge_face (TSTTG_Instance instance,
2244                          /*in*/ ARRAY_IN_DECL(TSTTG_GentityHandle, src_gentity_handles),
2245                          /*in*/ ARRAY_IN_DECL(double, src_uv),
2246                          /*in*/ ARRAY_IN_DECL(TSTTG_GentityHandle, trg_gentity_handles),
2247                          /*in*/ ARRAY_IN_DECL(double, trg_uv))
2248{
2249  TSTTG_processError(TSTTB_NOT_SUPPORTED, "Not implemented.");
2250  RETURN(TSTTB_NOT_SUPPORTED);
2251}
2252
2253/**
2254 * Return the normals at specified uv positions on gfaces.  If any
2255 * gentity input is not a face, returns error.  Input parameters and
2256 * output normals are interleaved.
2257 * @param gface_handles The entities being queried
2258 * @param parameters The uv parameters of points being queried, interleaved
2259 * @param normals Normals at specified points, interleaved
2260 */
2261enum TSTTB_ErrorType
2262TSTTG_gentityNormalUv (TSTTG_Instance instance,
2263                       /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, gface_handles),
2264                       /*in*/ CONST_ARRAY_IN_DECL(double, parameters),
2265                       /*out*/ ARRAY_INOUT_DECL(double, normals))
2266{
2267  enum TSTTB_ErrorType result = 
2268    TSTTG_gentityUvToXyz(instance, ARRAY_IN(gface_handles), ARRAY_IN(parameters), 
2269                         ARRAY_INOUT(normals));
2270  if (TSTTB_SUCCESS == result)
2271    result = TSTTG_gentityNormal(instance, ARRAY_IN(gface_handles), *normals, *normals_size, 
2272                           ARRAY_INOUT(normals));
2273  RETURN(result);
2274}
2275
2276/**
2277 * Return the tangents at specified u positions on gedges.  If any
2278 * gentity input is not a face, returns error.  Output normals are
2279 * interleaved.
2280 * @param gentity_handles The gedges being queried
2281 * @param parameters The u parameters of points being queried
2282 * @param tangents Tangents at specified points, interleaved
2283 */
2284enum TSTTB_ErrorType
2285TSTTG_gentityTangentU (TSTTG_Instance instance,
2286                       /*in*/ ARRAY_IN_DECL(TSTTG_CGentityHandle, gedge_handles),
2287                       /*in*/ CONST_ARRAY_IN_DECL(double, parameters),
2288                       /*out*/ ARRAY_INOUT_DECL(double, tangents))
2289{
2290  enum TSTTB_ErrorType result =
2291    TSTTG_gentityUvToXyz(instance, ARRAY_IN(gedge_handles), ARRAY_IN(parameters), 
2292                         ARRAY_INOUT(tangents));
2293  if (TSTTB_SUCCESS == result)
2294    result = TSTTG_gentityNormal(instance, ARRAY_IN(gedge_handles), *tangents, *tangents_size,
2295                                 ARRAY_INOUT(tangents));
2296  RETURN(result);
2297}
2298
2299/**
2300 *   Subtract the gentities in gentity_set_2 from the gentities in
2301 *   gentity_set_1; the result is returned in gentity_set_1.  If
2302 *   gentity_set 1 is a multiset and contains m entries of a particular
2303 *   gentity, say gentity k, and gentity_set 2 contains n entry of gentity
2304 *   k, the result contains m-n entries of gentity k.  (What about
2305 *   ordered sets? What if gentity_set 2 is not a subset of gentity set
2306 *   1?  Should be consistent with STL... )
2307 */
2308enum TSTTB_ErrorType
2309TSTTG_subtract (TSTTG_Instance instance,
2310                /*in*/ TSTTG_CGentitySetHandle entity_set_1,
2311                /*in*/ TSTTG_CGentitySetHandle entity_set_2,
2312                /*out*/ TSTTG_GentitySetHandle *result_entity_set)
2313{
2314  const RefGroup *set1 = CONST_SET_HANDLE(entity_set_1);
2315  const RefGroup *set2 = CONST_SET_HANDLE(entity_set_2);
2316  RefGroup *set3 = SET_HANDLE(*result_entity_set);
2317  if (NULL == set3) {
2318    set3 = RefEntityFactory::instance()->construct_RefGroup();
2319    *result_entity_set = set3;
2320  }
2321   
2322  set3->subtract(const_cast<RefGroup*>(set2), const_cast<RefGroup*>(set1));
2323  RETURN(TSTTB_SUCCESS);
2324}
2325
2326/**
2327 *   Intersect gentity_set_1 and gentity_set_2; the result is returned in
2328 *   gentity_set_1.  If both are multisets and both contain 2 entries of
2329 *   gentity k, the intersection contains 2 entries as well.
2330 */
2331enum TSTTB_ErrorType
2332TSTTG_intersect (TSTTG_Instance instance,
2333                 /*in*/ TSTTG_CGentitySetHandle entity_set_1,
2334                 /*in*/ TSTTG_CGentitySetHandle entity_set_2,
2335                 /*out*/ TSTTG_GentitySetHandle *result_entity_set)
2336{
2337  const RefGroup *set1 = CONST_SET_HANDLE(entity_set_1);
2338  const RefGroup *set2 = CONST_SET_HANDLE(entity_set_2);
2339  RefGroup *set3 = SET_HANDLE(*result_entity_set);
2340  if (NULL == set3) {
2341    set3 = RefEntityFactory::instance()->construct_RefGroup();
2342    *result_entity_set = set3;
2343  }
2344
2345  set3->intersect(const_cast<RefGroup*>(set2), const_cast<RefGroup*>(set1));
2346  RETURN(TSTTB_SUCCESS);
2347}
2348
2349/**
2350 *   Union the gentities in gentity_set_1 and gentity_set_2; the result is
2351 *   returned in gentity_set_1.  The multiset flag in gentityset 1
2352 *   determines if duplicate entries are allowed.
2353 */
2354enum TSTTB_ErrorType
2355TSTTG_unite (TSTTG_Instance instance,
2356             /*in*/ TSTTG_CGentitySetHandle entity_set_1,
2357             /*in*/ TSTTG_CGentitySetHandle entity_set_2,
2358             /*out*/ TSTTG_GentitySetHandle *result_entity_set)
2359{
2360  const RefGroup *set1 = CONST_SET_HANDLE(entity_set_1);
2361  const RefGroup *set2 = CONST_SET_HANDLE(entity_set_2);
2362  RefGroup *set3 = SET_HANDLE(*result_entity_set);
2363  if (NULL == set3) {
2364    set3 = RefEntityFactory::instance()->construct_RefGroup();
2365    *result_entity_set = set3;
2366  }
2367
2368  set3->unite(const_cast<RefGroup*>(set2), const_cast<RefGroup*>(set1));
2369  RETURN(TSTTB_SUCCESS);
2370}
2371
2372enum TSTTB_ErrorType
2373TSTTG_Copy (TSTTG_Instance instance,
2374            /*in*/ TSTTG_GentityHandle geom_entity,
2375            /*out*/ TSTTG_GentityHandle *geom_entity2)
2376{
2377  Body *this_body = dynamic_cast<Body*>(ENTITY_HANDLE(geom_entity));
2378  RefVolume *this_vol = dynamic_cast<RefVolume*>(ENTITY_HANDLE(geom_entity));
2379  if (NULL != this_vol || NULL != this_body) {
2380      // need to get the associated body, since cgm only supports copying bodies,
2381      // not volumes
2382    if (NULL == this_body) {
2383      this_body = this_vol->get_body_ptr();
2384      if (NULL == this_body) {
2385        TSTTG_processError(TSTTB_FAILURE, "Can't get body from volume.");
2386        RETURN(TSTTB_INVALID_ARGUMENT);
2387      }
2388    }
2389
2390    RefEntity *temp_entity = gmt->copy_body(this_body);
2391    *geom_entity2 = temp_entity;
2392  }
2393  else {
2394    RefEntity *this_ent = ENTITY_HANDLE(geom_entity);
2395    RefEntity *temp_entity = gmt->copy_refentity(this_ent);
2396    *geom_entity2 = temp_entity;
2397  }
2398
2399  if (NULL == *geom_entity2) {
2400    TSTTG_processError(TSTTB_FAILURE, "NULL returned from CGM copy.");
2401    RETURN(TSTTB_FAILURE);
2402  }
2403 
2404  RETURN(TSTTB_SUCCESS);
2405}
2406     
2407enum TSTTB_ErrorType
2408TSTTG_SweepAboutAxis (TSTTG_Instance instance,
2409                      /*in*/ TSTTG_GentityHandle geom_entity,
2410                      /*in*/ const double angle,
2411                      /*in*/ const double axis_normal_x,
2412                      /*in*/ const double axis_normal_y,
2413                      /*in*/ const double axis_normal_z,
2414                      /*out*/ TSTTG_GentityHandle *geom_entity2)
2415{
2416  DLIList<RefEntity*> ents;
2417  RefEntity *this_ent = ENTITY_HANDLE(geom_entity);
2418  if (NULL == this_ent) {
2419    TSTTG_processError(TSTTB_FAILURE, "Can't get ref entity from specified entity.");
2420    RETURN(TSTTB_INVALID_ARGUMENT);
2421  }
2422  else if (this_ent->dimension() > 2) {
2423    TSTTG_processError(TSTTB_INVALID_ENTITY_TYPE, "Can't sweep 3-d entities.");
2424    RETURN(TSTTB_INVALID_ARGUMENT);
2425  }
2426
2427  RefEntity *new_ent = gmt->copy_refentity(this_ent);
2428  ents.append(new_ent);
2429 
2430  CubitVector origin(0.0, 0.0, 0.0);
2431  CubitVector direction(axis_normal_x, axis_normal_y, axis_normal_z);
2432
2433  double radian_angle = angle * DEG_TO_RAD;
2434 
2435  CubitStatus result = gmt->sweep_rotational(ents, origin, direction,
2436                                             radian_angle);
2437  if (CUBIT_FAILURE == result) {
2438      // destroy entity we copied before
2439    gqt->delete_RefEntity(new_ent);
2440    TSTTG_processError(TSTTB_FAILURE, "Sweep returned failure.");
2441    RETURN(TSTTB_FAILURE);
2442  }
2443 
2444  else {
2445      // HACK to get last entity created, because cgm doesn't return
2446      // body created by sweep
2447    RefEntity *new_body = RefEntityFactory::instance()->get_last_body();
2448    *geom_entity2 = new_body;
2449
2450      // now we know it's succeeded, delete original body
2451    Body *this_body = dynamic_cast<TopologyEntity*>(this_ent)->body();
2452    if (NULL != this_body)
2453      gqt->delete_RefEntity(this_body);
2454    else
2455      gqt->delete_RefEntity(this_ent);
2456  }
2457
2458
2459  if (NULL == *geom_entity2) {
2460    RETURN(TSTTB_FAILURE);
2461  }
2462 
2463  RETURN(TSTTB_SUCCESS);
2464}
2465     
2466enum TSTTB_ErrorType
2467TSTTG_Delete (TSTTG_Instance instance,
2468              /*in*/ TSTTG_GentityHandle geom_entity)
2469{
2470  RefEntity *this_ent = ENTITY_HANDLE(geom_entity);
2471
2472    // special case: if this is a volume, delete the body instead
2473  CubitStatus result;
2474  RefVolume *this_vol = CAST_TO(this_ent, RefVolume);
2475  if (NULL != this_vol)
2476    result = gqt->delete_Body(this_vol->body());
2477  else   
2478    result = gqt->delete_RefEntity(this_ent);
2479
2480  if (CUBIT_FAILURE == result) {
2481    TSTTG_processError(TSTTB_FAILURE, "Problems deleting entity.");
2482    RETURN(TSTTB_FAILURE);
2483  }
2484
2485    // check to see if this was last thing deleted; if so, reset ids
2486  RefEntityFactory *rfi = RefEntityFactory::instance();
2487  if (rfi->num_bodies() == 0 && 
2488      rfi->num_ref_volumes() == 0 &&
2489      rfi->num_ref_faces() == 0 &&
2490      rfi->num_ref_edges() == 0 &&
2491      rfi->num_ref_vertices() == 0)
2492    rfi->reset_ids();
2493 
2494  RETURN(TSTTB_SUCCESS);
2495}
2496
2497enum TSTTB_ErrorType
2498TSTTG_Brick (TSTTG_Instance instance,
2499             /*in*/ const double x,
2500             /*in*/ const double y,
2501             /*in*/ const double z,
2502             /*out*/ TSTTG_GentityHandle *geom_entity)
2503{
2504  double tmp_x = x;
2505  double tmp_y = y;
2506  double tmp_z = z;
2507 
2508  if (0.0 == y && 0.0 == z) {
2509    tmp_y = x;
2510    tmp_z = x;
2511  }
2512 
2513  if (0.0 >= tmp_x || 0.0 >= tmp_y || 0.0 >= tmp_z) {
2514    TSTTG_processError(TSTTB_INVALID_ARGUMENT, "Dimensions must be >= 0, or y & z must both be zero.");
2515    RETURN(TSTTB_INVALID_ARGUMENT);
2516  }
2517   
2518  RefEntity *temp_body = gmt->brick(tmp_x, tmp_y, tmp_z);
2519  *geom_entity = temp_body;
2520
2521  if (NULL == *geom_entity) {
2522    RETURN(TSTTB_FAILURE);
2523  }
2524 
2525  RETURN(TSTTB_SUCCESS);
2526}
2527         
2528enum TSTTB_ErrorType
2529TSTTG_Cylinder (TSTTG_Instance instance,
2530                /*in*/ const double height,
2531                /*in*/ const double major_rad,
2532                /*in*/ const double minor_rad,
2533                /*out*/ TSTTG_GentityHandle *geom_entity)
2534{
2535  double tmp_minor = (0.0 == minor_rad ? major_rad : minor_rad);
2536  RefEntity *temp_body = 
2537    gmt->cylinder(height, major_rad, tmp_minor, major_rad);
2538  *geom_entity = temp_body;
2539
2540
2541  if (NULL == *geom_entity) {
2542    RETURN(TSTTB_FAILURE);
2543  }
2544 
2545  RETURN(TSTTB_SUCCESS);
2546}
2547         
2548enum TSTTB_ErrorType
2549TSTTG_Torus (TSTTG_Instance instance,
2550             /*in*/ const double major_rad,
2551             /*in*/ const double minor_rad,
2552             /*out*/ TSTTG_GentityHandle *geom_entity)
2553{
2554  if (minor_rad >= major_rad) {
2555    TSTTG_processError(TSTTB_INVALID_ARGUMENT, "Major radius must be greater than minor radius for tori.");
2556    RETURN(TSTTB_INVALID_ARGUMENT);
2557  }
2558 
2559  RefEntity *temp_body = gmt->torus(major_rad, minor_rad);
2560  *geom_entity = temp_body;
2561
2562  if (NULL == *geom_entity) {
2563    RETURN(TSTTB_FAILURE);
2564  }
2565 
2566  RETURN(TSTTB_SUCCESS);
2567}
2568
2569enum TSTTB_ErrorType
2570TSTTG_Move (TSTTG_Instance instance,
2571            /*inout*/ TSTTG_GentityHandle *geom_entity,
2572            /*in*/ const double x,
2573            /*in*/ const double y,
2574            /*in*/ const double z)
2575{
2576  CubitVector vec(x, y, z);
2577  Body *this_bod = dynamic_cast<Body*>(ENTITY_HANDLE(*geom_entity));
2578  CubitStatus result;
2579  if (NULL != this_bod) {
2580    result = gqt->translate(this_bod, vec);
2581    if (CUBIT_SUCCESS != result) {
2582      TSTTG_processError(TSTTB_FAILURE, "Failed to move body.");
2583      RETURN(TSTTB_FAILURE);
2584    }
2585   
2586    RETURN(TSTTB_SUCCESS);
2587  }
2588 
2589  BasicTopologyEntity *this_bte = dynamic_cast<BasicTopologyEntity*>(ENTITY_HANDLE(*geom_entity));
2590  if (NULL != this_bte) {
2591      // non-body move; check to see if there are any siblings to this entity in the
2592      // same body; if so, we can't move it; if not, get the body and move that; if
2593      // there is no body, it's a free entity and we can move it anyway
2594    Body *this_body = this_bte->body();
2595    if (NULL == this_body) {
2596      result = gqt->translate(this_bte, vec);
2597      if (CUBIT_SUCCESS != result) {
2598        TSTTG_processError(TSTTB_FAILURE, "Failed to move entity.");
2599        RETURN(TSTTB_FAILURE);
2600      }
2601    }
2602    else {
2603      int num_sibs = -1;
2604      switch (this_bte->dimension()) {
2605        case 0: num_sibs = this_body->num_ref_vertices(); break;
2606        case 1: num_sibs = this_body->num_ref_edges(); break;
2607        case 2: num_sibs = this_body->num_ref_faces(); break;
2608      }
2609      if (num_sibs == 1) {
2610          // ok to move the body instead
2611        result = gqt->translate(this_body, vec);
2612        if (CUBIT_SUCCESS != result) {
2613          TSTTG_processError(TSTTB_FAILURE, "Failed to move body even only one entity of that"
2614                             " dimension in the body.");
2615          RETURN(TSTTB_FAILURE);
2616        }
2617      }
2618      else {
2619        TSTTG_processError(TSTTB_FAILURE, "Too many siblings for an entity to move it.");
2620        RETURN(TSTTB_FAILURE);
2621      }
2622    }
2623
2624    RETURN(TSTTB_SUCCESS);
2625  }
2626 
2627  TSTTG_processError(TSTTB_INVALID_ENTITY_TYPE, "Wrong type of entity specified for move.");
2628  RETURN(TSTTB_INVALID_ENTITY_TYPE);
2629}
2630     
2631enum TSTTB_ErrorType
2632TSTTG_Rotate (TSTTG_Instance instance,
2633              /*inout*/ TSTTG_GentityHandle *geom_entity,
2634              /*in*/ const double angle,
2635              /*in*/ const double axis_normal_x,
2636              /*in*/ const double axis_normal_y,
2637              /*in*/ const double axis_normal_z)
2638{
2639  CubitVector this_axis(axis_normal_x, axis_normal_y, axis_normal_z);
2640  Body *this_bod = dynamic_cast<Body*>(ENTITY_HANDLE(*geom_entity));
2641  CubitStatus result;
2642  if (NULL != this_bod) {
2643    result = gqt->rotate(this_bod, this_axis, angle);
2644    if (CUBIT_SUCCESS != result) {
2645      TSTTG_processError(TSTTB_FAILURE, "Failed to rotate body.");
2646      RETURN(TSTTB_FAILURE);
2647    }
2648   
2649    RETURN(TSTTB_SUCCESS);
2650  }
2651 
2652  BasicTopologyEntity *this_bte = dynamic_cast<BasicTopologyEntity*>(ENTITY_HANDLE(*geom_entity));
2653  if (NULL != this_bte) {
2654    result = gqt->rotate(this_bte, this_axis, angle);
2655    if (CUBIT_SUCCESS != result) {
2656      TSTTG_processError(TSTTB_FAILURE, "Failed to rotate entity.");
2657      RETURN(TSTTB_FAILURE);
2658    }
2659   
2660    RETURN(TSTTB_SUCCESS);
2661  }
2662 
2663  TSTTG_processError(TSTTB_INVALID_ENTITY_TYPE, "Wrong type of entity specified for move.");
2664  RETURN(TSTTB_INVALID_ENTITY_TYPE);
2665}
2666     
2667enum TSTTB_ErrorType
2668TSTTG_Reflect (TSTTG_Instance instance,
2669               /*inout*/ TSTTG_GentityHandle *geom_entity,
2670               /*in*/ const double plane_normal_x,
2671               /*in*/ const double plane_normal_y,
2672               /*in*/ const double plane_normal_z)
2673{
2674  CubitVector this_plane(plane_normal_x, plane_normal_y, plane_normal_z);
2675  Body *this_bod = dynamic_cast<Body*>(ENTITY_HANDLE(*geom_entity));
2676  DLIList<Body*> bods;
2677  bods.append(this_bod);
2678  CubitStatus result;
2679  if (NULL != this_bod) {
2680    result = gqt->reflect(bods, this_plane);
2681    if (CUBIT_SUCCESS != result) {
2682      TSTTG_processError(TSTTB_FAILURE, "Failed to reflect body.");
2683      RETURN(TSTTB_FAILURE);
2684    }
2685   
2686    RETURN(TSTTB_SUCCESS);
2687  }
2688 
2689  BasicTopologyEntity *this_bte = dynamic_cast<BasicTopologyEntity*>(ENTITY_HANDLE(*geom_entity));
2690  if (NULL != this_bte) {
2691    result = gqt->reflect(this_bte, this_plane);
2692    if (CUBIT_SUCCESS != result) {
2693      TSTTG_processError(TSTTB_FAILURE, "Failed to reflect entity.");
2694      RETURN(TSTTB_FAILURE);
2695    }
2696   
2697    RETURN(TSTTB_SUCCESS);
2698  }
2699 
2700  TSTTG_processError(TSTTB_INVALID_ENTITY_TYPE, "Wrong type of entity specified for reflect.");
2701  RETURN(TSTTB_INVALID_ENTITY_TYPE);
2702}
2703
2704enum TSTTB_ErrorType
2705TSTTG_Scale (TSTTG_Instance instance,
2706             /*inout*/ TSTTG_GentityHandle *geom_entity,
2707             /*in*/ const double scale_x,
2708             /*in*/ const double scale_y,
2709             /*in*/ const double scale_z) 
2710{
2711  CubitVector factor(scale_x, scale_y, scale_z);
2712  Body *this_bod = dynamic_cast<Body*>(ENTITY_HANDLE(*geom_entity));
2713  CubitStatus result;
2714  if (NULL != this_bod) {
2715    result = gqt->scale(this_bod, factor);
2716    if (CUBIT_SUCCESS != result) {
2717      TSTTG_processError(TSTTB_FAILURE, "Failed to scale body.");
2718      RETURN(TSTTB_FAILURE);
2719    }
2720   
2721    RETURN(TSTTB_SUCCESS);
2722  }
2723 
2724  BasicTopologyEntity *this_bte = dynamic_cast<BasicTopologyEntity*>(ENTITY_HANDLE(*geom_entity));
2725    // non-body move; check to see if there are any siblings to this entity in the
2726    // same body; if so, we can't move it; if not, get the body and move that; if
2727    // there is no body, it's a free entity and we can move it anyway
2728  Body *this_body = this_bte->body();
2729  if (NULL == this_body && NULL != this_bte) {
2730    result = gqt->scale(this_bte, factor);
2731    if (CUBIT_SUCCESS != result) {
2732      TSTTG_processError(TSTTB_FAILURE, "Failed to scale entity.");
2733      RETURN(TSTTB_FAILURE);
2734    }
2735  }
2736  else if (NULL != this_body && NULL != this_bte) {
2737    int num_sibs = -1;
2738    switch (this_bte->dimension()) {
2739      case 0: num_sibs = this_body->num_ref_vertices(); break;
2740      case 1: num_sibs = this_body->num_ref_edges(); break;
2741      case 2: num_sibs = this_body->num_ref_faces(); break;
2742          // for TSTT, always scale volumes
2743      case 3: num_sibs = 1; break;
2744    }
2745    if (num_sibs == 1) {
2746        // ok to scale the body instead
2747      result = gqt->scale(this_body, factor);
2748      if (CUBIT_SUCCESS != result) {
2749        TSTTG_processError(TSTTB_FAILURE, "Failed to scale body even only one entity of that"
2750                           " dimension in the body.");
2751        RETURN(TSTTB_FAILURE);
2752      }
2753    }
2754    else {
2755      TSTTG_processError(TSTTB_FAILURE, "Too many siblings for an entity to scale it.");
2756      RETURN(TSTTB_FAILURE);
2757    }
2758  }
2759
2760  RETURN(TSTTB_SUCCESS);
2761}
2762
2763enum TSTTB_ErrorType
2764TSTTG_Unite (TSTTG_Instance instance,
2765             /*in*/ ARRAY_IN_DECL(TSTTG_GentityHandle, geom_entities),
2766             /*out*/ TSTTG_GentityHandle *geom_entity)
2767{
2768  DLIList<Body*> bods, orig_bods;
2769  RefEntity **handle_array = ENTITY_HANDLE_ARRAY(geom_entities);
2770  for (int i = 0; i < geom_entities_size; i++) {
2771    Body *this_body = dynamic_cast<Body*>(handle_array[i]);
2772    if (NULL != this_body) {
2773      Body *new_body = gmt->copy_body(this_body);
2774      if (NULL != new_body) {
2775        bods.append(this_body);
2776        orig_bods.append(new_body);
2777      }
2778    }
2779  }
2780  if (bods.size() < geom_entities_size) {
2781    TSTTG_processError(TSTTB_INVALID_ARGUMENT, "Not all entities input were regions.");
2782    for (int i = bods.size(); i > 0; i--)
2783      gqt->delete_RefEntity(bods.get_and_step());
2784   
2785    RETURN(TSTTB_SUCCESS);
2786  }
2787 
2788  DLIList<Body*> new_bods;
2789  CubitStatus result = gmt->unite(bods, new_bods, false);
2790  if (CUBIT_SUCCESS != result || 1 != new_bods.size()) {
2791    TSTTG_processError(TSTTB_FAILURE, "Unite failed.");
2792    RETURN(TSTTB_FAILURE);
2793  }
2794   
2795  else {
2796    *geom_entity = dynamic_cast<RefEntity*>(new_bods.get());
2797    for (int i = orig_bods.size(); i > 0; i--)
2798      gqt->delete_RefEntity(orig_bods.get_and_step());
2799  }
2800
2801  RETURN(TSTTB_SUCCESS);
2802}
2803     
2804enum TSTTB_ErrorType
2805TSTTG_Subtract (TSTTG_Instance instance,
2806                /*in*/ TSTTG_GentityHandle blank,
2807                /*in*/ TSTTG_GentityHandle tool,
2808                /*out*/ TSTTG_GentityHandle *geom_entity)
2809{
2810  Body *this_blank = dynamic_cast<Body*>(ENTITY_HANDLE(blank));
2811  Body *blank_copy = gmt->copy_body(this_blank);
2812  if (NULL == blank_copy) {
2813    TSTTG_processError(TSTTB_FAILURE, "Trouble copying blank.");
2814    RETURN(TSTTB_FAILURE);
2815  }
2816  Body *this_tool = dynamic_cast<Body*>(ENTITY_HANDLE(tool));
2817  Body *tool_copy = gmt->copy_body(this_tool);
2818  if (NULL == tool_copy) {
2819    TSTTG_processError(TSTTB_FAILURE, "Trouble copying tool.");
2820    gqt->delete_RefEntity(blank_copy);
2821    RETURN(TSTTB_FAILURE);
2822  }
2823
2824  DLIList<Body*> blank_list, new_body_list;
2825  blank_list.append(blank_copy);
2826 
2827  RefEntity *new_body = NULL;
2828  CubitStatus result = gmt->subtract(tool_copy, blank_list, new_body_list);
2829  if (CUBIT_SUCCESS != result || 0 == new_body_list.size()) {
2830    TSTTG_processError(TSTTB_FAILURE, "Subtract failed.");
2831    RETURN(TSTTB_FAILURE);
2832  }
2833  else {
2834    new_body = new_body_list.get();
2835    *geom_entity = new_body;
2836    gqt->delete_RefEntity(this_blank);
2837    gqt->delete_RefEntity(this_tool);
2838  }
2839
2840  RETURN(TSTTB_SUCCESS);
2841}
2842
2843enum TSTTB_ErrorType
2844TSTTG_Section (TSTTG_Instance instance,
2845               /*inout*/ TSTTG_GentityHandle *geom_entity,
2846               /*in*/ const double plane_normal_x,
2847               /*in*/ const double plane_normal_y,
2848               /*in*/ const double plane_normal_z,
2849               /*in*/ const double offset,
2850               /*in*/ const bool reverse,
2851               /*out*/ TSTTG_GentityHandle *geom_entity2)
2852{
2853  Body *this_body = dynamic_cast<Body*>(ENTITY_HANDLE(*geom_entity));
2854  if (NULL == this_body) {
2855    RefVolume *this_vol = dynamic_cast<RefVolume*>(ENTITY_HANDLE(*geom_entity));
2856    if (NULL != this_vol)
2857      this_body = this_vol->get_body_ptr();
2858  }
2859  if (NULL == this_body) {
2860    TSTTG_processError(TSTTB_INVALID_ARGUMENT, "Can only section bodies.");
2861    RETURN(TSTTB_INVALID_ARGUMENT);
2862  }
2863
2864  CubitVector normal(plane_normal_x, plane_normal_y, plane_normal_z);
2865  if (normal.length_squared() == 0.0) {
2866    TSTTG_processError(TSTTB_INVALID_ARGUMENT, "Zero-length vector input.");
2867    RETURN(TSTTB_INVALID_ARGUMENT);
2868  }
2869 
2870  CubitVector point1 = normal * CubitVector(1.0, 0.0, 0.0);
2871  if (point1.length_squared() == 0.0)
2872    point1 = normal * CubitVector(0.0, 1.0, 0.0);
2873   
2874  CubitVector point2 = normal * point1;
2875  CubitVector point3(0.0, 0.0, 0.0);
2876
2877  if (0.0 != offset) {
2878    normal.normalize();
2879    normal *= offset;
2880    point1 += normal;
2881    point2 += normal;
2882    point3 += normal;
2883  }
2884
2885 
2886  DLIList<Body*> blank_list, new_body_list;
2887  blank_list.append(gmt->copy_body(this_body));
2888  CubitStatus result = gmt->section(blank_list, point1, point2, point3,
2889                                    new_body_list, !reverse,
2890                                    false);
2891  if (CUBIT_SUCCESS != result || 0 == new_body_list.size()) {
2892    TSTTG_processError(TSTTB_FAILURE, "Section failed.");
2893    gqt->delete_RefEntity(blank_list.get());
2894    RETURN(TSTTB_FAILURE);
2895  }
2896   
2897  else {
2898      // need to assign it to a RE* first so the void cast gets done right
2899    RefEntity *new_body = new_body_list.get();
2900    *geom_entity2 = new_body;
2901      // also, delete the original body, now that the section worked
2902    gqt->delete_RefEntity(this_body);
2903  }
2904
2905  RETURN(TSTTB_SUCCESS);
2906}
2907
2908enum TSTTB_ErrorType
2909TSTTG_Imprint (TSTTG_Instance instance,
2910               /*in*/ ARRAY_IN_DECL(TSTTG_GentityHandle, gentity_handles)) 
2911{
2912  DLIList<Body*> bods;
2913  DLIList<RefVolume*> vols, temp_vols;
2914  RefEntity **handle_array = ENTITY_HANDLE_ARRAY(gentity_handles);
2915  CubitStatus status = CUBIT_SUCCESS;
2916  for (int i = 0; i < gentity_handles_size; i++) {
2917    Body *temp_bod = dynamic_cast<Body*>(handle_array[i]);
2918    if (NULL != temp_bod) {
2919      bods.append_unique(temp_bod);
2920      continue;
2921    }
2922   
2923    RefVolume *temp_vol = dynamic_cast<RefVolume*>(handle_array[i]);
2924    if (NULL != temp_vol) {
2925      TopologyEntity *topo_ent = dynamic_cast<TopologyEntity*>(handle_array[i]);
2926      if (NULL == topo_ent) {
2927        status = CUBIT_FAILURE;
2928        continue;
2929      }
2930      temp_bod = topo_ent->body();
2931      if (NULL == temp_bod) {
2932        status = CUBIT_FAILURE;
2933        continue;
2934      }
2935      bods.append_unique(temp_bod);
2936      continue;
2937    }
2938
2939      // if we've gotten here, it's an error
2940    status = CUBIT_FAILURE;
2941  }
2942 
2943  if (CUBIT_SUCCESS != status) RETURN(TSTTB_FAILURE);
2944
2945  DLIList<Body*> temp_bods;
2946  status = GeometryModifyTool::instance()->imprint(bods, temp_bods, false);
2947 
2948  RETURN(TSTTB_SUCCESS);
2949}
2950 
2951enum TSTTB_ErrorType
2952TSTTG_Merge (TSTTG_Instance instance,
2953             /*in*/ ARRAY_IN_DECL(TSTTG_GentityHandle, gentity_handles),
2954             const double tolerance) 
2955{
2956  double old_factor = GeometryQueryTool::instance()->get_geometry_factor();
2957  if (tolerance != old_factor) 
2958    GeometryQueryTool::instance()->set_geometry_factor(tolerance*1.0e6);
2959  else old_factor = 0.0;
2960 
2961  DLIList<Body*> bods;
2962  DLIList<RefVolume*> vols, temp_vols;
2963  DLIList<RefFace*> faces;
2964  DLIList<RefEdge*> edges;
2965  DLIList<RefVertex*> verts;
2966  RefEntity **handle_array = ENTITY_HANDLE_ARRAY(gentity_handles);
2967  for (int i = 0; i < gentity_handles_size; i++) {
2968    TopologyEntity *topo_ent = dynamic_cast<TopologyEntity*>(handle_array[i]);
2969    if (NULL == topo_ent) continue;
2970    Body *temp_bod;
2971    RefVolume *temp_vol;
2972    RefFace *temp_face;
2973    RefEdge *temp_edge;
2974    RefVertex *temp_vert;
2975    switch (handle_array[i]->dimension()) {
2976      case -1:
2977          // it should be a body
2978        temp_bod = dynamic_cast<Body*>(handle_array[i]);
2979        if (NULL == temp_bod) RETURN(TSTTB_FAILURE);
2980        temp_vols.clean_out();
2981        topo_ent->ref_volumes(temp_vols);
2982        vols += temp_vols;
2983        break;
2984      case 0:
2985        temp_vert = dynamic_cast<RefVertex*>(handle_array[i]);
2986        if (NULL == temp_vert) RETURN(TSTTB_FAILURE);
2987        verts.append(temp_vert);
2988        break;
2989      case 1:
2990        temp_edge = dynamic_cast<RefEdge*>(handle_array[i]);
2991        if (NULL == temp_edge) RETURN(TSTTB_FAILURE);
2992        edges.append(temp_edge);
2993        break;
2994      case 2:
2995        temp_face = dynamic_cast<RefFace*>(handle_array[i]);
2996        if (NULL == temp_face) RETURN(TSTTB_FAILURE);
2997        faces.append(temp_face);
2998        break;
2999      case 3:
3000        temp_vol = dynamic_cast<RefVolume*>(handle_array[i]);
3001        if (NULL == temp_vol) RETURN(TSTTB_FAILURE);
3002        vols.append(temp_vol);
3003        break;
3004    }
3005  }
3006 
3007  CubitStatus status = CUBIT_SUCCESS, temp_status;
3008   
3009  if (bods.size() != 0) {
3010    temp_status = MergeTool::instance()->merge_bodies(bods);
3011    if (CUBIT_SUCCESS != temp_status) status = temp_status;
3012  }
3013   
3014  if (vols.size() != 0) {
3015    temp_status = MergeTool::instance()->merge_volumes(vols, false);
3016    if (CUBIT_SUCCESS != temp_status) status = temp_status;
3017  }
3018   
3019  if (faces.size() != 0) {
3020    temp_status = MergeTool::instance()->merge_reffaces(faces, false);
3021    if (CUBIT_SUCCESS != temp_status) status = temp_status;
3022  }
3023   
3024  if (edges.size() != 0) {
3025    temp_status = MergeTool::instance()->merge_refedges(edges, true, false);
3026    if (CUBIT_SUCCESS != temp_status) status = temp_status;
3027  }
3028   
3029  if (verts.size() != 0) {
3030    temp_status = MergeTool::instance()->merge_refvertices(verts, false);
3031    if (CUBIT_SUCCESS != temp_status) status = temp_status;
3032  }
3033
3034  if (0 != old_factor)
3035    GeometryQueryTool::instance()->set_geometry_factor(old_factor);
3036   
3037  if (CUBIT_SUCCESS != status) {
3038    RETURN(TSTTB_FAILURE);
3039  }
3040 
3041  else {
3042    RETURN(TSTTB_SUCCESS);
3043  }
3044}
3045 
Note: See TracBrowser for help on using the browser.