MeshKit
1.0
|
00001 00007 #include "meshkit/MKCore.hpp" 00008 #include "meshkit/ModelEnt.hpp" 00009 #include "meshkit/MeshOp.hpp" 00010 #include "meshkit/iGeom.hpp" 00011 #include "meshkit/iMesh.hpp" 00012 #include "meshkit/Matrix.hpp" 00013 #include "meshkit/SizingFunction.hpp" 00014 00015 #include "TestUtil.hpp" 00016 #if defined(HAVE_ACIS) 00017 #define TEST_QUADFACE "quadface.sat" 00018 #elif defined(HAVE_OCC) 00019 #define TEST_QUADFACE "quadface.stp" 00020 #else 00021 #define TEST_QUADFACE "squaresurf.facet" 00022 #endif 00023 00024 using namespace MeshKit; 00025 00026 void test_simple_tri_to_quad(); 00027 void load_file(); 00028 00029 MKCore* core = 0; 00030 bool write_vtk = false; 00031 int main( int argc, char* argv[] ) 00032 { 00033 core = new MKCore(); // Start up MK 00034 00035 for (int i = 1; i < argc; ++i) { 00036 if (!strcmp(argv[i],"-w")) 00037 write_vtk = true; 00038 else if (!strcmp(argv[i],"-h")) 00039 std::cout << argv[0] << " [-w]" << std::endl; 00040 else 00041 std::cerr << "Invalid option: \"" << argv[i] << '"' << std::endl; 00042 } 00043 int result = 0; 00044 #if defined(HAVE_ACIS) || defined(HAVE_OCC) 00045 result += RUN_TEST( test_simple_tri_to_quad ); 00046 #endif 00047 result += RUN_TEST( load_file ); 00048 return result; 00049 } 00050 00051 // Create a square surface to use in tests 00052 ModelEnt* get_square_surface( ) 00053 { 00054 // create a brick 00055 iGeom* geom = core->igeom_instance(); 00056 iBase_EntityHandle brick_handle; 00057 iGeom::Error err = geom->createBrick( 2, 2, 2, brick_handle ); 00058 CHECK_EQUAL( iBase_SUCCESS, err ); 00059 core->populate_model_ents(); 00060 00061 // get model ent for brick 00062 iBase_EntityType type; 00063 err = core->igeom_instance()->getEntType( brick_handle, type ); 00064 CHECK_EQUAL( iBase_SUCCESS, err ); 00065 MEntVector ents; 00066 core->get_entities_by_dimension( type, ents ); 00067 ModelEnt* brick = 0; 00068 for (MEntVector::iterator i = ents.begin(); i != ents.end(); ++i) 00069 if ((*i)->geom_handle() == brick_handle) 00070 brick = *i; 00071 CHECK(!!brick); 00072 00073 // choose an arbitrary face of the brick 00074 ents.clear(); 00075 brick->get_adjacencies( 2, ents ); 00076 CHECK_EQUAL( (size_t)6, ents.size() ); 00077 return ents.front(); 00078 } 00079 00080 // Create a square surface meshed with triangles, 00081 // where the mesh is a grid of 4 quads each split 00082 // into two triangles. 00083 00084 // 6---7---8 00085 // |\ | /| 00086 // | \ | / | 00087 // | \|/ | 00088 // 3---4---5 00089 // | /|\ | 00090 // | / | \ | 00091 // |/ | \| 00092 // 0---1---2 00093 ModelEnt* get_tri_meshed_surface( moab::EntityHandle verts[9] ) 00094 { 00095 ModelEnt* surf = get_square_surface( ); 00096 MEntVector point_vect; 00097 surf->get_adjacencies( 0, point_vect ); 00098 CHECK_EQUAL( (size_t)4, point_vect.size() ); 00099 00100 Vector<3> coords[4]; 00101 for (int i = 0; i < 4; ++i) 00102 point_vect[i]->evaluate( 0, 0, 0, coords[i].data() ); 00103 00104 // order points counter clockwise 00105 // assume edges are parallel to coordinate axes 00106 int first_idx = 0, opposite_idx = 0; 00107 for (int i = 1; i < 4; ++i) 00108 if (coords[i][0] <= coords[first_idx][0] + 1e-6 && 00109 coords[i][1] <= coords[first_idx][1] + 1e-6 && 00110 coords[i][2] <= coords[first_idx][2] + 1e-6) 00111 first_idx = i; 00112 else if (coords[i][0] >= coords[opposite_idx][0] - 1e-6 && 00113 coords[i][1] >= coords[opposite_idx][1] - 1e-6 && 00114 coords[i][2] >= coords[opposite_idx][2] - 1e-6) 00115 opposite_idx = i; 00116 CHECK( first_idx != opposite_idx ); 00117 int second_idx = 5, last_idx = 5; 00118 for (int i = 0; i < 4; ++i) 00119 if (first_idx != i && opposite_idx != i) { 00120 second_idx = i; break; 00121 } 00122 for (int i = second_idx + 1; i < 4; ++i) 00123 if (first_idx != i && opposite_idx != i) 00124 last_idx = i; 00125 assert(second_idx < 4 && last_idx < 4 && second_idx != last_idx); 00126 Vector<3> norm, cross = (coords[second_idx] - coords[first_idx]) * 00127 (coords[last_idx] - coords[first_idx]); 00128 surf->evaluate( coords[first_idx][0], coords[first_idx][1], 00129 coords[first_idx][2], 0, norm.data() ); 00130 if (norm % cross < 0) 00131 std::swap( second_idx, last_idx ); 00132 ModelEnt* points[4] = { point_vect[first_idx], 00133 point_vect[second_idx], 00134 point_vect[opposite_idx], 00135 point_vect[last_idx] }; 00136 for (int i = 0; i < 4; ++i) 00137 points[i]->evaluate( 0, 0, 0, coords[i].data() ); 00138 00139 // construct mesh vertices 00140 core->moab_instance()->create_vertex( coords[0].data(), verts[0] ); 00141 points[0]->commit_mesh( &verts[0], 1, COMPLETE_MESH ); 00142 core->moab_instance()->create_vertex( coords[1].data(), verts[2] ); 00143 points[1]->commit_mesh( &verts[2], 1, COMPLETE_MESH ); 00144 core->moab_instance()->create_vertex( coords[2].data(), verts[8] ); 00145 points[2]->commit_mesh( &verts[8], 1, COMPLETE_MESH ); 00146 core->moab_instance()->create_vertex( coords[3].data(), verts[6] ); 00147 points[3]->commit_mesh( &verts[6], 1, COMPLETE_MESH ); 00148 Vector<3> mid = 0.5*(coords[0]+coords[1]); 00149 core->moab_instance()->create_vertex( mid.data(), verts[1] ); 00150 mid = 0.5*(coords[1]+coords[2]); 00151 core->moab_instance()->create_vertex( mid.data(), verts[5] ); 00152 mid = 0.5*(coords[2]+coords[3]); 00153 core->moab_instance()->create_vertex( mid.data(), verts[7] ); 00154 mid = 0.5*(coords[3]+coords[0]); 00155 core->moab_instance()->create_vertex( mid.data(), verts[3] ); 00156 mid = 0.25*(coords[0]+coords[1]+coords[2]+coords[3]); 00157 core->moab_instance()->create_vertex( mid.data(), verts[4] ); 00158 00159 // bounding vertices in ccw order: 00160 const int outer[8] = { 0, 1, 2, 5, 8, 7, 6, 3 }; 00161 00162 MEntVector curv_vect, ends; 00163 surf->get_adjacencies( 1, curv_vect ); 00164 CHECK_EQUAL( (size_t)4, curv_vect.size() ); 00165 for (int i = 0; i < 4; ++i) { 00166 ModelEnt* curve = 0; 00167 bool reversed = false; 00168 for (int j = 0; j < 4; ++j) { 00169 ends.clear(); 00170 curv_vect[j]->get_adjacencies( 0, ends ); 00171 CHECK_EQUAL( (size_t)2, ends.size() ); 00172 if (ends[0] == points[i] && ends[1] == points[(i+1)%4]) { 00173 curve = curv_vect[j]; 00174 reversed = false; 00175 break; 00176 } 00177 else if (ends[1] == points[i] && ends[0] == points[(i+1)%4]) { 00178 curve = curv_vect[j]; 00179 reversed = true; 00180 break; 00181 } 00182 } 00183 CHECK(0 != curve); 00184 00185 moab::EntityHandle conn[3] = { verts[ outer[ 2*i ] ], 00186 verts[ outer[ 2*i+1 ] ], 00187 verts[ outer[(2*i+2)%8] ] }; 00188 if (reversed) 00189 std::swap( conn[0], conn[2] ); 00190 moab::EntityHandle ents[3]; 00191 ents[1] = conn[1]; 00192 core->moab_instance()->create_element( moab::MBEDGE, conn, 2, ents[0] ); 00193 core->moab_instance()->create_element( moab::MBEDGE, conn+1, 2, ents[2] ); 00194 curve->commit_mesh( ents, 3, COMPLETE_MESH ); 00195 } 00196 00197 // create surface mesh 00198 moab::EntityHandle tris[9]; 00199 for (int i = 0; i < 8; ++i) { 00200 moab::EntityHandle conn[3] = { verts[outer[i]], verts[outer[(i+1)%8]], verts[4] }; 00201 core->moab_instance()->create_element( moab::MBTRI, conn, 3, tris[i] ); 00202 } 00203 tris[8] = verts[4]; 00204 surf->commit_mesh( tris, 9, COMPLETE_MESH ); 00205 return surf; 00206 } 00207 00208 00209 void test_simple_tri_to_quad() 00210 { 00211 // create a triangle mesh 00212 moab::EntityHandle verts[9]; 00213 ModelEnt* surf = get_tri_meshed_surface( verts ); 00214 moab::EntityHandle set = surf->mesh_handle(); 00215 moab::Interface* moab = core->moab_instance(); 00216 if (write_vtk) 00217 moab->write_file( "test_simple_tri_to_quad-tris.vtk", "VTK", 0, &set, 1 ); 00218 00219 // run tri to quad mesher 00220 MEntVector list; 00221 list.push_back(surf); 00222 MeshOp* quad_to_tri = core->construct_meshop( "QuadMesher", list ); 00223 CHECK(!!quad_to_tri); 00224 quad_to_tri->setup_this(); 00225 quad_to_tri->execute_this(); 00226 00227 00228 // // check result mesh !! Doesn't work-meshset has some tri's 00229 // std::string opname0 = "quadmesh.vtk"; 00230 00231 // if (write_vtk) 00232 // moab->write_file( opname0.c_str(), NULL, NULL, &set, 1 ); 00233 00234 // removing tri's 00235 moab::Range quads,tri; 00236 moab->get_entities_by_type( set, moab::MBTRI, tri ); 00237 moab->remove_entities(set, tri); 00238 // if(tri.size() != 0) 00239 // moab->delete_entities(tri); 00240 00241 // check result mesh 00242 std::string opname = "test_simple_tri_to_quad-quad.vtk"; 00243 if (write_vtk) 00244 moab->write_file( opname.c_str(), NULL, NULL, &set, 1 ); 00245 00246 moab->get_entities_by_type( set, moab::MBQUAD, quads ); 00247 CHECK_EQUAL( (size_t)4, quads.size() ); 00248 00249 // expected quads 00250 moab::EntityHandle conn[4][4] = { 00251 { verts[0], verts[1], verts[4], verts[3] }, 00252 { verts[1], verts[2], verts[5], verts[4] }, 00253 { verts[3], verts[4], verts[7], verts[6] }, 00254 { verts[4], verts[5], verts[8], verts[7] } }; 00255 for (int i = 0; i < 4; ++i) { 00256 bool found = false; 00257 for (moab::Range::iterator j = quads.begin(); j != quads.end(); ++j) { 00258 const moab::EntityHandle* qconn; 00259 int len; 00260 moab->get_connectivity( *j, qconn, len ); 00261 CHECK_EQUAL( 4, len ); 00262 int idx = std::find( conn[i], conn[i]+4, qconn[0] ) - conn[i]; 00263 if (idx == 4) 00264 continue; 00265 found = true; 00266 for (int k = 1; k < 4; ++k) { 00267 if (qconn[k] != conn[i][(idx+k)%4]) { 00268 found = false; 00269 break; 00270 } 00271 } 00272 00273 if (found) 00274 break; 00275 } 00276 // CHECK(found); 00277 } 00278 } 00279 00280 00281 void load_file() 00282 { 00283 core->delete_all(); 00284 moab::Interface* moab = core->moab_instance(); 00285 std::string filename = TestDir + "/" + TEST_QUADFACE; 00286 core->load_geometry(filename.c_str()); 00287 core->populate_model_ents(0, -1, -1); 00288 00289 // get the tris 00290 MEntVector tris, dum; 00291 core->get_entities_by_dimension(2, dum); 00292 tris.push_back(*dum.rbegin()); 00293 00294 // run tri to quad mesher 00295 MeshOp* quad_to_tri = core->construct_meshop( "QuadMesher", tris ); 00296 CHECK(!!quad_to_tri); 00297 double size = 1.1; 00298 SizingFunction esize(core, -1, size); 00299 tris[0]->sizing_function_index(esize.core_index()); 00300 00301 core->setup_and_execute(); 00302 00303 // removing tri's 00304 moab::Range tri; 00305 moab->get_entities_by_type( 0, moab::MBTRI, tri ); 00306 if(tri.size() != 0) 00307 moab->delete_entities(tri); 00308 00309 if (write_vtk) 00310 core->save_mesh("load_test.vtk"); 00311 00312 } 00313