1 /**
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  */
8 /**
9  * \file testgeom.cc
10  *
11  * \brief testgeom, a unit test for the ITAPS geometry interface
12  *
13  */
14 #include "FBiGeom.h"
15 #include <iostream>
16 #include <set>
17 #include <algorithm>
18 #include <vector>
19 #include <iterator>
20 #include <algorithm>
21 #include <iomanip>
22 #include <assert.h>
23 #include <string.h>
24 #include <math.h>
25 #define CHECK( STR ) if (err != iBase_SUCCESS) return print_error( STR, err, geom, __FILE__, __LINE__ )
26 
27 #define STRINGIFY(S) XSTRINGIFY(S)
28 #define XSTRINGIFY(S) #S
29 
print_error(const char * desc,int err,FBiGeom_Instance geom,const char * file,int line)30 static bool print_error(const char* desc, int err, FBiGeom_Instance geom,
31       const char* file, int line) {
32    char buffer[1024];
33    FBiGeom_getDescription(geom, buffer, sizeof(buffer));
34    buffer[sizeof(buffer) - 1] = '\0';
35 
36    std::cerr << "ERROR: " << desc << std::endl << "  Error code: " << err
37          << std::endl << "  Error desc: " << buffer << std::endl
38          << "  At        : " << file << ':' << line << std::endl;
39 
40    return false; // must always return false or CHECK macro will break
41 }
42 
43 typedef iBase_TagHandle TagHandle;
44 typedef iBase_EntityHandle GentityHandle;
45 typedef iBase_EntitySetHandle GentitysetHandle;
46 
47 /* Frees allocated arrays for us */
48 template<typename T> class SimpleArray {
49 private:
50    T* arr;
51    int arrSize;
52    int arrAllocated;
53 
54 public:
SimpleArray()55    SimpleArray() :
56       arr(0), arrSize(0), arrAllocated(0) {
57    }
SimpleArray(unsigned s)58    SimpleArray(unsigned s) :
59       arrSize(s), arrAllocated(s) {
60       arr = (T*) malloc(s * sizeof(T));
61       for (unsigned i = 0; i < s; ++i)
62          new (arr + i) T();
63    }
64 
~SimpleArray()65    ~SimpleArray() {
66       for (int i = 0; i < size(); ++i)
67          arr[i].~T();
68       free(arr);
69    }
70 
ptr()71    T** ptr() {
72       return &arr;
73    }
size()74    int& size() {
75       return arrSize;
76    }
size() const77    int size() const {
78       return arrSize;
79    }
capacity()80    int& capacity() {
81       return arrAllocated;
82    }
capacity() const83    int capacity() const {
84       return arrAllocated;
85    }
86 
87    typedef T* iterator;
88    typedef const T* const_iterator;
begin()89    iterator begin() {
90       return arr;
91    }
begin() const92    const_iterator begin() const {
93       return arr;
94    }
end()95    iterator end() {
96       return arr + arrSize;
97    }
end() const98    const_iterator end() const {
99       return arr + arrSize;
100    }
101 
operator [](unsigned idx)102    T& operator[](unsigned idx) {
103       return arr[idx];
104    }
operator [](unsigned idx) const105    T operator[](unsigned idx) const {
106       return arr[idx];
107    }
108 };
109 
110 #define ARRAY_INOUT( A ) A.ptr(), &A.capacity(), &A.size()
111 #define ARRAY_IN( A ) &A[0], A.size()
112 
113 bool smooth_test(const std::string &filename, FBiGeom_Instance);
114 
115 bool tags_test(FBiGeom_Instance geom);
116 bool tag_get_set_test(FBiGeom_Instance geom);
117 bool tag_info_test(FBiGeom_Instance geom);
118 bool gentityset_test(FBiGeom_Instance geom, bool /*multiset*/, bool /*ordered*/);
119 bool topology_adjacencies_test(FBiGeom_Instance geom);
120 bool geometry_evaluation_test(FBiGeom_Instance geom);
121 bool construct_test(FBiGeom_Instance geom);
122 bool primitives_test(FBiGeom_Instance geom);
123 bool transforms_test(FBiGeom_Instance geom);
124 bool booleans_test(FBiGeom_Instance geom);
125 bool shutdown_test(FBiGeom_Instance geom, std::string &engine_opt);
126 bool save_entset_test(FBiGeom_Instance geom);
127 bool mesh_size_test(FBiGeom_Instance geom);
128 bool normals_test(FBiGeom_Instance geom);
129 
130 bool ray_test(FBiGeom_Instance geom);
131 
handle_error_code(const bool result,int & number_failed,int &,int & number_successful)132 void handle_error_code(const bool result, int &number_failed,
133       int &/*number_not_implemented*/, int &number_successful) {
134    if (result) {
135       std::cout << "Success";
136       number_successful++;
137    } else {
138       std::cout << "Failure";
139       number_failed++;
140    }
141 }
142 
main(int argc,char * argv[])143 int main(int argc, char *argv[]) {
144    std::string filename = STRINGIFY(MESHDIR) "/shell.h5m";
145    std::string engine_opt;
146 
147    if (argc == 1) {
148       std::cout << "Using default input file: " << filename << std::endl;
149    } else if (argc == 2) {
150       filename = argv[1];
151    } else {
152       std::cerr << "Usage: " << argv[0] << " [geom_filename]" << std::endl;
153       return 1;
154    }
155 
156    bool result;
157    int number_tests = 0;
158    int number_tests_successful = 0;
159    int number_tests_not_implemented = 0;
160    int number_tests_failed = 0;
161 
162    // initialize the Mesh
163    int err;
164    FBiGeom_Instance geom;
165    FBiGeom_newGeom(engine_opt.c_str(), &geom, &err, engine_opt.length());
166    CHECK( "Interface initialization didn't work properly." );
167 
168    // Print out Header information
169    std::cout << "\n\nITAPS GEOMETRY INTERFACE TEST PROGRAM:\n\n";
170    // gLoad test
171 
172    std::cout << "   Smooth faceting load and initialization: \n";
173    result = smooth_test(filename, geom);
174    handle_error_code(result, number_tests_failed, number_tests_not_implemented,
175          number_tests_successful);
176 
177    number_tests++;
178    std::cout << "\n";
179 
180    // tags test
181    std::cout << "   tags: ";
182    result = tags_test(geom);
183    handle_error_code(result, number_tests_failed, number_tests_not_implemented,
184          number_tests_successful);
185    number_tests++;
186    std::cout << "\n";
187    /*
188     // gentitysets test
189     std::cout << "   gentity sets: ";
190     result = gentityset_test(geom, false, false);
191     handle_error_code(result, number_tests_failed,
192     number_tests_not_implemented,
193     number_tests_successful);
194     number_tests++;
195     std::cout << "\n";
196     */
197    // topology adjacencies test
198    std::cout << "   topology adjacencies: ";
199    result = topology_adjacencies_test(geom);
200    handle_error_code(result, number_tests_failed, number_tests_not_implemented,
201          number_tests_successful);
202    number_tests++;
203    std::cout << "\n";
204 
205    // geometry evaluation test
206    std::cout << "   geometry evaluation: \n";
207    result = geometry_evaluation_test(geom);
208    handle_error_code(result, number_tests_failed, number_tests_not_implemented,
209          number_tests_successful);
210    number_tests++;
211    std::cout << "\n";
212 
213    // normals evaluation test
214    std::cout << "   normals geometry evaluation: \n";
215    result = normals_test(geom);
216    handle_error_code(result, number_tests_failed, number_tests_not_implemented,
217          number_tests_successful);
218    number_tests++;
219    std::cout << "\n";
220 
221    // ray tracing test
222    std::cout << "   ray intersection test: \n";
223    result = ray_test(geom);
224    handle_error_code(result, number_tests_failed, number_tests_not_implemented,
225             number_tests_successful);
226    number_tests++;
227    std::cout << "\n";
228    /*
229     // construct test
230     std::cout << "   construct: ";
231     result = construct_test(geom);
232     handle_error_code(result, number_tests_failed,
233     number_tests_not_implemented,
234     number_tests_successful);
235     number_tests++;
236     std::cout << "\n";
237 
238     // primitives test
239     std::cout << "   primitives: ";
240     result = primitives_test(geom);
241     handle_error_code(result, number_tests_failed,
242     number_tests_not_implemented,
243     number_tests_successful);
244     number_tests++;
245     std::cout << "\n";
246 
247     // transforms test
248     std::cout << "   transforms: ";
249     result = transforms_test(geom);
250     handle_error_code(result, number_tests_failed,
251     number_tests_not_implemented,
252     number_tests_successful);
253     number_tests++;
254     std::cout << "\n";
255 
256     // booleans test
257     std::cout << "   booleans: ";
258     result = booleans_test(geom);
259     handle_error_code(result, number_tests_failed,
260     number_tests_not_implemented,
261     number_tests_successful);
262     number_tests++;
263     std::cout << "\n";
264 
265     #if defined(HAVE_ACIS) && !defined(FORCE_OCC)
266     std::cout << "   mesh size: ";
267     result = mesh_size_test(geom);
268     handle_error_code(result, number_tests_failed,
269     number_tests_not_implemented,
270     number_tests_successful);
271     number_tests++;
272     std::cout << "\n";
273 
274     // save entset test
275     std::cout << "   save entset: ";
276     result = save_entset_test(geom);
277     handle_error_code(result, number_tests_failed,
278     number_tests_not_implemented,
279     number_tests_successful);
280     number_tests++;
281     std::cout << "\n";
282     #endif
283     */
284    // shutdown test
285    std::cout << "   shutdown: ";
286    result = shutdown_test(geom, engine_opt);
287    handle_error_code(result, number_tests_failed, number_tests_not_implemented,
288          number_tests_successful);
289    number_tests++;
290    std::cout << "\n";
291 
292    // summary
293 
294    std::cout << "\nTSTT TEST SUMMARY: \n" << "   Number Tests:           "
295          << number_tests << "\n" << "   Number Successful:      "
296          << number_tests_successful << "\n" << "   Number Not Implemented: "
297          << number_tests_not_implemented << "\n"
298          << "   Number Failed:          " << number_tests_failed << "\n\n"
299          << std::endl;
300 
301    return number_tests_failed;
302 }
303 
304 /*!
305  @test
306  Load Mesh
307  @li Load a mesh file
308  */
309 
smooth_test(const std::string & filename,FBiGeom_Instance geom)310 bool smooth_test(const std::string &filename, FBiGeom_Instance geom) {
311    int err;
312    char opts[] = "SMOOTH;";
313    FBiGeom_load(geom, &filename[0], opts, &err, filename.length(), 8);
314    //FBiGeom_load( geom, &filename[0], 0, &err, filename.length(), 0 );
315    CHECK( "ERROR : can not load a geometry" );
316 
317    iBase_EntitySetHandle root_set;
318    FBiGeom_getRootSet(geom, &root_set, &err);
319    CHECK( "ERROR : getRootSet failed!" );
320 
321    // print out the number of entities
322    std::cout << "Model contents: " << std::endl;
323    const char *gtype[] = { "vertices: ", "edges: ", "faces: ", "regions: " };
324    for (int i = 0; i <= 3; ++i) {
325       int count;
326       FBiGeom_getNumOfType(geom, root_set, i, &count, &err);
327       CHECK( "Error: problem getting entities after gLoad." );
328       std::cout << gtype[i] << count << std::endl;
329    }
330 
331    return true;
332 }
333 /*!
334  @test
335  Test tag creating, reading, writing, deleting
336  @li Load a mesh file
337  */
tags_test(FBiGeom_Instance geom)338 bool tags_test(FBiGeom_Instance geom) {
339    bool success = tag_info_test(geom);
340    if (!success)
341       return success;
342 
343    success = tag_get_set_test(geom);
344    if (!success)
345       return success;
346 
347    return true;
348 }
349 
tag_info_test(FBiGeom_Instance geom)350 bool tag_info_test(FBiGeom_Instance geom) {
351    int err;
352 
353    iBase_EntitySetHandle root_set;
354    FBiGeom_getRootSet(geom, &root_set, &err);
355    CHECK( "ERROR : getRootSet failed!" );
356 
357    // create an arbitrary tag, size 4
358    iBase_TagHandle this_tag, tmp_handle;
359    std::string tag_name("tag_info tag"), tmp_name;
360    FBiGeom_createTag(geom, &tag_name[0], 4, iBase_BYTES, &this_tag, &err,
361          tag_name.length());
362    CHECK( "ERROR : can not create a tag." );
363 
364    // get information on the tag
365 
366    char name_buffer[256];
367    FBiGeom_getTagName(geom, this_tag, name_buffer, &err, sizeof(name_buffer));
368    CHECK( "ERROR : Couldn't get tag name." );
369    if (tag_name != name_buffer) {
370       std::cerr << "ERROR: getTagName returned '" << name_buffer
371             << "' for tag created as '" << tag_name << "'" << std::endl;
372       return false;
373    }
374 
375    FBiGeom_getTagHandle(geom, &tag_name[0], &tmp_handle, &err, tag_name.length());
376    CHECK( "ERROR : Couldn't get tag handle." );
377    if (tmp_handle != this_tag) {
378       std::cerr << "ERROR: getTagHandle didn't return consistent result."
379             << std::endl;
380       return false;
381    }
382 
383    int tag_size;
384    FBiGeom_getTagSizeBytes(geom, this_tag, &tag_size, &err);
385    CHECK( "ERROR : Couldn't get tag size." );
386    if (tag_size != 4) {
387       std::cerr << "ERROR: getTagSizeBytes: expected 4, got " << tag_size
388             << std::endl;
389       return false;
390    }
391 
392    FBiGeom_getTagSizeValues(geom, this_tag, &tag_size, &err);
393    CHECK( "ERROR : Couldn't get tag size." );
394    if (tag_size != 4) {
395       std::cerr << "ERROR: getTagSizeValues: expected 4, got " << tag_size
396             << std::endl;
397       return false;
398    }
399 
400    int tag_type;
401    FBiGeom_getTagType(geom, this_tag, &tag_type, &err);
402    CHECK( "ERROR : Couldn't get tag type." );
403    if (tag_type != iBase_BYTES) {
404       std::cerr << "ERROR: getTagType: expected " << iBase_BYTES << ", got "
405             << tag_type << std::endl;
406       return false;
407    }
408 
409    FBiGeom_destroyTag(geom, this_tag, true, &err);
410    CHECK( "ERROR : Couldn't delete a tag." );
411 
412    // print information about all the tags in the model
413 
414    std::set<iBase_TagHandle> tags;
415    SimpleArray<iBase_EntityHandle> entities;
416    FBiGeom_getEntities(geom, root_set, iBase_ALL_TYPES, ARRAY_INOUT(entities), &err );
417    CHECK( "getEntities( ..., iBase_ALL_TYPES, ... ) failed." );
418    for (int i = 0; i < entities.size(); ++i) {
419       SimpleArray<iBase_TagHandle> tag_arr;
420       FBiGeom_getAllTags( geom, entities[i], ARRAY_INOUT(tag_arr), &err);
421       CHECK( "getAllTags failed." );
422       std::copy( tag_arr.begin(), tag_arr.end(), std::inserter( tags, tags.begin() ) );
423    }
424 
425    std::cout << "Tags defined on model: ";
426    bool first = true;
427    for (std::set<iBase_TagHandle>::iterator sit = tags.begin(); sit != tags.end(); ++sit) {
428       FBiGeom_getTagName( geom, *sit, name_buffer, &err, sizeof(name_buffer) );
429       name_buffer[sizeof(name_buffer)-1] = '\0'; // mnake sure of NUL termination
430       CHECK( "getTagName failed." );
431 
432       if (!first) std::cout << ", ";
433       std::cout << name_buffer;
434       first = false;
435    }
436    if (first) std::cout << "<none>";
437    std::cout << std::endl;
438 
439    return true;
440 }
441 
tag_get_set_test(FBiGeom_Instance geom)442 bool tag_get_set_test(FBiGeom_Instance geom) {
443    int err;
444 
445    // create an arbitrary tag, size 4
446    iBase_TagHandle this_tag;
447    std::string tag_name("tag_get_set tag");
448    FBiGeom_createTag(geom, &tag_name[0], sizeof(int), iBase_BYTES, &this_tag,
449          &err, tag_name.length());
450    CHECK( "ERROR : can not create a tag for get_set test." );
451 
452    iBase_EntitySetHandle root_set;
453    FBiGeom_getRootSet(geom, &root_set, &err);
454    CHECK( "ERROR : getRootSet failed!" );
455 
456    // set this tag to an integer on each entity; keep track of total sum
457    int sum = 0, num = 0, dim;
458    for (dim = 0; dim <= 3; dim++) {
459       SimpleArray<iBase_EntityHandle> gentity_handles;
460       FBiGeom_getEntities(geom, root_set, dim, ARRAY_INOUT( gentity_handles ), &err );
461       int num_ents = gentity_handles.size();
462       std::vector<int> tag_vals( num_ents );
463       for (int i = 0; i < num_ents; ++i) {
464          tag_vals[i] = num;
465          sum += num;
466          ++num;
467       }
468 
469       FBiGeom_setArrData( geom, ARRAY_IN( gentity_handles ),
470             this_tag,
471             (char*)&tag_vals[0], tag_vals.size()*sizeof(int),
472             &err );
473       CHECK( "ERROR : can't set tag on entities" );
474    }
475 
476    // check tag values for entities now
477    int get_sum = 0;
478    for (dim = 0; dim <= 3; dim++) {
479       SimpleArray<iBase_EntityHandle> gentity_handles;
480       FBiGeom_getEntities( geom, root_set, dim, ARRAY_INOUT( gentity_handles ), &err );
481       int num_ents = gentity_handles.size();
482 
483       SimpleArray<char> tag_vals;
484       FBiGeom_getArrData( geom, ARRAY_IN( gentity_handles ), this_tag,
485           (void**)tag_vals.ptr(), &tag_vals.capacity(), &tag_vals.size(), &err );
486       CHECK( "ERROR : can't get tag on entities" );
487 
488       int* tag_ptr = (int*)(&tag_vals[0]);
489       for (int i = 0; i < num_ents; ++i)
490       get_sum += tag_ptr[i];
491    }
492 
493    if (get_sum != sum) {
494       std::cerr << "ERROR: getData didn't return consistent results." << std::endl;
495       return false;
496    }
497 
498    FBiGeom_destroyTag( geom, this_tag, true, &err );
499    CHECK( "ERROR : couldn't delete tag." );
500 
501    return true;
502 }
503 
504 /*!
505  @test
506  TSTT gentity sets test (just implemented parts for now)
507  @li Check gentity sets
508  */
gentityset_test(FBiGeom_Instance geom,bool,bool)509 bool gentityset_test(FBiGeom_Instance geom, bool /*multiset*/, bool /*ordered*/) {
510    int num_type = 4;
511    iBase_EntitySetHandle ges_array[4];
512    int number_array[4];
513    //int num_all_gentities_super = 0;
514    int ent_type = iBase_VERTEX;
515 
516    int err;
517    iBase_EntitySetHandle root_set;
518    FBiGeom_getRootSet(geom, &root_set, &err);
519    CHECK( "ERROR : getRootSet failed!" );
520 
521    // get the number of sets in the whole model
522    int all_sets = 0;
523    FBiGeom_getNumEntSets(geom, root_set, 0, &all_sets, &err);
524    CHECK( "Problem getting the number of all gentity sets in whole model." );
525 
526    // add gentities to entitysets by type
527    for (; ent_type < num_type; ent_type++) {
528       // initialize the entityset
529       FBiGeom_createEntSet(geom, true, &ges_array[ent_type], &err);
530       CHECK( "Problem creating entityset." );
531 
532       // get entities by type in total "mesh"
533       SimpleArray<iBase_EntityHandle> gentities;
534       FBiGeom_getEntities(geom, root_set, ent_type, ARRAY_INOUT(gentities), &err );
535       CHECK( "Failed to get gentities by type in gentityset_test." );
536 
537       // add gentities into gentity set
538       FBiGeom_addEntArrToSet( geom, ARRAY_IN( gentities ), ges_array[ent_type], &err );
539       CHECK( "Failed to add gentities in entityset_test." );
540 
541       // Check to make sure entity set really has correct number of entities in it
542       FBiGeom_getNumOfType( geom, ges_array[ent_type], ent_type, &number_array[ent_type], &err );
543       CHECK( "Failed to get number of gentities by type in entityset_test." );
544 
545       // compare the number of entities by type
546       int num_type_gentity = gentities.size();
547 
548       if (number_array[ent_type] != num_type_gentity)
549       {
550          std::cerr << "Number of gentities by type is not correct"
551          << std::endl;
552          return false;
553       }
554 
555       // add to number of all entities in super set
556       //num_all_gentities_super += num_type_gentity;
557    }
558 
559    // make a super set having all entitysets
560    iBase_EntitySetHandle super_set;
561    FBiGeom_createEntSet( geom, true, &super_set, &err );
562    CHECK( "Failed to create a super set in gentityset_test." );
563 
564    for (int i = 0; i < num_type; i++) {
565       FBiGeom_addEntSet( geom, ges_array[i], super_set, &err );
566       CHECK( "Failed to create a super set in gentityset_test." );
567    }
568 
569    //----------TEST BOOLEAN OPERATIONS----------------//
570 
571    iBase_EntitySetHandle temp_ges1;
572    FBiGeom_createEntSet( geom, true, &temp_ges1, &err );
573    CHECK( "Failed to create a super set in gentityset_test." );
574 
575    // Subtract
576    // add all EDGEs and FACEs to temp_es1
577    // get all EDGE entities
578    SimpleArray<iBase_EntityHandle> gedges, gfaces, temp_gentities1;
579    FBiGeom_getEntities( geom, ges_array[iBase_EDGE], iBase_EDGE, ARRAY_INOUT(gedges), &err );
580    CHECK( "Failed to get gedge gentities in gentityset_test." );
581 
582    // add EDGEs to ges1
583    FBiGeom_addEntArrToSet( geom, ARRAY_IN(gedges), temp_ges1, &err );
584    CHECK( "Failed to add gedge gentities in gentityset_test." );
585 
586    // get all FACE gentities
587    FBiGeom_getEntities( geom, ges_array[iBase_FACE], iBase_FACE, ARRAY_INOUT(gfaces), &err );
588    CHECK( "Failed to get gface gentities in gentityset_test." );
589 
590    // add FACEs to es1
591    FBiGeom_addEntArrToSet( geom, ARRAY_IN(gfaces), temp_ges1, &err );
592    CHECK( "Failed to add gface gentities in gentityset_test." );
593 
594    // subtract EDGEs
595    FBiGeom_subtract( geom, temp_ges1, ges_array[iBase_EDGE], &temp_ges1, &err );
596    CHECK( "Failed to subtract gentitysets in gentityset_test." );
597 
598    FBiGeom_getEntities( geom, temp_ges1, iBase_FACE, ARRAY_INOUT(temp_gentities1), &err );
599    CHECK( "Failed to get gface gentities in gentityset_test." );
600 
601    if (gfaces.size() != temp_gentities1.size()) {
602       std::cerr << "Number of entitysets after subtraction not correct \
603              in gentityset_test." << std::endl;
604       return false;
605    }
606 
607    // check there's nothing but gfaces in temp_ges1
608    int num_gents;
609    FBiGeom_getNumOfType( geom, temp_ges1, iBase_EDGE, &num_gents, &err );
610    CHECK( "Failed to get dimensions of gentities in gentityset_test." );
611    if (0 != num_gents) {
612       std::cerr << "Subtraction failed to remove all edges" << std::endl;
613       return false;
614    }
615 
616    //------------Intersect------------
617    //
618 
619    // clean out the temp_ges1
620    FBiGeom_rmvEntArrFromSet( geom, ARRAY_IN(gfaces), temp_ges1, &err );
621    CHECK( "Failed to remove gface gentities in gentityset_test." );
622 
623    // check if it is really cleaned out
624    FBiGeom_getNumOfType( geom, temp_ges1, iBase_FACE, &num_gents, &err );
625    CHECK( "Failed to get number of gentities by type in gentityset_test." );
626 
627    if (num_gents != 0) {
628       std::cerr << "failed to remove correctly." << std::endl;
629       return false;
630    }
631 
632    // add EDGEs to temp ges1
633    FBiGeom_addEntArrToSet( geom, ARRAY_IN(gedges), temp_ges1, &err );
634    CHECK( "Failed to add gedge gentities in gentityset_test." );
635 
636    // add FACEs to temp ges1
637    FBiGeom_addEntArrToSet( geom, ARRAY_IN(gfaces), temp_ges1, &err );
638    CHECK( "Failed to add gface gentities in gentityset_test." );
639 
640    // intersect temp_ges1 with gedges set
641    // temp_ges1 entityset is altered
642    FBiGeom_intersect( geom, temp_ges1, ges_array[iBase_EDGE], &temp_ges1, &err );
643    CHECK( "Failed to intersect in gentityset_test." );
644 
645    // try to get FACEs, but there should be nothing but EDGE
646    FBiGeom_getNumOfType( geom, temp_ges1, iBase_FACE, &num_gents, &err );
647    CHECK( "Failed to get gface gentities in gentityset_test." );
648 
649    if (num_gents != 0) {
650       std::cerr << "wrong number of gfaces." << std::endl;
651       return false;
652    }
653 
654    //-------------Unite--------------
655 
656    // get all regions
657    iBase_EntitySetHandle temp_ges2;
658    SimpleArray<iBase_EntityHandle> gregions;
659 
660    FBiGeom_createEntSet( geom, true, &temp_ges2, &err );
661    CHECK( "Failed to create a temp gentityset in gentityset_test." );
662 
663    FBiGeom_getEntities( geom, ges_array[iBase_REGION], iBase_REGION, ARRAY_INOUT(gregions), &err );
664    CHECK( "Failed to get gregion gentities in gentityset_test." );
665 
666    // add REGIONs to temp es2
667    FBiGeom_addEntArrToSet( geom, ARRAY_IN(gregions), temp_ges2, &err );
668    CHECK( "Failed to add gregion gentities in gentityset_test." );
669 
670    // unite temp_ges1 and temp_ges2
671    // temp_ges1 gentityset is altered
672    FBiGeom_unite( geom, temp_ges1, temp_ges2, &temp_ges1, &err );
673    CHECK( "Failed to unite in gentityset_test." );
674 
675    // perform the check
676    FBiGeom_getNumOfType( geom, temp_ges1, iBase_REGION, &num_gents, &err );
677    CHECK( "Failed to get number of gregion gentities by type in gentityset_test." );
678 
679    if (num_gents != number_array[iBase_REGION]) {
680       std::cerr << "different number of gregions in gentityset_test." << std::endl;
681       return false;
682    }
683 
684    //--------Test parent/child stuff in entiysets-----------
685 
686    // Add 2 sets as children to another
687    iBase_EntitySetHandle parent_child;
688    FBiGeom_createEntSet( geom, true, &parent_child, &err );
689    CHECK( "Problem creating gentityset in gentityset_test." );
690 
691    FBiGeom_addPrntChld( geom, ges_array[iBase_VERTEX], parent_child, &err );
692    CHECK( "Problem add parent in gentityset_test." );
693 
694    // check if parent is really added
695    SimpleArray<iBase_EntitySetHandle> parents;
696    FBiGeom_getPrnts( geom, parent_child, 1, ARRAY_INOUT(parents), &err );
697    CHECK( "Problem getting parents in gentityset_test." );
698 
699    if (parents.size() != 1) {
700       std::cerr << "number of parents is not correct in gentityset_test."
701       << std::endl;
702       return false;
703    }
704 
705    // add parent and child
706    //sidl::array<void*> parent_child_array = sidl::array<void*>::create1d(1);
707    //int num_parent_child_array;
708    //sidl::array<void*> temp_gedge_array = sidl::array<void*>::create1d(1);
709    //int num_temp_gedge_array;
710    //parent_child_array.set(0, parent_child);
711    //temp_gedge_array.set(0, ges_array[TSTTG::EntityType_EDGE]);
712    FBiGeom_addPrntChld( geom, ges_array[iBase_EDGE], parent_child, &err );
713    CHECK( "Problem adding parent and child in gentityset_test." );
714 
715    //sidl::array<void*> temp_gface_array = sidl::array<void*>::create1d(1);
716    //int num_temp_gface_array;
717    //temp_gface_array.set(0, ges_array[TSTTG::EntityType_FACE]);
718    FBiGeom_addPrntChld( geom, parent_child, ges_array[iBase_FACE], &err );
719    CHECK( "Problem adding parent and child in gentityset_test." );
720 
721    // add child
722    FBiGeom_addPrntChld( geom, parent_child, ges_array[iBase_REGION], &err );
723    CHECK( "Problem adding child in gentityset_test." );
724 
725    // get the number of parent gentitysets
726    num_gents = -1;
727    FBiGeom_getNumPrnt( geom, parent_child, 1, &num_gents, &err );
728    CHECK( "Problem getting number of parents in gentityset_test." );
729 
730    if (num_gents != 2) {
731       std::cerr << "number of parents is not correct in gentityset_test."
732       << std::endl;
733       return false;
734    }
735 
736    // get the number of child gentitysets
737    num_gents = -1;
738    FBiGeom_getNumChld( geom, parent_child, 1, &num_gents, &err );
739    CHECK( "Problem getting number of children in gentityset_test." );
740 
741    if (num_gents != 2) {
742       std::cerr << "number of children is not correct in gentityset_test."
743       << std::endl;
744       return false;
745    }
746 
747    SimpleArray<iBase_EntitySetHandle> children;
748    FBiGeom_getChldn( geom, parent_child, 1, ARRAY_INOUT(children), &err );
749    CHECK( "Problem getting children in gentityset_test." );
750 
751    if (children.size() != 2) {
752       std::cerr << "number of children is not correct in gentityset_test."
753       << std::endl;
754       return false;
755    }
756 
757    // remove children
758    FBiGeom_rmvPrntChld( geom, parent_child, ges_array[iBase_FACE], &err );
759    CHECK( "Problem removing parent child in gentityset_test." );
760 
761    // get the number of child gentitysets
762    FBiGeom_getNumChld( geom, parent_child, 1, &num_gents, &err );
763    CHECK( "Problem getting number of children in gentityset_test." );
764 
765    if (num_gents != 1) {
766       std::cerr << "number of children is not correct in gentityset_test."
767       << std::endl;
768       return false;
769    }
770 
771    // parent_child and ges_array[TSTTG::EntityType_EDGE] should be related
772    int result = 0;
773    FBiGeom_isChildOf( geom, ges_array[iBase_EDGE], parent_child, &result, &err );
774    CHECK( "Problem checking relation in gentityset_test." );
775    if (!result) {
776       std::cerr << "parent_child and ges_array[TSTTG::EntityType_EDGE] should be related" << std::endl;
777       return false;
778    }
779 
780    // ges_array[TSTTG::EntityType_FACE] and ges_array[TSTTG::REGION] are not related
781    result = 2;
782    FBiGeom_isChildOf( geom, ges_array[iBase_FACE], ges_array[iBase_REGION], &result, &err );
783    if (result) {
784       std::cerr << "ges_array[TSTTG::REGION] and ges_array[TSTTG::EntityType_FACE] should not be related" << std::endl;
785       return false;
786    }
787 
788    //--------test modify and query functions-----------------------------
789 
790    // check the number of gentity sets in whole mesh
791    SimpleArray<iBase_EntitySetHandle> gentity_sets;
792    FBiGeom_getEntSets( geom, root_set, 1, ARRAY_INOUT( gentity_sets ), &err );
793    CHECK( "Problem to get all gentity sets in mesh." );
794 
795    if (gentity_sets.size() != all_sets + 8) {
796       std::cerr << "the number of gentity sets in whole mesh should be 8 times of num_iter."
797       << std::endl;
798       return false;
799    }
800 
801    // get all gentity sets in super set
802    SimpleArray<iBase_EntitySetHandle> ges_array1;
803    FBiGeom_getEntSets( geom, super_set, 1, ARRAY_INOUT( ges_array1 ), &err );
804    CHECK( "Problem to get gentity sets in super set." );
805 
806    // get the number of gentity sets in super set
807    int num_super;
808    FBiGeom_getNumEntSets( geom, super_set, 1, &num_super, &err );
809    CHECK( "Problem to get the number of all gentity sets in super set." );
810 
811    // the number of gentity sets in super set should be same
812    if (num_super != ges_array1.size()) {
813       std::cerr << "the number of gentity sets in super set should be same." << std::endl;
814       return false;
815    }
816 
817    // get all entities in super set
818    SimpleArray<iBase_EntitySetHandle> all_gentities;
819    FBiGeom_getEntSets( geom, super_set, 1, ARRAY_INOUT( all_gentities ), &err );
820    CHECK( "Problem to get all gentities in super set." );
821 
822    // compare the number of all gentities in super set
823    // HJK : num_hops is not implemented
824    //if (num_all_gentities_super != ARRAY_SIZE(all_gentities)) {
825    //std::cerr << "number of all gentities in super set should be same." << std::endl;
826    //success = false;
827    //}
828 
829    // test add, remove and get all entitiy sets using super set
830    // check GetAllGentitysets works recursively and dosen't return
831    // multi sets
832    for (int k = 0; k < num_super; k++) {
833       // add gentity sets of super set to each gentity set of super set
834       // make multiple child super sets
835       iBase_EntitySetHandle ges_k = ges_array1[k];
836 
837       for (int a = 0; a < ges_array1.size(); a++) {
838          FBiGeom_addEntSet( geom, ges_array1[a], ges_k, &err );
839          CHECK( "Problem to add entity set." );
840       }
841 
842       // add super set to each entity set
843       //    sidl::array<GentitysetHandle> superset_array
844       //= sidl::array<GentitysetHandle>::create1d(1);
845       //superset_array.set(0, super_set);
846       //int num_superset_array;
847 
848       FBiGeom_addEntSet( geom, super_set, ges_k, &err );
849       CHECK( "Problem to add super set to gentitysets." );
850 
851       // add one gentity sets multiple times
852       // HJK: ??? how to deal this case?
853       //sidl::array<GentitysetHandle> temp_array1
854       //= sidl::array<GentitysetHandle>::create1d(1);
855       //int num_temp_array1;
856       //temp_array1.set(0, temp_ges1);
857 
858       //for (int l = 0; l < 3; l++) {
859       FBiGeom_addEntSet( geom, temp_ges1, ges_k, &err );
860       CHECK( "Problem to add temp set to gentitysets." );
861       //}
862    }
863 
864    return true;
865 }
866 
867 /*!
868  @test
869  TSTTG topology adjacencies Test
870  @li Check topology information
871  @li Check adjacency
872  */
873 // make each topological entity vectors, check their topology
874 // types, get interior and exterior faces of model
topology_adjacencies_test(FBiGeom_Instance geom)875 bool topology_adjacencies_test(FBiGeom_Instance geom) {
876    int i, err;
877    iBase_EntitySetHandle root_set;
878    FBiGeom_getRootSet(geom, &root_set, &err);
879    CHECK( "ERROR : getRootSet failed!" );
880 
881    int top = iBase_VERTEX;
882    int num_test_top = iBase_ALL_TYPES;
883    std::vector<std::vector<iBase_EntityHandle> > gentity_vectors(num_test_top);
884 
885    // fill the vectors of each topology entities
886    // like lines vector, polygon vector, triangle vector,
887    // quadrilateral, polyhedrron, tet, hex, prism, pyramid,
888    // septahedron vectors
889    for (i = top; i < num_test_top; i++) {
890       SimpleArray<iBase_EntityHandle> gentities;
891       FBiGeom_getEntities(geom, root_set, i, ARRAY_INOUT( gentities ), &err );
892       CHECK("Failed to get gentities in adjacencies_test.");
893 
894       gentity_vectors[i].resize( gentities.size() );
895       std::copy( gentities.begin(), gentities.end(), gentity_vectors[i].begin() );
896    }
897 
898    // check number of entities for each topology
899    for (i = top; i < num_test_top; i++) {
900       int num_tops = 0;
901       FBiGeom_getNumOfType( geom, root_set, i, &num_tops, &err );
902       CHECK( "Failed to get number of gentities in adjacencies_test." );
903 
904       if (static_cast<int>(gentity_vectors[i].size()) != num_tops) {
905          std::cerr << "Number of gentities doesn't agree with number returned for dimension "
906          << i << std::endl;
907          return false;
908       }
909    }
910 
911    // check adjacencies in both directions
912    std::vector<iBase_EntityHandle>::iterator vit;
913    for (i = iBase_REGION; i >= iBase_VERTEX; i--) {
914       for (vit = gentity_vectors[i].begin(); vit != gentity_vectors[i].end(); ++vit) {
915          iBase_EntityHandle this_gent = *vit;
916 
917          // check downward adjacencies
918          for (int j = iBase_VERTEX; j < i; j++) {
919 
920             SimpleArray<iBase_EntityHandle> lower_ents;
921             FBiGeom_getEntAdj( geom, this_gent, j, ARRAY_INOUT(lower_ents), &err );
922             CHECK( "Bi-directional adjacencies test failed." );
923 
924             // for each of them, make sure they are adjacent to the upward ones
925             int num_lower = lower_ents.size();
926             for (int k = 0; k < num_lower; k++) {
927                SimpleArray<iBase_EntityHandle> upper_ents;
928                FBiGeom_getEntAdj( geom, lower_ents[k], i, ARRAY_INOUT(upper_ents), &err );
929                CHECK( "Bi-directional adjacencies test failed." );
930                if (std::find(upper_ents.begin(),upper_ents.end(), this_gent) ==
931                upper_ents.end()) {
932                   std::cerr << "Didn't find lower-upper adjacency which was supposed to be there, dims = "
933                   << i << ", " << j << std::endl;
934                   return false;
935                }
936             }
937          }
938       }
939    }
940 
941    return true;
942 }
943 
944 /*!
945  @test
946  FBiGeom_MOAB topology adjacencies Test
947  @li Check topology information
948  @li Check adjacency
949  */
950 // make each topological entity vectors, check their topology
951 // types, get interior and exterior faces of model
geometry_evaluation_test(FBiGeom_Instance geom)952 bool geometry_evaluation_test(FBiGeom_Instance geom) {
953    int i, err;
954    iBase_EntitySetHandle root_set;
955    FBiGeom_getRootSet(geom, &root_set, &err);
956    CHECK( "ERROR : getRootSet failed!" );
957 
958    int top = iBase_VERTEX;
959    int num_test_top = iBase_ALL_TYPES;
960    std::vector<std::vector<iBase_EntityHandle> > gentity_vectors(num_test_top);
961 
962    // fill the vectors of each topology entities
963    // like lines vector, polygon vector, triangle vector,
964    // quadrilateral, polyhedrron, tet, hex, prism, pyramid,
965    // septahedron vectors
966    for (i = top; i < num_test_top; i++) {
967       SimpleArray<iBase_EntityHandle> gentities;
968       FBiGeom_getEntities(geom, root_set, i, ARRAY_INOUT( gentities ), &err );
969       CHECK("Failed to get gentities in adjacencies_test.");
970 
971       gentity_vectors[i].resize( gentities.size() );
972       std::copy( gentities.begin(), gentities.end(), gentity_vectors[i].begin() );
973    }
974 
975    // check adjacencies in both directions
976    double min[3], max[3], on[3];
977    double near[3] = {.0, .0, .0};
978    std::vector<iBase_EntityHandle>::iterator vit;
979    for (i = iBase_REGION; i >= iBase_VERTEX; i--) {
980       if (i != iBase_EDGE) {
981          for (vit = gentity_vectors[i].begin(); vit != gentity_vectors[i].end(); ++vit) {
982             iBase_EntityHandle this_gent = *vit;
983             FBiGeom_getEntBoundBox(geom, this_gent, &min[0], &min[1], &min[2],
984             &max[0], &max[1], &max[2], &err);
985             CHECK("Failed to get bounding box of entity.");
986 
987             for (int j=0; j<3; j++)
988             near[j] = (min[j]+max[j])/2;
989             FBiGeom_getEntClosestPt(geom, this_gent, near[0], near[1], near[2],
990             &on[0], &on[1], &on[2], &err);
991             CHECK("Failed to get closest point on entity.");
992             std::cout<<" entity of type " << i << " closest point to \n  " <<
993             near[0] << " " << near[1] << " " << near[2] << "\n  is " << on[0] << " " << on[1] << " " << on[2] << "\n";
994          }
995       }
996    }
997 
998    return true;
999 }
1000 //
1001 //  test normals evaluations on the surface only
normals_test(FBiGeom_Instance geom)1002 bool normals_test(FBiGeom_Instance geom) {
1003    int i, err;
1004    iBase_EntitySetHandle root_set;
1005    FBiGeom_getRootSet(geom, &root_set, &err);
1006    CHECK( "ERROR : getRootSet failed!" );
1007 
1008    int top = iBase_VERTEX;
1009    int num_test_top = iBase_ALL_TYPES;
1010    std::vector<std::vector<iBase_EntityHandle> > gentity_vectors(num_test_top);
1011 
1012    // fill the vectors of each topology entities
1013    // like lines vector, polygon vector, triangle vector,
1014    // quadrilateral, polyhedrron, tet, hex, prism, pyramid,
1015    // septahedron vectors
1016    for (i = top; i < num_test_top; i++) {
1017       SimpleArray<iBase_EntityHandle> gentities;
1018       FBiGeom_getEntities(geom, root_set, i, ARRAY_INOUT( gentities ), &err );
1019       CHECK("Failed to get gentities in adjacencies_test.");
1020 
1021       gentity_vectors[i].resize( gentities.size() );
1022       std::copy( gentities.begin(), gentities.end(), gentity_vectors[i].begin() );
1023    }
1024 
1025    // check adjacencies in both directions
1026    double min[3], max[3];
1027    double normal[3] = {.0, .0, .0};
1028    std::vector<iBase_EntityHandle>::iterator vit;
1029    for (i = iBase_REGION; i > iBase_EDGE; i--) {
1030       for (vit = gentity_vectors[i].begin(); vit != gentity_vectors[i].end(); ++vit) {
1031          iBase_EntityHandle this_gent = *vit;
1032          FBiGeom_getEntBoundBox(geom, this_gent, &min[0], &min[1], &min[2],
1033          &max[0], &max[1], &max[2], &err);
1034          CHECK("Failed to get bounding box of entity.");
1035 
1036          FBiGeom_getEntNrmlXYZ( geom, this_gent,
1037          (max[0]+min[0])/2,
1038          (max[1]+min[1])/2,
1039          (max[2]+min[2])/2,
1040          &normal[0],
1041          &normal[1],
1042          &normal[2],
1043          &err );
1044 
1045          CHECK("Failed to get normal to the closest point.");
1046          std::cout<<" entity of type " << i << " closest normal to center:\n  " <<
1047          normal[0] << " " << normal[1] << " " << normal[2] << "\n";
1048       }
1049    }
1050 
1051    return true;
1052 }
1053 
1054 //  test normals evaluations on the surface only
ray_test(FBiGeom_Instance geom)1055 bool ray_test(FBiGeom_Instance geom) {
1056    int  err;
1057    iBase_EntitySetHandle root_set;
1058    FBiGeom_getRootSet(geom, &root_set, &err);
1059    CHECK( "ERROR : getRootSet failed!" );
1060 
1061    int top = iBase_FACE;
1062 
1063    SimpleArray<iBase_EntityHandle> faces;
1064    FBiGeom_getEntities(geom, root_set, top, ARRAY_INOUT( faces ), &err );
1065    CHECK("Failed to get gentities in adjacencies_test.");
1066 
1067    // check only the first face
1068 
1069    // check adjacencies in both directions
1070    double min[3], max[3];
1071 
1072    iBase_EntityHandle first_face = faces[0];
1073 
1074    FBiGeom_getEntBoundBox(geom, first_face, &min[0], &min[1], &min[2],
1075    &max[0], &max[1], &max[2], &err);
1076    CHECK("Failed to get bounding box of entity.");
1077 
1078    // assume that the ray shot from the bottom of the box (middle) is a pretty good candidate
1079    // in z direction
1080    double x = (min[0]+max[0])/2, y = (min[1]+max[1])/2, z = min[2];
1081    SimpleArray<iBase_EntityHandle> intersect_entity_handles;
1082    SimpleArray<double> intersect_coords;
1083    SimpleArray<double> param_coords;
1084    FBiGeom_getPntRayIntsct( geom,  x,  y,  z, // shot from
1085                                        0., 0., 1., // direction
1086                                        ARRAY_INOUT(intersect_entity_handles),
1087                                        iBase_INTERLEAVED,
1088                                        ARRAY_INOUT(intersect_coords),
1089                                        ARRAY_INOUT(param_coords),
1090                                        &err );
1091 
1092    CHECK("Failed to find ray intersections points ");
1093    for(int i=0; i<intersect_entity_handles.size(); i++)
1094    {
1095       int j;
1096       FBiGeom_getEntType( geom, intersect_entity_handles[i],
1097                                &j,&err);
1098       CHECK("Failed to get type of entity.");
1099 
1100       std::cout<<" entity of type " << j << " n: " << intersect_entity_handles[i]<< "\n"<<
1101             intersect_coords[3*i] << " " << intersect_coords[3*i+1] << " "
1102             << intersect_coords[3*i+2] << "\n" <<
1103             " distance: " << param_coords[i] << "\n";
1104    }
1105 
1106    return true;
1107 }
1108 
1109 /*!
1110  @test
1111  TSTTG construct Test
1112  @li Check construction of geometry
1113  */
construct_test(FBiGeom_Instance geom)1114 bool construct_test(FBiGeom_Instance geom) {
1115    int err;
1116    iBase_EntityHandle new_body = 0;
1117 
1118    // construct a cylinder, sweep it about an axis, and delete the result
1119    iBase_EntityHandle cyl = 0;
1120    FBiGeom_createCylinder(geom, 1.0, 1.0, 0.0, &cyl, &err);
1121    // Is the minor radius really supposed to be zero??? - JK
1122    CHECK( "Creating cylinder failed." );
1123 
1124    // move it onto the y axis
1125    FBiGeom_moveEnt(geom, cyl, 0.0, 1.0, -0.5, &err);
1126    CHECK( "Problems moving surface." );
1127 
1128    // get the surface with max z
1129    iBase_EntityHandle max_surf = 0;
1130    SimpleArray<iBase_EntityHandle> surfs;
1131    FBiGeom_getEntAdj(geom, cyl, iBase_FACE, ARRAY_INOUT(surfs), &err );
1132    CHECK( "Problems getting max surf for rotation." );
1133 
1134    SimpleArray<double> max_corn, min_corn;
1135    FBiGeom_getArrBoundBox( geom, ARRAY_IN(surfs), iBase_INTERLEAVED,
1136    ARRAY_INOUT( min_corn ),
1137    ARRAY_INOUT( max_corn ),
1138    &err );
1139    CHECK( "Problems getting max surf for rotation." );
1140    double dtol = 1.0e-6;
1141    for (int i = 0; i < surfs.size(); ++i) {
1142       if ((max_corn[3*i+2]) <= dtol && (max_corn[3*i+2]) >= -dtol &&
1143       (min_corn[3*i+2]) <= dtol && (min_corn[3*i+2]) >= -dtol) {
1144          max_surf = surfs[i];
1145          break;
1146       }
1147    }
1148 
1149    if (0 == max_surf) {
1150       std::cerr << "Couldn't find max surf for rotation." << std::endl;
1151       return false;
1152    }
1153 
1154    // sweep it around the x axis
1155    FBiGeom_moveEnt( geom, cyl, 0.0, 1.0, 0.0, &err );
1156    CHECK( "Problems moving surface." );
1157 
1158    FBiGeom_sweepEntAboutAxis( geom, max_surf, 360.0, 1.0, 0.0, 0.0, &new_body, &err );
1159    CHECK( "Problems sweeping surface about axis." );
1160 
1161    // now delete
1162    FBiGeom_deleteEnt( geom, new_body, &err );
1163    CHECK( "Problems deleting cylinder or swept surface body." );
1164 
1165    // if we got here, we were successful
1166    return true;
1167 }
1168 
compare_box(const double * expected_min,const double * expected_max,const double * actual_min,const double * actual_max)1169 static bool compare_box(const double* expected_min, const double* expected_max,
1170       const double* actual_min, const double* actual_max) {
1171    bool same = true;
1172    double dtol = 1.0e-6;
1173 
1174    for (int i = 0; i < 3; ++i) {
1175       if (expected_min[i] < actual_min[i] - dtol || expected_min[i] * 10
1176             > actual_min[i] || expected_max[i] > actual_max[i] + dtol
1177             || expected_max[i] * 10 < actual_max[i])
1178          same = false;
1179    }
1180    return same;
1181 }
1182 
primitives_test(FBiGeom_Instance geom)1183 bool primitives_test(FBiGeom_Instance geom) {
1184    int err;
1185    SimpleArray<iBase_EntityHandle> prims(3);
1186    iBase_EntityHandle prim;
1187 
1188    FBiGeom_createBrick(geom, 1.0, 2.0, 3.0, &prim, &err);
1189    CHECK( "createBrick failed." );
1190    prims[0] = prim;
1191 
1192    FBiGeom_createCylinder(geom, 1.0, 4.0, 2.0, &prim, &err);
1193    CHECK( "createCylinder failed." );
1194    prims[1] = prim;
1195 
1196    FBiGeom_createTorus(geom, 2.0, 1.0, &prim, &err);
1197    CHECK( "createTorus failed." );
1198    prims[2] = prim;
1199 
1200    // verify the bounding boxes for Acis based entities
1201    SimpleArray<double> max_corn, min_corn;
1202    FBiGeom_getArrBoundBox(geom, ARRAY_IN(prims),iBase_INTERLEAVED,  ARRAY_INOUT(min_corn),
1203          ARRAY_INOUT(max_corn), &err );
1204 
1205          double preset_min_corn[] =
1206          // min brick corner xyz
1207          {  -0.5, -1.0, -1.5,
1208             // min cyl corner xyz
1209          -4.0, -2.0, -0.5,
1210          // min torus corner xyz
1211          -3.0, -3.0, -1.0
1212       };
1213 
1214       double preset_max_corn[] =
1215       // max brick corner xyz
1216          {  0.5, 1.0, 1.5,
1217             // max cyl corner xyz
1218          4.0, 2.0, 0.5,
1219          // max torus corner xyz
1220          3.0, 3.0, 1.0
1221       };
1222 
1223       if (!compare_box( preset_min_corn, preset_max_corn,
1224                   &min_corn[0], &max_corn[0] )) {
1225          std::cerr << "Box check failed for brick" << std::endl;
1226          return false;
1227       }
1228 
1229       if (!compare_box( preset_min_corn+3, preset_max_corn+3,
1230                   &min_corn[3], &max_corn[3] )) {
1231          std::cerr << "Box check failed for cylinder" << std::endl;
1232          return false;
1233       }
1234 
1235       if (!compare_box( preset_min_corn+6, preset_max_corn+6,
1236                   &min_corn[6], &max_corn[6] )) {
1237          std::cerr << "Box check failed for torus" << std::endl;
1238          return false;
1239       }
1240       // must have worked; delete the entities then return
1241          for (int i = 0; i < 3; ++i) {
1242             FBiGeom_deleteEnt( geom, prims[i], &err );
1243             CHECK( "Problems deleting primitive after boolean check." );
1244          }
1245 
1246          return true;
1247       }
1248 
transforms_test(FBiGeom_Instance geom)1249 bool transforms_test(FBiGeom_Instance geom) {
1250    int err;
1251 
1252    // construct a brick
1253    iBase_EntityHandle brick = 0;
1254    FBiGeom_createBrick(geom, 1.0, 2.0, 3.0, &brick, &err);
1255    CHECK( "Problems creating brick for transforms test." );
1256 
1257    // move it, then test bounding box
1258    FBiGeom_moveEnt(geom, brick, 0.5, 1.0, 1.5, &err);
1259    CHECK( "Problems moving brick for transforms test." );
1260 
1261    double bb_min[3], bb_max[3];
1262    FBiGeom_getEntBoundBox(geom, brick, bb_min, bb_min + 1, bb_min + 2, bb_max,
1263          bb_max + 1, bb_max + 2, &err);
1264    CHECK( "Problems getting bounding box after move." );
1265 
1266    double dtol = 1.0e-6;
1267    if ((bb_min[0]) >= dtol || (bb_min[0]) <= -dtol || (bb_min[1]) >= dtol
1268          || (bb_min[1]) <= -dtol || (bb_min[2]) >= dtol || (bb_min[2]) <= -dtol
1269          || (bb_max[0] - 1) >= dtol || 1 - bb_max[0] >= dtol || (bb_max[1] - 2)
1270          >= dtol || 2 - bb_max[1] >= dtol || (bb_max[2] - 3) >= dtol || 3
1271          - bb_max[2] >= dtol) {
1272       std::cerr << "Wrong bounding box after move." << std::endl;
1273       return false;
1274    }
1275 
1276    // now rotate it about +x, then test bounding box
1277    FBiGeom_rotateEnt(geom, brick, 90, 1.0, 0.0, 0.0, &err);
1278    CHECK( "Problems rotating brick for transforms test." );
1279 
1280    FBiGeom_getEntBoundBox(geom, brick, bb_min, bb_min + 1, bb_min + 2, bb_max,
1281          bb_max + 1, bb_max + 2, &err);
1282    CHECK( "Problems getting bounding box after rotate." );
1283 
1284    if ((bb_min[0]) >= dtol || -bb_min[0] >= dtol || (bb_min[1] + 3) >= dtol
1285          || -(bb_min[1] + 3) >= dtol || (bb_min[2]) >= dtol || -(bb_min[2])
1286          >= dtol || (bb_max[0] - 1) >= dtol || 1 - bb_max[0] >= dtol
1287          || (bb_max[1]) >= dtol || -(bb_max[1]) >= dtol || (bb_max[2] - 2)
1288          >= dtol || 2 - bb_max[2] >= dtol) {
1289       std::cerr << "Wrong bounding box after rotate." << std::endl;
1290       return false;
1291    }
1292 
1293    // now reflect through y plane; should recover original bb
1294    FBiGeom_reflectEnt(geom, brick, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, &err);
1295    CHECK( "Problems reflecting brick for transforms test." );
1296 
1297    FBiGeom_getEntBoundBox(geom, brick, bb_min, bb_min + 1, bb_min + 2, bb_max,
1298          bb_max + 1, bb_max + 2, &err);
1299    CHECK( "Problems getting bounding box after reflect." );
1300 
1301    if ((bb_min[0]) >= dtol || -(bb_min[0]) >= dtol || (bb_min[1]) >= dtol
1302          || (bb_min[2]) >= dtol || -(bb_min[1]) >= dtol || -(bb_min[2]) >= dtol
1303          || (bb_max[0] - 1) >= dtol || 1 - bb_max[0] >= dtol || (bb_max[1] - 3)
1304          >= dtol || 3 - bb_max[1] >= dtol || (bb_max[2] - 2) >= dtol || 2
1305          - bb_max[2] >= dtol) {
1306       std::cerr << "Wrong bounding box after reflect." << std::endl;
1307       return false;
1308    }
1309 
1310    // must have worked; delete the entities then return
1311    FBiGeom_deleteEnt(geom, brick, &err);
1312    CHECK( "Problems deleting brick after transforms check." );
1313    return true;
1314 }
1315 
booleans_test(FBiGeom_Instance geom)1316 bool booleans_test(FBiGeom_Instance geom) {
1317    int err;
1318 
1319    // construct a brick size 1, and a cylinder rad 0.25 height 2
1320    iBase_EntityHandle brick = 0, cyl = 0;
1321    FBiGeom_createBrick(geom, 1.0, 0.0, 0.0, &brick, &err);
1322    CHECK( "Problems creating brick for booleans test." );
1323    FBiGeom_createCylinder(geom, 1.0, 0.25, 0.0, &cyl, &err);
1324    CHECK( "Problems creating cylinder for booleans test." );
1325 
1326    // subtract the cylinder from the brick
1327    iBase_EntityHandle subtract_result = 0;
1328    FBiGeom_subtractEnts(geom, brick, cyl, &subtract_result, &err);
1329    CHECK( "Problems subtracting for booleans subtract test." );
1330 
1331    // section the brick
1332    iBase_EntityHandle section_result = 0;
1333    FBiGeom_sectionEnt(geom, subtract_result, 1.0, 0.0, 0.0, 0.25, true,
1334          &section_result, &err);
1335    CHECK( "Problems sectioning for booleans section test." );
1336 
1337    // unite the section result with a new cylinder
1338    FBiGeom_createCylinder(geom, 1.0, 0.25, 0.0, &cyl, &err);
1339    CHECK( "Problems creating cylinder for unite test." );
1340    iBase_EntityHandle unite_results;
1341    iBase_EntityHandle unite_input[] = { section_result, cyl };
1342    FBiGeom_uniteEnts(geom, unite_input, 2, &unite_results, &err);
1343    CHECK( "Problems uniting for booleans unite test." );
1344 
1345    FBiGeom_deleteEnt(geom, unite_results, &err);
1346    CHECK( "Problems deleting for booleans unite test." );
1347    return true;
1348 }
1349 
get_entities(FBiGeom_Instance geom,int entity_type,std::vector<iBase_EntityHandle> & entities_out,iBase_TagHandle id_tag=0,std::vector<int> * ids_out=0)1350 static int get_entities(FBiGeom_Instance geom, int entity_type, std::vector<
1351       iBase_EntityHandle>& entities_out, iBase_TagHandle id_tag = 0,
1352       std::vector<int>* ids_out = 0) {
1353    int err, num;
1354    iBase_EntitySetHandle root;
1355    FBiGeom_getRootSet(geom, &root, &err);
1356    if (iBase_SUCCESS != err)
1357       return err;
1358    FBiGeom_getNumOfType(geom, root, entity_type, &num, &err);
1359    if (iBase_SUCCESS != err)
1360       return err;
1361 
1362    entities_out.resize(num);
1363    int junk1 = entities_out.size(), junk2;
1364    iBase_EntityHandle* junk_ptr = &entities_out[0];
1365    ;
1366    FBiGeom_getEntities(geom, root, entity_type, &junk_ptr, &junk1, &junk2, &err);
1367    if (iBase_SUCCESS != err)
1368       return err;
1369    assert( num == junk1 && num == junk2 );
1370 
1371    if (!ids_out)
1372       return iBase_SUCCESS;
1373 
1374    ids_out->resize(num);
1375    int* int_ptr = &(*ids_out)[0];
1376    FBiGeom_getIntArrData(geom, &entities_out[0], num, id_tag, &int_ptr, &junk1,
1377          &junk2, &err);
1378    if (iBase_SUCCESS != err)
1379       return err;
1380    assert( num == junk1 && num == junk2 );
1381 
1382    return iBase_SUCCESS;
1383 }
1384 
check_firmness(FBiGeom_Instance geom,const std::vector<iBase_EntityHandle> & entities,const std::vector<int> & ids,iBase_TagHandle firmness_tag,const char * expected_value,const char * ent_type_str)1385 static int check_firmness(FBiGeom_Instance geom, const std::vector<
1386       iBase_EntityHandle>& entities, const std::vector<int>& ids,
1387       iBase_TagHandle firmness_tag, const char* expected_value,
1388       const char* ent_type_str) {
1389    const int firmness_size = 4;
1390    std::vector<char> firmness(firmness_size * entities.size());
1391 
1392    char* byte_ptr = &firmness[0];
1393    int err, junk1 = firmness.size(), junk2 = entities.size() * firmness_size;
1394    FBiGeom_getArrData(geom, &entities[0], entities.size(), firmness_tag,
1395          (void**)&byte_ptr, &junk1, &junk2, &err);
1396    if (iBase_SUCCESS != err)
1397       return err;
1398 
1399    bool all_correct = true;
1400    for (unsigned i = 0; i < entities.size(); ++i)
1401       if (std::string(&firmness[firmness_size * i], firmness_size)
1402             != expected_value)
1403          all_correct = false;
1404    if (!all_correct) {
1405       std::cout << "ERROR: Expected \"" << expected_value << "\" firmness "
1406             << "for all " << ent_type_str << "." << std::endl;
1407       std::cout << "ID  Actual  " << std::endl;
1408       for (unsigned i = 0; i < entities.size(); ++i)
1409          std::cout << std::setw(2) << ids[i] << "  " << std::string(
1410                &firmness[firmness_size * i], firmness_size) << std::endl;
1411       return iBase_FAILURE;
1412    }
1413 
1414    return iBase_SUCCESS;
1415 }
1416 
count_num_with_tag(FBiGeom_Instance geom,const std::vector<iBase_EntityHandle> & ents,iBase_TagHandle tag)1417 static int count_num_with_tag(FBiGeom_Instance geom, const std::vector<
1418       iBase_EntityHandle>& ents, iBase_TagHandle tag) {
1419    int err, bytes;
1420    FBiGeom_getTagSizeBytes(geom, tag, &bytes, &err);
1421    if (iBase_SUCCESS != err)
1422       return -1;
1423    std::vector<char> data(bytes);
1424 
1425    int success_count = 0;
1426    for (size_t i = 0; i < ents.size(); ++i) {
1427       char* ptr = &data[0];
1428       int junk1 = bytes, junk2;
1429       FBiGeom_getData(geom, ents[i], tag, (void**)&ptr, &junk1, &junk2, &err);
1430       if (iBase_TAG_NOT_FOUND == err)
1431          continue;
1432       if (iBase_SUCCESS != err)
1433          return -1;
1434       ++success_count;
1435    }
1436 
1437    return success_count;
1438 }
1439 
mesh_size_test(FBiGeom_Instance geom)1440 bool mesh_size_test(FBiGeom_Instance geom) {
1441    const char* filename = STRINGIFY(SRCDIR) "/size.sat";
1442    int err, junk1, junk2;
1443    bool result = true;
1444 
1445    FBiGeom_deleteAll(geom, &err);
1446    CHECK("");
1447    FBiGeom_load(geom, filename, 0, &err, strlen(filename), 0);
1448    CHECK( "Failed to load input file: 'size.sat'" );
1449 
1450    // get tag handles
1451    iBase_TagHandle interval, size, firmness, id;
1452    FBiGeom_getTagHandle(geom, "MESH_INTERVAL", &interval, &err, strlen(
1453          "MESH_INTERVAL"));
1454    CHECK( "FBiGeom_getTagHandle(\"MESH_INTERVAL\")" );
1455    FBiGeom_getTagHandle(geom, "MESH_SIZE", &size, &err, strlen("MESH_SIZE"));
1456    CHECK( "FBiGeom_getTagHandle(\"MESH_SIZE\")" );
1457    FBiGeom_getTagHandle(geom, "SIZE_FIRMNESS", &firmness, &err, strlen(
1458          "SIZE_FIRMNESS"));
1459    CHECK( "FBiGeom_getTagHandle(\"SIZE_FIRMNESS\")" );
1460    FBiGeom_getTagHandle(geom, "GLOBAL_ID", &id, &err, strlen("GLOBAL_ID"));
1461    CHECK( "FBiGeom_getTagHandle(\"GLOBAL_ID\")" );
1462 
1463    // get entity lists
1464    std::vector<iBase_EntityHandle> verts, curves, surfs, vols;
1465    std::vector<int> vert_ids, curve_ids, surf_ids, vol_ids;
1466    err = get_entities(geom, iBase_VERTEX, verts, id, &vert_ids);
1467    CHECK("");
1468    err = get_entities(geom, iBase_EDGE, curves, id, &curve_ids);
1469    CHECK("");
1470    err = get_entities(geom, iBase_FACE, surfs, id, &surf_ids);
1471    CHECK("");
1472    err = get_entities(geom, iBase_REGION, vols, id, &vol_ids);
1473    CHECK("");
1474 
1475    // expect interval count to be the same as ID for every curve
1476    std::vector<int> intervals(curves.size());
1477    int *int_ptr = &intervals[0];
1478    junk1 = junk2 = curves.size();
1479    FBiGeom_getIntArrData(geom, &curves[0], curves.size(), interval, &int_ptr,
1480          &junk1, &junk2, &err);
1481    CHECK("Failed to get intervals for curves");
1482    if (intervals != curve_ids) {
1483       std::cout << "ERROR: Incorrect curve intervals for one or more curves."
1484             << std::endl;
1485       std::cout << "ID  Expected  Actual" << std::endl;
1486       for (unsigned i = 0; i < curves.size(); ++i)
1487          std::cout << std::setw(2) << curve_ids[i] << "  " << std::setw(8)
1488                << curve_ids[i] << "  " << std::setw(6) << intervals[i]
1489                << std::endl;
1490       result = false;
1491    }
1492 
1493    // expect size to be the same as ID for every surface
1494    std::vector<double> sizes(surfs.size());
1495    double* dbl_ptr = &sizes[0];
1496    junk1 = junk2 = surfs.size();
1497    FBiGeom_getDblArrData(geom, &surfs[0], surfs.size(), size, &dbl_ptr, &junk1,
1498          &junk2, &err);
1499    CHECK("Failed to get sizes for surfaces");
1500    bool all_correct = true;
1501    for (unsigned i = 0; i < surfs.size(); ++i)
1502       if (fabs(sizes[i] - (double) surf_ids[i]) > 1e-8)
1503          all_correct = false;
1504    if (!all_correct) {
1505       std::cout << "ERROR: Incorrect mesh size for one or more surfaces."
1506             << std::endl;
1507       std::cout << "ID  Expected  Actual  " << std::endl;
1508       for (unsigned i = 0; i < surfs.size(); ++i)
1509          std::cout << std::setw(2) << surf_ids[i] << "  " << std::setw(8)
1510                << (double) surf_ids[i] << "  " << std::setw(8) << sizes[i]
1511                << std::endl;
1512       result = false;
1513    }
1514 
1515    err = result ? iBase_SUCCESS : iBase_FAILURE;
1516    CHECK("Invalid size or interval data");
1517 
1518    // expect "HARD" firmness on all curves
1519    err = check_firmness(geom, curves, curve_ids, firmness, "HARD", "curves");
1520    CHECK("Invalid curve firmness");
1521    // expect "SOFT" firmness on all surfaces
1522    err = check_firmness(geom, surfs, surf_ids, firmness, "SOFT", "surfaces");
1523    CHECK("Invalid surface firmness");
1524 
1525    // expect no firmnes on other entities
1526    err = count_num_with_tag(geom, verts, firmness) ? iBase_FAILURE
1527          : iBase_SUCCESS;
1528    CHECK("Got firmness for vertex.");
1529    err = count_num_with_tag(geom, vols, firmness) ? iBase_FAILURE
1530          : iBase_SUCCESS;
1531    CHECK("Got firmness for volume.");
1532 
1533    // expect no interval tag on any entities except curves
1534    err = count_num_with_tag(geom, verts, interval) ? iBase_FAILURE
1535          : iBase_SUCCESS;
1536    CHECK("Got interval count for vertex.");
1537    err = count_num_with_tag(geom, vols, interval) ? iBase_FAILURE
1538          : iBase_SUCCESS;
1539    CHECK("Got interval count for volume.");
1540 
1541    // expect no size tag on any entities except surfaces
1542    // curves should have size of one of their parent surfaces
1543    err = count_num_with_tag(geom, verts, size) ? iBase_FAILURE : iBase_SUCCESS;
1544    CHECK("Got mesh size for vertex.");
1545    err = count_num_with_tag(geom, vols, size) ? iBase_FAILURE : iBase_SUCCESS;
1546    CHECK("Got mesh size for volume.");
1547 
1548    return true;
1549 }
1550 
shutdown_test(FBiGeom_Instance geom,std::string & engine_opt)1551 bool shutdown_test(FBiGeom_Instance geom, std::string &engine_opt) {
1552    int err;
1553 
1554    // test shutdown & startup of interface
1555    FBiGeom_dtor(geom, &err);
1556    CHECK( "Interface destruction didn't work properly." );
1557 
1558    FBiGeom_newGeom(engine_opt.c_str(), &geom, &err, engine_opt.length());
1559    CHECK( "Interface re-construction didn't work properly." );
1560 
1561    FBiGeom_dtor(geom, &err);
1562    CHECK( "2nd Interface destruction didn't work properly." );
1563 
1564    return true;
1565 }
1566 
save_entset_test(FBiGeom_Instance geom)1567 bool save_entset_test(FBiGeom_Instance geom) {
1568    int err;
1569 
1570 #ifdef FORCE_OCC
1571    std::string filename = "testout.brep";
1572 #elif defined (HAVE_ACIS)
1573    std::string filename = "testout.sat";
1574 #elif defined (HAVE_OCC)
1575    std::string filename = "testout.brep";
1576 #else
1577    std::string filename = "testout.sat";
1578 #endif
1579 
1580    // initialize number of ents and sets to compare with later
1581    int num_ents_bef, num_sets_bef;
1582    iBase_EntitySetHandle root;
1583    FBiGeom_getRootSet(geom, &root, &err);
1584    CHECK("Failed to get root set.");
1585    FBiGeom_getNumEntSets(geom, root, 1, &num_sets_bef, &err);
1586    CHECK("Failed to get number of ent sets.");
1587    FBiGeom_getNumOfType(geom, root, iBase_REGION, &num_ents_bef, &err);
1588    CHECK("Failed to get number of entities.");
1589 
1590    // create set, and entity to add to set
1591    iBase_EntityHandle cyl;
1592    FBiGeom_createCylinder(geom, 1.0, 0.25, 0.0, &cyl, &err);
1593    CHECK( "Problems creating cylinder for save entset test." );
1594    iBase_EntitySetHandle seth;
1595    FBiGeom_createEntSet(geom, true, &seth, &err);
1596    CHECK( "Problems creating entity set for save entset test." );
1597 
1598    // add the entity
1599    FBiGeom_addEntToSet(geom, cyl, seth, &err);
1600    CHECK( "Problems adding entity to set for save entset test." );
1601 
1602    // save/restore the model, and see if the entity is there
1603    FBiGeom_save(geom, filename.c_str(), NULL, &err, filename.length(), 0);
1604    CHECK( "Problems saving file for save entset test." );
1605 
1606    FBiGeom_destroyEntSet(geom, seth, &err);
1607    CHECK("Failed to destroy entity set.");
1608    FBiGeom_deleteEnt(geom, cyl, &err);
1609    CHECK("Failed to destroy entity.");
1610 
1611    // read the file back in
1612    FBiGeom_load(geom, filename.c_str(), NULL, &err, filename.length(), 0);
1613    CHECK( "Problems reading file for save entset test." );
1614 
1615    // check number of sets and entities
1616    int num_ents_aft, num_sets_aft;
1617    FBiGeom_getNumEntSets(geom, root, 1, &num_sets_aft, &err);
1618    CHECK("Failed to get number of ent sets.");
1619    FBiGeom_getNumOfType(geom, root, iBase_REGION, &num_ents_aft, &err);
1620    CHECK("Failed to get number of entities.");
1621    bool success = true;
1622    if (num_ents_aft != 2 * num_ents_bef + 1) {
1623       print_error("Failed to get the right number of entities.", iBase_FAILURE,
1624             geom, __FILE__, __LINE__);
1625       success = false;
1626    } else if (num_sets_aft != 2 * num_sets_bef + 1) {
1627       print_error("Failed to get the right number of entity sets.",
1628             iBase_FAILURE, geom, __FILE__, __LINE__);
1629       success = false;
1630    }
1631 
1632    // otherwise, we succeeded
1633    return success;
1634 }
1635 
1636