/** * Copyright 2006 Sandia Corporation. Under the terms of Contract * DE-AC04-94AL85000 with Sandia Coroporation, the U.S. Government * retains certain rights in this software. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * */ /** * \file testgeom.cpp * * \brief testgeom, a unit test for the TSTT geometry interface * */ #include "iGeom.h" #include #include #include #include #include #include #include #include #include #include #define CHECK( STR ) if (err != iBase_SUCCESS) return print_error( STR, err, geom, __FILE__, __LINE__ ) #define STRINGIFY(S) XSTRINGIFY(S) #define XSTRINGIFY(S) #S static bool print_error( const char* desc, int err, iGeom_Instance geom, const char* file, int line ) { char buffer[1024]; iGeom_getDescription( geom, buffer, sizeof(buffer) ); buffer[sizeof(buffer)-1] = '\0'; std::cerr << "ERROR: " << desc << std::endl << " Error code: " << err << std::endl << " Error desc: " << buffer << std::endl << " At : " << file << ':' << line << std::endl ; return false; // must always return false or CHECK macro will break } typedef iBase_TagHandle TagHandle; typedef iBase_EntityHandle GentityHandle; typedef iBase_EntitySetHandle GentitysetHandle; /* Frees allocated arrays for us */ template class SimpleArray { private: T* arr; int arrSize; int arrAllocated; public: SimpleArray() : arr(0) , arrSize(0), arrAllocated(0) {} SimpleArray( unsigned s ) :arrSize(s), arrAllocated(s) { arr = (T*)malloc(s*sizeof(T)); for (unsigned i = 0; i < s; ++i) new (arr+i) T(); } ~SimpleArray() { for (int i = 0; i < size(); ++i) arr[i].~T(); free(arr); } T** ptr() { return &arr; } int& size() { return arrSize; } int size() const { return arrSize; } int& capacity() { return arrAllocated; } int capacity() const { return arrAllocated; } typedef T* iterator; typedef const T* const_iterator; iterator begin() { return arr; } const_iterator begin() const { return arr; } iterator end() { return arr + arrSize; } const_iterator end() const { return arr + arrSize; } T& operator[]( unsigned idx ) { return arr[idx]; } T operator[]( unsigned idx ) const { return arr[idx]; } }; #define ARRAY_INOUT( A ) A.ptr(), &A.capacity(), &A.size() #define ARRAY_IN( A ) &A[0], A.size() bool gLoad_test(const std::string filename, iGeom_Instance); bool tags_test(iGeom_Instance geom); bool tag_get_set_test(iGeom_Instance geom); bool tag_info_test(iGeom_Instance geom); bool gentityset_test(iGeom_Instance geom, bool /*multiset*/, bool /*ordered*/); bool topology_adjacencies_test(iGeom_Instance geom); bool construct_test(iGeom_Instance geom); bool primitives_test(iGeom_Instance geom); bool transforms_test(iGeom_Instance geom); bool booleans_test(iGeom_Instance geom); bool faceting_test(iGeom_Instance geom); bool shutdown_test(iGeom_Instance geom, std::string &engine_opt); bool save_entset_test(iGeom_Instance geom); bool mesh_size_test(iGeom_Instance geom); void handle_error_code(const bool result, int &number_failed, int &/*number_not_implemented*/, int &number_successful) { if (result) { std::cout << "Success"; number_successful++; } else { std::cout << "Failure"; number_failed++; } } int main( int argc, char *argv[] ) { // Check command line arg #ifdef FORCE_OCC #ifndef HAVE_OCC #error "Cannot force use of OCC w/out OCC support" #endif std::string filename = STRINGIFY(SRCDIR) "/../test/LeverArm.brep"; std::string engine_opt = ";engine=OCC"; #elif defined(HAVE_ACIS) std::string filename = STRINGIFY(SRCDIR) "/testgeom.sat"; std::string engine_opt = ";engine=ACIS"; #elif defined(HAVE_OCC) std::string filename = STRINGIFY(SRCDIR) "/../test/LeverArm.brep"; std::string engine_opt = ";engine=OCC"; #else std::string filename = STRINGIFY(SRCDIR) "/testgeom.sat"; std::string engine_opt; #endif if (argc == 1) { std::cout << "Using default input file: " << filename << std::endl; } else if (argc == 2) { filename = argv[1]; } else { std::cerr << "Usage: " << argv[0] << " [geom_filename]" << std::endl; return 1; } bool result; int number_tests = 0; int number_tests_successful = 0; int number_tests_not_implemented = 0; int number_tests_failed = 0; // initialize the Mesh int err; iGeom_Instance geom; iGeom_newGeom( engine_opt.c_str(), &geom, &err, engine_opt.length() ); // Print out Header information std::cout << "\n\nITAPS GEOMETRY INTERFACE TEST PROGRAM:\n\n"; // gLoad test std::cout << " gLoad: "; result = gLoad_test(filename, geom); handle_error_code(result, number_tests_failed, number_tests_not_implemented, number_tests_successful); number_tests++; std::cout << "\n"; // tags test std::cout << " tags: "; result = tags_test(geom); handle_error_code(result, number_tests_failed, number_tests_not_implemented, number_tests_successful); number_tests++; std::cout << "\n"; // gentitysets test std::cout << " gentity sets: "; result = gentityset_test(geom, false, false); handle_error_code(result, number_tests_failed, number_tests_not_implemented, number_tests_successful); number_tests++; std::cout << "\n"; // topology adjacencies test std::cout << " topology adjacencies: "; result = topology_adjacencies_test(geom); handle_error_code(result, number_tests_failed, number_tests_not_implemented, number_tests_successful); number_tests++; std::cout << "\n"; // construct test std::cout << " construct: "; result = construct_test(geom); handle_error_code(result, number_tests_failed, number_tests_not_implemented, number_tests_successful); number_tests++; std::cout << "\n"; // primitives test std::cout << " primitives: "; result = primitives_test(geom); handle_error_code(result, number_tests_failed, number_tests_not_implemented, number_tests_successful); number_tests++; std::cout << "\n"; // transforms test std::cout << " transforms: "; result = transforms_test(geom); handle_error_code(result, number_tests_failed, number_tests_not_implemented, number_tests_successful); number_tests++; std::cout << "\n"; // booleans test std::cout << " booleans: "; result = booleans_test(geom); handle_error_code(result, number_tests_failed, number_tests_not_implemented, number_tests_successful); number_tests++; std::cout << "\n"; #if defined(HAVE_ACIS) && !defined(FORCE_OCC) std::cout << " mesh size: "; result = mesh_size_test(geom); handle_error_code(result, number_tests_failed, number_tests_not_implemented, number_tests_successful); number_tests++; std::cout << "\n"; // save entset test std::cout << " save entset: "; result = save_entset_test(geom); handle_error_code(result, number_tests_failed, number_tests_not_implemented, number_tests_successful); number_tests++; std::cout << "\n"; // facet tests std::cout << " faceting: "; result = faceting_test(geom); handle_error_code(result, number_tests_failed, number_tests_not_implemented, number_tests_successful); number_tests++; std::cout << "\n"; #endif // shutdown test std::cout << " shutdown: "; result = shutdown_test(geom, engine_opt); handle_error_code(result, number_tests_failed, number_tests_not_implemented, number_tests_successful); number_tests++; std::cout << "\n"; // summary std::cout << "\nTSTT TEST SUMMARY: \n" << " Number Tests: " << number_tests << "\n" << " Number Successful: " << number_tests_successful << "\n" << " Number Not Implemented: " << number_tests_not_implemented << "\n" << " Number Failed: " << number_tests_failed << "\n\n" << std::endl; return number_tests_failed; } /*! @test Load Mesh @li Load a mesh file */ bool gLoad_test(const std::string filename, iGeom_Instance geom) { int err; iGeom_load( geom, &filename[0], 0, &err, filename.length(), 0 ); CHECK( "ERROR : can not load a geometry" ); iBase_EntitySetHandle root_set; iGeom_getRootSet( geom, &root_set, &err ); CHECK( "ERROR : getRootSet failed!" ); // print out the number of entities std::cout << "Model contents: " << std::endl; const char *gtype[] = {"vertices: ", "edges: ", "faces: ", "regions: "}; for (int i = 0; i <= 3; ++i) { int count; iGeom_getNumOfType( geom, root_set, i, &count, &err ); CHECK( "Error: problem getting entities after gLoad." ); std::cout << gtype[i] << count << std::endl; } SimpleArray vertices; iGeom_getEntities( geom, root_set, iBase_VERTEX, ARRAY_INOUT( vertices ), &err ); CHECK("Failed to get gentities in adjacencies_test."); for (int j=0; j tags; SimpleArray entities; iGeom_getEntities( geom, root_set, iBase_ALL_TYPES, ARRAY_INOUT(entities), &err ); CHECK( "getEntities( ..., iBase_ALL_TYPES, ... ) failed." ); for (int i = 0; i < entities.size(); ++i) { SimpleArray tag_arr; iGeom_getAllTags( geom, entities[i], ARRAY_INOUT(tag_arr), &err); CHECK( "getAllTags failed." ); std::copy( tag_arr.begin(), tag_arr.end(), std::inserter( tags, tags.begin() ) ); } std::cout << "Tags defined on model: "; bool first = true; for (std::set::iterator sit = tags.begin(); sit != tags.end(); ++sit) { iGeom_getTagName( geom, *sit, name_buffer, &err, sizeof(name_buffer) ); name_buffer[sizeof(name_buffer)-1] = '\0'; // mnake sure of NUL termination CHECK( "getTagName failed." ); if (!first) std::cout << ", "; std::cout << name_buffer; first = false; } if (first) std::cout << ""; std::cout << std::endl; return true; } bool tag_get_set_test(iGeom_Instance geom) { int err; // create an arbitrary tag, size 4 iBase_TagHandle this_tag; std::string tag_name("tag_get_set tag"); iGeom_createTag( geom, &tag_name[0], sizeof(int), iBase_BYTES, &this_tag, &err, tag_name.length() ); CHECK( "ERROR : can not create a tag for get_set test." ); iBase_EntitySetHandle root_set; iGeom_getRootSet( geom, &root_set, &err ); CHECK( "ERROR : getRootSet failed!" ); // set this tag to an integer on each entity; keep track of total sum int sum = 0, num = 0, dim; for (dim = 0; dim <= 3; dim++) { SimpleArray gentity_handles; iGeom_getEntities( geom, root_set, dim, ARRAY_INOUT( gentity_handles ), &err ); int num_ents = gentity_handles.size(); std::vector tag_vals( num_ents ); for (int i = 0; i < num_ents; ++i) { tag_vals[i] = num; sum += num; ++num; } iGeom_setArrData( geom, ARRAY_IN( gentity_handles ), this_tag, &tag_vals[0], tag_vals.size()*sizeof(int), &err ); CHECK( "ERROR : can't set tag on entities" ); } // check tag values for entities now int get_sum = 0; for (dim = 0; dim <= 3; dim++) { SimpleArray gentity_handles; iGeom_getEntities( geom, root_set, dim, ARRAY_INOUT( gentity_handles ), &err ); int num_ents = gentity_handles.size(); std::vector tag_vals( num_ents ); void* vals_ptr = &tag_vals[0]; int vals_size = tag_vals.size(), vals_alloc = tag_vals.size()*sizeof(int); iGeom_getArrData( geom, ARRAY_IN( gentity_handles ), this_tag, &vals_ptr, &vals_alloc, &vals_size, &err ); CHECK( "ERROR : can't get tag on entities" ); for (int i = 0; i < num_ents; ++i) get_sum += tag_vals[i]; } if (get_sum != sum) { std::cerr << "ERROR: getData didn't return consistent results." << std::endl; return false; } iGeom_destroyTag( geom, this_tag, true, &err ); CHECK( "ERROR : couldn't delete tag." ); return true; } /*! @test TSTT gentity sets test (just implemented parts for now) @li Check gentity sets */ bool gentityset_test(iGeom_Instance geom, bool /*multiset*/, bool /*ordered*/) { int num_type = 4; iBase_EntitySetHandle ges_array[4]; int number_array[4]; int num_all_gentities_super = 0; int ent_type = iBase_VERTEX; int err; iBase_EntitySetHandle root_set; iGeom_getRootSet( geom, &root_set, &err ); CHECK( "ERROR : getRootSet failed!" ); // get the number of sets in the whole model int all_sets = 0; iGeom_getNumEntSets( geom, root_set, 0, &all_sets, &err ); CHECK( "Problem getting the number of all gentity sets in whole model." ); // add gentities to entitysets by type for (; ent_type < num_type; ent_type++) { // initialize the entityset iGeom_createEntSet( geom, true, &ges_array[ent_type], &err ); CHECK( "Problem creating entityset." ); // get entities by type in total "mesh" SimpleArray gentities; iGeom_getEntities( geom, root_set, ent_type, ARRAY_INOUT(gentities), &err ); CHECK( "Failed to get gentities by type in gentityset_test." ); // add gentities into gentity set iGeom_addEntArrToSet( geom, ARRAY_IN( gentities ), ges_array[ent_type], &err ); CHECK( "Failed to add gentities in entityset_test." ); // Check to make sure entity set really has correct number of entities in it iGeom_getNumOfType( geom, ges_array[ent_type], ent_type, &number_array[ent_type], &err ); CHECK( "Failed to get number of gentities by type in entityset_test." ); // compare the number of entities by type int num_type_gentity = gentities.size(); if (number_array[ent_type] != num_type_gentity) { std::cerr << "Number of gentities by type is not correct" << std::endl; return false; } // add to number of all entities in super set num_all_gentities_super += num_type_gentity; } // make a super set having all entitysets iBase_EntitySetHandle super_set; iGeom_createEntSet( geom, true, &super_set, &err ); CHECK( "Failed to create a super set in gentityset_test." ); for (int i = 0; i < num_type; i++) { iGeom_addEntSet( geom, ges_array[i], super_set, &err ); CHECK( "Failed to create a super set in gentityset_test." ); } //----------TEST BOOLEAN OPERATIONS----------------// iBase_EntitySetHandle temp_ges1; iGeom_createEntSet( geom, true, &temp_ges1, &err ); CHECK( "Failed to create a super set in gentityset_test." ); // Subtract // add all EDGEs and FACEs to temp_es1 // get all EDGE entities SimpleArray gedges, gfaces, temp_gentities1; iGeom_getEntities( geom, ges_array[iBase_EDGE], iBase_EDGE, ARRAY_INOUT(gedges), &err ); CHECK( "Failed to get gedge gentities in gentityset_test." ); // add EDGEs to ges1 iGeom_addEntArrToSet( geom, ARRAY_IN(gedges), temp_ges1, &err ); CHECK( "Failed to add gedge gentities in gentityset_test." ); // get all FACE gentities iGeom_getEntities( geom, ges_array[iBase_FACE], iBase_FACE, ARRAY_INOUT(gfaces), &err ); CHECK( "Failed to get gface gentities in gentityset_test." ); // add FACEs to es1 iGeom_addEntArrToSet( geom, ARRAY_IN(gfaces), temp_ges1, &err ); CHECK( "Failed to add gface gentities in gentityset_test." ); // subtract EDGEs iGeom_subtract( geom, temp_ges1, ges_array[iBase_EDGE], &temp_ges1, &err ); CHECK( "Failed to subtract gentitysets in gentityset_test." ); iGeom_getEntities( geom, temp_ges1, iBase_FACE, ARRAY_INOUT(temp_gentities1), &err ); CHECK( "Failed to get gface gentities in gentityset_test." ); if (gfaces.size() != temp_gentities1.size()) { std::cerr << "Number of entitysets after subtraction not correct \ in gentityset_test." << std::endl; return false; } // check there's nothing but gfaces in temp_ges1 int num_gents; iGeom_getNumOfType( geom, temp_ges1, iBase_EDGE, &num_gents, &err ); CHECK( "Failed to get dimensions of gentities in gentityset_test." ); if (0 != num_gents) { std::cerr << "Subtraction failed to remove all edges" << std::endl; return false; } //------------Intersect------------ // // clean out the temp_ges1 iGeom_rmvEntArrFromSet( geom, ARRAY_IN(gfaces), temp_ges1, &err ); CHECK( "Failed to remove gface gentities in gentityset_test." ); // check if it is really cleaned out iGeom_getNumOfType( geom, temp_ges1, iBase_FACE, &num_gents, &err ); CHECK( "Failed to get number of gentities by type in gentityset_test." ); if (num_gents != 0) { std::cerr << "failed to remove correctly." << std::endl; return false; } // add EDGEs to temp ges1 iGeom_addEntArrToSet( geom, ARRAY_IN(gedges), temp_ges1, &err ); CHECK( "Failed to add gedge gentities in gentityset_test." ); // add FACEs to temp ges1 iGeom_addEntArrToSet( geom, ARRAY_IN(gfaces), temp_ges1, &err ); CHECK( "Failed to add gface gentities in gentityset_test." ); // intersect temp_ges1 with gedges set // temp_ges1 entityset is altered iGeom_intersect( geom, temp_ges1, ges_array[iBase_EDGE], &temp_ges1, &err ); CHECK( "Failed to intersect in gentityset_test." ); // try to get FACEs, but there should be nothing but EDGE iGeom_getNumOfType( geom, temp_ges1, iBase_FACE, &num_gents, &err ); CHECK( "Failed to get gface gentities in gentityset_test." ); if (num_gents != 0) { std::cerr << "wrong number of gfaces." << std::endl; return false; } //-------------Unite-------------- // get all regions iBase_EntitySetHandle temp_ges2; SimpleArray gregions; iGeom_createEntSet( geom, true, &temp_ges2, &err ); CHECK( "Failed to create a temp gentityset in gentityset_test." ); iGeom_getEntities( geom, ges_array[iBase_REGION], iBase_REGION, ARRAY_INOUT(gregions), &err ); CHECK( "Failed to get gregion gentities in gentityset_test." ); // add REGIONs to temp es2 iGeom_addEntArrToSet( geom, ARRAY_IN(gregions), temp_ges2, &err ); CHECK( "Failed to add gregion gentities in gentityset_test." ); // unite temp_ges1 and temp_ges2 // temp_ges1 gentityset is altered iGeom_unite( geom, temp_ges1, temp_ges2, &temp_ges1, &err ); CHECK( "Failed to unite in gentityset_test." ); // perform the check iGeom_getNumOfType( geom, temp_ges1, iBase_REGION, &num_gents, &err ); CHECK( "Failed to get number of gregion gentities by type in gentityset_test." ); if (num_gents != number_array[iBase_REGION]) { std::cerr << "different number of gregions in gentityset_test." << std::endl; return false; } //--------Test parent/child stuff in entiysets----------- // Add 2 sets as children to another iBase_EntitySetHandle parent_child; iGeom_createEntSet( geom, true, &parent_child, &err ); CHECK( "Problem creating gentityset in gentityset_test." ); iGeom_addPrntChld( geom, ges_array[iBase_VERTEX], parent_child, &err ); CHECK( "Problem add parent in gentityset_test." ); // check if parent is really added SimpleArray parents; iGeom_getPrnts( geom, parent_child, 1, ARRAY_INOUT(parents), &err ); CHECK( "Problem getting parents in gentityset_test." ); if (parents.size() != 1) { std::cerr << "number of parents is not correct in gentityset_test." << std::endl; return false; } // add parent and child //sidl::array parent_child_array = sidl::array::create1d(1); //int num_parent_child_array; //sidl::array temp_gedge_array = sidl::array::create1d(1); //int num_temp_gedge_array; //parent_child_array.set(0, parent_child); //temp_gedge_array.set(0, ges_array[TSTTG::EntityType_EDGE]); iGeom_addPrntChld( geom, ges_array[iBase_EDGE], parent_child, &err ); CHECK( "Problem adding parent and child in gentityset_test." ); //sidl::array temp_gface_array = sidl::array::create1d(1); //int num_temp_gface_array; //temp_gface_array.set(0, ges_array[TSTTG::EntityType_FACE]); iGeom_addPrntChld( geom, parent_child, ges_array[iBase_FACE], &err ); CHECK( "Problem adding parent and child in gentityset_test." ); // add child iGeom_addPrntChld( geom, parent_child, ges_array[iBase_REGION], &err ); CHECK( "Problem adding child in gentityset_test." ); // get the number of parent gentitysets num_gents = -1; iGeom_getNumPrnt( geom, parent_child, 0, &num_gents, &err ); CHECK( "Problem getting number of parents in gentityset_test." ); if (num_gents != 2) { std::cerr << "number of parents is not correct in gentityset_test." << std::endl; return false; } // get the number of child gentitysets num_gents = -1; iGeom_getNumChld( geom, parent_child, 0, &num_gents, &err ); CHECK( "Problem getting number of children in gentityset_test." ); if (num_gents != 2) { std::cerr << "number of children is not correct in gentityset_test." << std::endl; return false; } SimpleArray children; iGeom_getChldn( geom, parent_child, 0, ARRAY_INOUT(children), &err ); CHECK( "Problem getting children in gentityset_test." ); if (children.size() != 2) { std::cerr << "number of children is not correct in gentityset_test." << std::endl; return false; } // remove children iGeom_rmvPrntChld( geom, parent_child, ges_array[iBase_FACE], &err ); CHECK( "Problem removing parent child in gentityset_test." ); // get the number of child gentitysets iGeom_getNumChld( geom, parent_child, 0, &num_gents, &err ); CHECK( "Problem getting number of children in gentityset_test." ); if (num_gents != 1) { std::cerr << "number of children is not correct in gentityset_test." << std::endl; return false; } // parent_child and ges_array[TSTTG::EntityType_EDGE] should be related int result = 0; iGeom_isChildOf( geom, ges_array[iBase_EDGE], parent_child, &result, &err ); CHECK( "Problem checking relation in gentityset_test." ); if (!result) { std::cerr << "parent_child and ges_array[TSTTG::EntityType_EDGE] should be related" << std::endl; return false; } // ges_array[TSTTG::EntityType_FACE] and ges_array[TSTTG::REGION] are not related result = 2; iGeom_isChildOf( geom, ges_array[iBase_FACE], ges_array[iBase_REGION], &result, &err ); if (result) { std::cerr << "ges_array[TSTTG::REGION] and ges_array[TSTTG::EntityType_FACE] should not be related" << std::endl; return false; } //--------test modify and query functions----------------------------- // check the number of gentity sets in whole mesh SimpleArray gentity_sets; iGeom_getEntSets( geom, root_set, 0, ARRAY_INOUT( gentity_sets ), &err ); CHECK( "Problem to get all gentity sets in mesh." ); if (gentity_sets.size() != all_sets + 8) { std::cerr << "the number of gentity sets in whole mesh should be 8 times of num_iter." << std::endl; return false; } // get all gentity sets in super set SimpleArray ges_array1; iGeom_getEntSets( geom, super_set, 0, ARRAY_INOUT( ges_array1 ), &err ); CHECK( "Problem to get gentity sets in super set." ); // get the number of gentity sets in super set int num_super; iGeom_getNumEntSets( geom, super_set, 0, &num_super, &err ); CHECK( "Problem to get the number of all gentity sets in super set." ); // the number of gentity sets in super set should be same if (num_super != ges_array1.size()) { std::cerr << "the number of gentity sets in super set should be same." << std::endl; return false; } // get all entities in super set SimpleArray all_gentities; iGeom_getEntSets( geom, super_set, 0, ARRAY_INOUT( all_gentities ), &err ); CHECK( "Problem to get all gentities in super set." ); // compare the number of all gentities in super set // HJK : num_hops is not implemented //if (num_all_gentities_super != ARRAY_SIZE(all_gentities)) { //std::cerr << "number of all gentities in super set should be same." << std::endl; //success = false; //} return true; } /*! @test TSTTG topology adjacencies Test @li Check topology information @li Check adjacency */ // make each topological entity vectors, check their topology // types, get interior and exterior faces of model bool topology_adjacencies_test(iGeom_Instance geom) { int i, err; iBase_EntitySetHandle root_set; iGeom_getRootSet( geom, &root_set, &err ); CHECK( "ERROR : getRootSet failed!" ); int top = iBase_VERTEX; int num_test_top = iBase_ALL_TYPES; std::vector< std::vector > gentity_vectors(num_test_top); // fill the vectors of each topology entities // like lines vector, polygon vector, triangle vector, // quadrilateral, polyhedrron, tet, hex, prism, pyramid, // septahedron vectors for (i = top; i < num_test_top; i++) { SimpleArray gentities; iGeom_getEntities( geom, root_set, i, ARRAY_INOUT( gentities ), &err ); CHECK("Failed to get gentities in adjacencies_test."); gentity_vectors[i].resize( gentities.size() ); std::copy( gentities.begin(), gentities.end(), gentity_vectors[i].begin() ); } // check number of entities for each topology for (i = top; i < num_test_top; i++) { int num_tops = 0; iGeom_getNumOfType( geom, root_set, i, &num_tops, &err ); CHECK( "Failed to get number of gentities in adjacencies_test." ); if (static_cast(gentity_vectors[i].size()) != num_tops) { std::cerr << "Number of gentities doesn't agree with number returned for dimension " << i << std::endl; return false; } } // check adjacencies in both directions std::vector::iterator vit; for (i = iBase_REGION; i >= iBase_VERTEX; i--) { for (vit = gentity_vectors[i].begin(); vit != gentity_vectors[i].end(); vit++) { iBase_EntityHandle this_gent = *vit; // check downward adjacencies for (int j = iBase_VERTEX; j < i; j++) { SimpleArray lower_ents; iGeom_getEntAdj( geom, this_gent, j, ARRAY_INOUT(lower_ents), &err ); CHECK( "Bi-directional adjacencies test failed." ); // for each of them, make sure they are adjacent to the upward ones int num_lower = lower_ents.size(); for (int k = 0; k < num_lower; k++) { SimpleArray upper_ents; iGeom_getEntAdj( geom, lower_ents[k], i, ARRAY_INOUT(upper_ents), &err ); CHECK( "Bi-directional adjacencies test failed." ); if (std::find(upper_ents.begin(),upper_ents.end(), this_gent) == upper_ents.end()) { std::cerr << "Didn't find lower-upper adjacency which was supposed to be there, dims = " << i << ", " << j << std::endl; return false; } } } } } return true; } /*! @test TSTTG construct Test @li Check construction of geometry */ bool construct_test(iGeom_Instance geom) { int err; iBase_EntityHandle new_body = 0; // construct a cylinder, sweep it about an axis, and delete the result iBase_EntityHandle cyl = 0; iGeom_createCylinder( geom, 1.0, 1.0, 0.0, &cyl, &err ); // Is the minor radius really supposed to be zero??? - JK CHECK( "Creating cylinder failed." ); // move it onto the y axis iGeom_moveEnt( geom, cyl, 0.0, 1.0, -0.5, &err ); CHECK( "Problems moving surface." ); // get the surface with max z iBase_EntityHandle max_surf = 0; SimpleArray surfs; iGeom_getEntAdj( geom, cyl, iBase_FACE, ARRAY_INOUT(surfs), &err ); CHECK( "Problems getting max surf for rotation." ); SimpleArray max_corn, min_corn; iGeom_getArrBoundBox( geom, ARRAY_IN(surfs), iBase_INTERLEAVED, ARRAY_INOUT( min_corn ), ARRAY_INOUT( max_corn ), &err ); CHECK( "Problems getting max surf for rotation." ); double dtol = 1.0e-6; for (int i = 0; i < surfs.size(); ++i) { if ((max_corn[3*i+2]) <= dtol && (max_corn[3*i+2]) >= -dtol && (min_corn[3*i+2]) <= dtol && (min_corn[3*i+2]) >= -dtol) { max_surf = surfs[i]; break; } } if (0 == max_surf) { std::cerr << "Couldn't find max surf for rotation." << std::endl; return false; } // sweep it around the x axis iGeom_moveEnt( geom, cyl, 0.0, 1.0, 0.0, &err ); CHECK( "Problems moving surface." ); iGeom_sweepEntAboutAxis( geom, max_surf, 360.0, 1.0, 0.0, 0.0, &new_body, &err ); CHECK( "Problems sweeping surface about axis." ); // now delete iGeom_deleteEnt( geom, new_body, &err ); CHECK( "Problems deleting cylinder or swept surface body." ); // if we got here, we were successful return true; } static bool compare_box( const double* expected_min, const double* expected_max, const double* actual_min, const double* actual_max ) { bool same = true; double dtol = 1.0e-6; for (int i = 0; i < 3; ++i) { if (expected_min[i] < actual_min[i] - dtol || expected_min[i]*10 > actual_min[i] || expected_max[i] > actual_max[i] + dtol || expected_max[i]*10 < actual_max[i]) same = false; } return same; } bool primitives_test(iGeom_Instance geom) { int err; SimpleArray prims(3); iBase_EntityHandle prim; iGeom_createBrick( geom, 1.0, 2.0, 3.0, &prim, &err ); CHECK( "createBrick failed." ); prims[0] = prim; iGeom_createCylinder( geom, 1.0, 4.0, 2.0, &prim, &err ); CHECK( "createCylinder failed." ); prims[1] = prim; iGeom_createTorus( geom, 2.0, 1.0, &prim, &err ); CHECK( "createTorus failed." ); prims[2] = prim; // verify the bounding boxes for Acis based entities SimpleArray max_corn, min_corn; iGeom_getArrBoundBox( geom, ARRAY_IN(prims), iBase_INTERLEAVED, ARRAY_INOUT(min_corn), ARRAY_INOUT(max_corn), &err ); double preset_min_corn[] = // min brick corner xyz {-0.5, -1.0, -1.5, // min cyl corner xyz -4.0, -2.0, -0.5, // min torus corner xyz -3.0, -3.0, -1.0 }; double preset_max_corn[] = // max brick corner xyz {0.5, 1.0, 1.5, // max cyl corner xyz 4.0, 2.0, 0.5, // max torus corner xyz 3.0, 3.0, 1.0 }; if (!compare_box( preset_min_corn, preset_max_corn, &min_corn[0], &max_corn[0] )) { std::cerr << "Box check failed for brick" << std::endl; return false; } if (!compare_box( preset_min_corn+3, preset_max_corn+3, &min_corn[3], &max_corn[3] )) { std::cerr << "Box check failed for cylinder" << std::endl; return false; } if (!compare_box( preset_min_corn+6, preset_max_corn+6, &min_corn[6], &max_corn[6] )) { std::cerr << "Box check failed for torus" << std::endl; return false; } // must have worked; delete the entities then return for (int i = 0; i < 3; ++i) { iGeom_deleteEnt( geom, prims[i], &err ); CHECK( "Problems deleting primitive after boolean check." ); } return true; } bool transforms_test(iGeom_Instance geom) { int err; // construct a brick iBase_EntityHandle brick = 0; iGeom_createBrick( geom, 1.0, 2.0, 3.0, &brick, &err ); CHECK( "Problems creating brick for transforms test." ); // move it, then test bounding box iGeom_moveEnt( geom, brick, 0.5, 1.0, 1.5, &err ); CHECK( "Problems moving brick for transforms test." ); double bb_min[3], bb_max[3]; iGeom_getEntBoundBox( geom, brick, bb_min, bb_min+1, bb_min+2, bb_max, bb_max+1, bb_max+2, &err ); CHECK( "Problems getting bounding box after move." ); double dtol = 1.0e-6; if ((bb_min[0]) >= dtol || (bb_min[0]) <= -dtol || (bb_min[1]) >= dtol || (bb_min[1]) <= -dtol || (bb_min[2]) >= dtol || (bb_min[2]) <= -dtol || (bb_max[0]-1) >= dtol || 1-bb_max[0] >=dtol || (bb_max[1]-2) >= dtol || 2 - bb_max[1] >=dtol|| (bb_max[2]-3) >= dtol || 3 - bb_max[2] >= dtol) { std::cerr << "Wrong bounding box after move." << std::endl; return false; } // now rotate it about +x, then test bounding box iGeom_rotateEnt( geom, brick, 90, 1.0, 0.0, 0.0, &err ); CHECK( "Problems rotating brick for transforms test." ); iGeom_getEntBoundBox( geom, brick, bb_min, bb_min+1, bb_min+2, bb_max, bb_max+1, bb_max+2, &err ); CHECK( "Problems getting bounding box after rotate." ); if ((bb_min[0]) >= dtol || -bb_min[0] >= dtol || (bb_min[1]+3) >= dtol || -(bb_min[1]+3) >= dtol || (bb_min[2]) >= dtol || -(bb_min[2]) >= dtol || (bb_max[0]-1) >= dtol || 1-bb_max[0] >= dtol || (bb_max[1]) >= dtol || -(bb_max[1]) >= dtol || (bb_max[2]-2) >= dtol || 2-bb_max[2] >=dtol) { std::cerr << "Wrong bounding box after rotate." << std::endl; return false; } // now reflect through y plane; should recover original bb iGeom_reflectEnt( geom, brick, 0.0, 1.0, 0.0, &err ); CHECK( "Problems reflecting brick for transforms test." ); iGeom_getEntBoundBox( geom, brick, bb_min, bb_min+1, bb_min+2, bb_max, bb_max+1, bb_max+2, &err ); CHECK( "Problems getting bounding box after reflect." ); if ((bb_min[0]) >= dtol || -(bb_min[0]) >= dtol ||(bb_min[1]) >= dtol || (bb_min[2]) >= dtol || -(bb_min[1]) >= dtol || -(bb_min[2]) >= dtol || (bb_max[0]-1) >= dtol || 1- bb_max[0] >= dtol || (bb_max[1]-3) >= dtol || 3 - bb_max[1] >= dtol || (bb_max[2]-2) >= dtol || 2 - bb_max[2] >= dtol) { std::cerr << "Wrong bounding box after reflect." << std::endl; return false; } // must have worked; delete the entities then return iGeom_deleteEnt( geom, brick, &err ); CHECK( "Problems deleting brick after transforms check." ); return true; } bool booleans_test(iGeom_Instance geom) { int err; // construct a brick size 1, and a cylinder rad 0.25 height 2 iBase_EntityHandle brick = 0, cyl = 0; iGeom_createBrick( geom, 1.0, 0.0, 0.0, &brick, &err ); CHECK( "Problems creating brick for booleans test." ); iGeom_createCylinder( geom, 1.0, 0.25, 0.0, &cyl, &err ); CHECK( "Problems creating cylinder for booleans test." ); // subtract the cylinder from the brick iBase_EntityHandle subtract_result = 0; iGeom_subtractEnts( geom, brick, cyl, &subtract_result, &err ); CHECK( "Problems subtracting for booleans subtract test." ); // section the brick iBase_EntityHandle section_result = 0; iGeom_sectionEnt( geom, subtract_result, 1.0, 0.0, 0.0, 0.25, true, §ion_result, &err ); CHECK( "Problems sectioning for booleans section test." ); // unite the section result with a new cylinder iGeom_createCylinder( geom, 1.0, 0.25, 0.0, &cyl, &err ); CHECK( "Problems creating cylinder for unite test." ); iBase_EntityHandle unite_results; iBase_EntityHandle unite_input[] = { section_result, cyl }; iGeom_uniteEnts( geom, unite_input, 2, &unite_results, &err ); CHECK( "Problems uniting for booleans unite test." ); iGeom_deleteEnt( geom, unite_results, &err ); CHECK( "Problems deleting for booleans unite test." ); return true; } static int get_entities( iGeom_Instance geom, int entity_type, std::vector& entities_out, iBase_TagHandle id_tag = 0, std::vector* ids_out = 0 ) { int err, num; iBase_EntitySetHandle root; iGeom_getRootSet( geom, &root, &err ); if (iBase_SUCCESS != err) return err; iGeom_getNumOfType( geom, root, entity_type, &num, &err ); if (iBase_SUCCESS != err) return err; entities_out.resize(num); int junk1 = entities_out.size(), junk2; iBase_EntityHandle* junk_ptr = &entities_out[0];; iGeom_getEntities( geom, root, entity_type, &junk_ptr, &junk1, &junk2, &err ); if (iBase_SUCCESS != err) return err; assert( num == junk1 && num == junk2 ); if (!ids_out) return iBase_SUCCESS; ids_out->resize(num); int* int_ptr = &(*ids_out)[0]; iGeom_getIntArrData( geom, &entities_out[0], num, id_tag, &int_ptr, &junk1, &junk2, &err ); if (iBase_SUCCESS != err) return err; assert( num == junk1 && num == junk2 ); return iBase_SUCCESS; } static int check_firmness( iGeom_Instance geom, const std::vector& entities, const std::vector& ids, iBase_TagHandle firmness_tag, const char* expected_value, const char* ent_type_str ) { const int firmness_size = 4; std::vector firmness(firmness_size * entities.size()); void* byte_ptr = &firmness[0]; int err, junk1 = firmness.size(), junk2 = entities.size()*firmness_size; iGeom_getArrData( geom, &entities[0], entities.size(), firmness_tag, (void**)&byte_ptr, &junk1, &junk2, &err ); if (iBase_SUCCESS != err) return err; bool all_correct = true; for (unsigned i = 0; i < entities.size(); ++i) if (std::string(&firmness[firmness_size*i],firmness_size) != expected_value) all_correct = false; if (!all_correct) { std::cout << "ERROR: Expected \"" << expected_value << "\" firmness " << "for all " << ent_type_str << "." << std::endl; std::cout << "ID Actual " << std::endl; for (unsigned i = 0; i < entities.size(); ++i) std::cout << std::setw(2) << ids[i] << " " << std::string(&firmness[firmness_size*i],firmness_size) << std::endl; return iBase_FAILURE; } return iBase_SUCCESS; } static int count_num_with_tag( iGeom_Instance geom, const std::vector& ents, iBase_TagHandle tag ) { int err, bytes; iGeom_getTagSizeBytes( geom, tag, &bytes, &err ); if (iBase_SUCCESS != err) return -1; std::vector data(bytes); int success_count = 0; for (size_t i = 0; i < ents.size(); ++i) { void* ptr = &data[0]; int junk1 = bytes, junk2; iGeom_getData( geom, ents[i], tag, (void**)&ptr, &junk1, &junk2, &err ); if (iBase_TAG_NOT_FOUND == err) continue; if (iBase_SUCCESS != err) return -1; ++success_count; } return success_count; } bool mesh_size_test(iGeom_Instance geom) { const char* filename = STRINGIFY(SRCDIR) "/size.sat"; int err; iGeom_deleteAll( geom, &err ); CHECK(""); iGeom_load( geom, filename, 0, &err, strlen(filename), 0 ); CHECK( "Failed to load input file: 'size.sat'" ); // get tag handles iBase_TagHandle interval, size, firmness, id; iGeom_getTagHandle( geom, "MESH_INTERVAL", &interval, &err, strlen("MESH_INTERVAL") ); CHECK( "iGeom_getTagHandle(\"MESH_INTERVAL\")" ); iGeom_getTagHandle( geom, "MESH_SIZE", &size, &err, strlen("MESH_SIZE") ); CHECK( "iGeom_getTagHandle(\"MESH_SIZE\")" ); iGeom_getTagHandle( geom, "SIZE_FIRMNESS", &firmness, &err, strlen("SIZE_FIRMNESS") ); CHECK( "iGeom_getTagHandle(\"SIZE_FIRMNESS\")" ); iGeom_getTagHandle( geom, "GLOBAL_ID", &id, &err, strlen("GLOBAL_ID") ); CHECK( "iGeom_getTagHandle(\"GLOBAL_ID\")" ); // get entity lists std::vector verts, curves, surfs, vols; std::vector vert_ids, curve_ids, surf_ids, vol_ids; err = get_entities( geom, iBase_VERTEX, verts, id, &vert_ids ); CHECK(""); err = get_entities( geom, iBase_EDGE, curves, id, &curve_ids ); CHECK(""); err = get_entities( geom, iBase_FACE, surfs, id, &surf_ids ); CHECK(""); err = get_entities( geom, iBase_REGION, vols, id, &vol_ids ); CHECK(""); // expect interval count to be the same as ID for every curve /* testgeom didn't pass with the following call, uncomment it when fixed. std::vector intervals(curves.size()); int *int_ptr = &intervals[0]; junk1 = junk2 = curves.size(); iGeom_getIntArrData( geom, &curves[0], curves.size(), interval, &int_ptr, &junk1, &junk2, &err ); CHECK("Failed to get intervals for curves"); if (intervals != curve_ids) { std::cout << "ERROR: Incorrect curve intervals for one or more curves." << std::endl; std::cout << "ID Expected Actual" << std::endl; for (unsigned i = 0; i < curves.size(); ++i) std::cout << std::setw(2) << curve_ids[i] << " " << std::setw(8) << curve_ids[i] << " " << std::setw(6) << intervals[i] << std::endl; result = false; } // expect size to be the same as ID for every surface std::vector sizes(surfs.size()); double* dbl_ptr = &sizes[0]; junk1 = junk2 = surfs.size(); iGeom_getDblArrData( geom, &surfs[0], surfs.size(), size, &dbl_ptr, &junk1, &junk2, &err ); CHECK("Failed to get sizes for surfaces"); bool all_correct = true; for (unsigned i = 0; i < surfs.size(); ++i) if (fabs(sizes[i] - (double)surf_ids[i] ) > 1e-8) all_correct = false; if (!all_correct) { std::cout << "ERROR: Incorrect mesh size for one or more surfaces." << std::endl; std::cout << "ID Expected Actual " << std::endl; for (unsigned i = 0; i < surfs.size(); ++i) std::cout << std::setw(2) << surf_ids[i] << " " << std::setw(8) << (double)surf_ids[i] << " " << std::setw(8) << sizes[i] << std::endl; result = false; } err = result ? iBase_SUCCESS : iBase_FAILURE; CHECK("Invalid size or interval data"); // expect "HARD" firmness on all curves err = check_firmness( geom, curves, curve_ids, firmness, "HARD", "curves" ); CHECK("Invalid curve firmness"); // expect "SOFT" firmness on all surfaces err = check_firmness( geom, surfs, surf_ids, firmness, "SOFT", "surfaces" ); CHECK("Invalid surface firmness"); */ // expect no firmnes on other entities err = count_num_with_tag( geom, verts, firmness ) ? iBase_FAILURE : iBase_SUCCESS; CHECK("Got firmness for vertex."); err = count_num_with_tag( geom, vols, firmness ) ? iBase_FAILURE : iBase_SUCCESS; CHECK("Got firmness for volume."); // expect no interval tag on any entities except curves err = count_num_with_tag( geom, verts, interval ) ? iBase_FAILURE : iBase_SUCCESS; CHECK("Got interval count for vertex."); err = count_num_with_tag( geom, vols, interval ) ? iBase_FAILURE : iBase_SUCCESS; CHECK("Got interval count for volume."); // expect no size tag on any entities except surfaces // curves should have size of one of their parent surfaces err = count_num_with_tag( geom, verts, size ) ? iBase_FAILURE : iBase_SUCCESS; CHECK("Got mesh size for vertex."); err = count_num_with_tag( geom, vols, size ) ? iBase_FAILURE : iBase_SUCCESS; CHECK("Got mesh size for volume."); return true; } bool faceting_test(iGeom_Instance geom) { const char* filename = STRINGIFY(SRCDIR) "/size.sat"; int err; double dist_tolerance=0.001; iGeom_deleteAll( geom, &err ); CHECK(""); iGeom_load( geom, filename, 0, &err, strlen(filename), 0 ); CHECK( "Failed to load input file: 'size.sat'" ); // get entity lists iBase_TagHandle id; iGeom_getTagHandle( geom, "GLOBAL_ID", &id, &err, strlen("GLOBAL_ID") ); CHECK( "iGeom_getTagHandle(\"GLOBAL_ID\")" ); std::vector verts, curves, surfs, vols; std::vector vert_ids, curve_ids, surf_ids, vol_ids; err = get_entities( geom, iBase_VERTEX, verts, id, &vert_ids ); CHECK(""); err = get_entities( geom, iBase_EDGE, curves, id, &curve_ids ); CHECK(""); err = get_entities( geom, iBase_FACE, surfs, id, &surf_ids ); CHECK(""); err = get_entities( geom, iBase_REGION, vols, id, &vol_ids ); CHECK(""); unsigned int ent; std::vector points; double *p_ptr = &points[0]; int p_size = 0, p_alloc=points.size(); std::vector facets; int *f_ptr = &facets[0]; int f_size = 0, f_alloc=facets.size(); for (ent=0; ent < verts.size(); ent++) { iGeom_getFacets(geom, verts[ent], dist_tolerance, &p_ptr, &p_alloc, &p_size, &f_ptr, &f_alloc, &f_size, &err); if (iBase_INVALID_ENTITY_TYPE != err) { err = iBase_FAILURE; CHECK("getFacets should fail for vertices."); } } for (ent=0; ent < curves.size(); ent++) { iGeom_getFacets(geom, curves[ent], dist_tolerance, &p_ptr, &p_alloc, &p_size, &f_ptr, &f_alloc, &f_size, &err); points.resize(p_size); facets.resize(f_size); if ( iBase_BAD_ARRAY_DIMENSION == err || iBase_BAD_ARRAY_SIZE == err) { p_ptr = &points[0]; p_alloc = points.size(); f_ptr = &facets[0]; f_alloc = facets.size(); iGeom_getFacets(geom, curves[ent], dist_tolerance, &p_ptr, &p_alloc, &p_size, &f_ptr, &f_alloc, &f_size, &err); } CHECK("getFacets failed for a curve."); err = (6 != p_size); CHECK("wrong number of points in curve"); err = (0 != f_size); CHECK("Non-zero number of facets in curve"); // should check for known sizes and values of these facets & points } for (ent=0; ent < surfs.size(); ent++) { iGeom_getFacets(geom, surfs[ent], dist_tolerance, &p_ptr, &p_alloc, &p_size, &f_ptr, &f_alloc, &f_size, &err); points.resize(p_size); facets.resize(f_size); if ( iBase_BAD_ARRAY_DIMENSION == err || iBase_BAD_ARRAY_SIZE == err) { p_ptr = &points[0]; p_alloc = points.size(); f_ptr = &facets[0]; f_alloc = facets.size(); iGeom_getFacets(geom, surfs[ent], dist_tolerance, &p_ptr, &p_alloc, &p_size, &f_ptr, &f_alloc, &f_size, &err); } std::cerr << "curve " << ent << ": " << p_size << " points and " << f_size << " facets." << std::endl; CHECK("getFacets failed for a surface."); err = (12 != p_size); CHECK("wrong number of points in curve"); err = (6 != f_size); CHECK("wrong number of facets in curve"); // should check for known sizes and values of these facets & points } for (ent=0; ent < vols.size(); ent++) { iGeom_getFacets(geom, vols[ent], dist_tolerance, &p_ptr, &p_alloc, &p_size, &f_ptr, &f_alloc, &f_size, &err); if (iBase_INVALID_ENTITY_TYPE != err) { err = iBase_FAILURE; CHECK("getFacets should fail for volumes."); } } return true; } bool shutdown_test(iGeom_Instance geom, std::string &engine_opt) { int err; // test shutdown & startup of interface iGeom_dtor(geom, &err); CHECK( "Interface destruction didn't work properly." ); iGeom_newGeom(engine_opt.c_str(), &geom, &err, engine_opt.length()); CHECK( "Interface re-construction didn't work properly." ); iGeom_dtor(geom, &err); CHECK( "2nd Interface destruction didn't work properly." ); return true; } bool save_entset_test(iGeom_Instance geom) { int err; #ifdef FORCE_OCC std::string filename = "testout.brep"; #elif defined (HAVE_ACIS) std::string filename = "testout.sat"; #elif defined (HAVE_OCC) std::string filename = "testout.brep"; #else std::string filename = "testout.sat"; #endif // initialize number of ents and sets to compare with later int num_ents_bef, num_sets_bef; iBase_EntitySetHandle root; iGeom_getRootSet( geom, &root, &err ); CHECK("Failed to get root set."); iGeom_getNumEntSets(geom, root, 0, &num_sets_bef, &err); CHECK("Failed to get number of ent sets."); iGeom_getNumOfType(geom, root, iBase_REGION, &num_ents_bef, &err); CHECK("Failed to get number of entities."); // create set, and entity to add to set iBase_EntityHandle cyl; iGeom_createCylinder( geom, 1.0, 0.25, 0.0, &cyl, &err ); CHECK( "Problems creating cylinder for save entset test." ); iBase_EntitySetHandle seth; iGeom_createEntSet(geom, true, &seth, &err); CHECK( "Problems creating entity set for save entset test." ); // add the entity iGeom_addEntToSet(geom, cyl, seth, &err); CHECK( "Problems adding entity to set for save entset test." ); // save/restore the model, and see if the entity is there iGeom_save(geom, filename.c_str(), NULL, &err, filename.length(), 0); CHECK( "Problems saving file for save entset test." ); iGeom_destroyEntSet(geom, seth, &err); CHECK("Failed to destroy entity set."); iGeom_deleteEnt(geom, cyl, &err); CHECK("Failed to destroy entity."); // read the file back in iGeom_load(geom, filename.c_str(), NULL, &err, filename.length(), 0); CHECK( "Problems reading file for save entset test." ); // check number of sets and entities int num_ents_aft, num_sets_aft; iGeom_getNumEntSets(geom, root, 0, &num_sets_aft, &err); CHECK("Failed to get number of ent sets."); iGeom_getNumOfType(geom, root, iBase_REGION, &num_ents_aft, &err); CHECK("Failed to get number of entities."); bool success = true; if (num_ents_aft != 2*num_ents_bef + 1) { print_error("Failed to get the right number of entities.", iBase_FAILURE, geom, __FILE__, __LINE__); success = false; } else if (num_sets_aft != 2*num_sets_bef + 1) { print_error("Failed to get the right number of entity sets.", iBase_FAILURE, geom, __FILE__, __LINE__); success = false; } // otherwise, we succeeded return success; }