MeshKit
1.0
|
00001 #include "meshkit/QuadCleanUp.hpp" 00002 #include "meshkit/SwapEdges.hpp" 00003 00004 using namespace Jaal; 00005 00007 00008 int 00009 QuadCleanUp::automatic() 00010 { 00011 int err; 00012 (void) err; 00013 // **************************************************************************** 00014 // If the mesh is triangular first convert it into Quad mesh .... 00015 // **************************************************************************** 00016 // 00017 if (mesh->isHomogeneous () == 3) { 00018 Tri2Quads t2quad; 00019 Mesh *quadmesh = t2quad.getQuadMesh( mesh, 1); 00020 delete mesh; // deletes the triangle mesh... 00021 mesh = quadmesh; 00022 return 0; 00023 } 00024 00025 // Throughout the cleaning process, euler characteristic should remain same 00026 int euler0 = mesh->getEulerCharacteristic(); // Invariant 00027 00028 // Total area of the domain must be same ... 00029 double area0 = mesh->getSurfaceArea(); 00030 00031 // Ensure that there are irregular nodes in the mesh. if not, you are lucky and done. 00032 NodeSequence irreg_nodes; 00033 mesh->get_irregular_nodes(irreg_nodes, 4 ); 00034 if( irreg_nodes.empty() ) { 00035 cout << "Great: There are no irregular nodes in the mesh" << endl; 00036 mopt.shape_optimize( mesh ); 00037 return 0; 00038 } 00039 00040 // **************************************************************************** 00041 // Triangle to Quad Transformation starts from here ...Input preparation.. 00042 // **************************************************************************** 00043 00044 assert( mesh->isHomogeneous () == 4); 00045 cout << " Input Mesh : " << endl; 00046 cout << " # Nodes : " << mesh->getSize(0) << endl; 00047 cout << " # Quad Faces : " << mesh->getSize(2) << endl; 00048 cout << " # Components : " << mesh->getNumComponents() << endl; 00049 cout << " # Irregular nodes : " << irreg_nodes.size() << endl; 00050 cout << " # Concave faces : " << mesh->count_concave_faces() << endl; 00051 cout << " Invariants: " << endl; 00052 cout << " Euler Characteristics : " << euler0 << endl; 00053 cout << " Surface Area : " << area0 << endl; 00054 00055 // *************************************************************************** 00056 // Mesh connectivity must be consistent: Condition: Strict 00057 // *************************************************************************** 00058 00059 if( !mesh->is_consistently_oriented() ) 00060 mesh->make_consistently_oriented(); 00061 00062 // Initial mesh may have different connectivity. Condition Strict 00063 size_t ninvert = mesh->count_inverted_faces(); 00064 size_t numfaces = mesh->getSize(2); 00065 00066 if( ninvert > 0.5*numfaces ) mesh->reverse(); 00067 00068 // **************************************************************************** 00069 // Initial mesh may have doublets, remove them, they are troublesome: Condition Strict 00070 // **************************************************************************** 00071 size_t ncount; 00072 ncount = remove_interior_doublets(); 00073 cout << "Info: # of doublets removed : " << ncount << endl; 00074 00075 // **************************************************************************** 00076 // Check the boundary nodes connectivity, and ensure that all elements adjacent 00077 // to them are convex. Singlet must be called after doublets removal ... 00078 // **************************************************************************** 00079 ncount = remove_boundary_singlets(); 00080 cout << "Info: # of singlets removed : " << ncount << endl; 00081 assert( mesh->is_consistently_oriented() ); 00082 00083 00084 // *************************************************************************** 00085 // Perform some local operations: Condition: Soft. Diamonds must be called after the 00086 // vertex deduction operation, otherewise, face-close operation might increase the 00087 // vertex degrees. 00088 // *************************************************************************** 00089 int ncount1, ncount2; 00090 00091 while(1) { 00092 while(1) { 00093 mopt.shape_optimize( mesh ); 00094 ncount1 = remove_diamonds(); 00095 cout << "Info: # of Diamonds removed : " << ncount << endl; 00096 assert( mesh->is_consistently_oriented() ); 00097 if( ncount1 == 0) break; 00098 } 00099 00100 // *************************************************************************** 00101 // Perform vertex degree reduction with local edge swapping: Soft. 00102 // *************************************************************************** 00103 00104 while(1) { 00105 mopt.shape_optimize( mesh ); 00106 ncount2 = vertex_degree_reduction(); 00107 cout << "#of edges swapped: " << ncount2 << endl; 00108 assert( mesh->is_consistently_oriented() ); 00109 if( ncount2 == 0) break; 00110 } 00111 if( ncount1 + ncount2 == 0) break; 00112 } 00113 mesh->saveAs( "alllocal.off"); 00114 return 0; 00115 00116 // **************************************************************************** 00117 // Perform Global remeshing to elimate 3 and 5 degree nodes .. 00118 // **************************************************************************** 00119 err = remesh_defective_patches(); 00120 00121 mesh->prune(); 00122 assert( mesh->is_consistently_oriented() ); 00123 mopt.shape_optimize( mesh ); 00124 00125 // Throughout the cleaning process, euler characteristic should remain same 00126 int euler1 = mesh->getEulerCharacteristic(); // Invariant 00127 00128 // Total area of the domain must be same ... 00129 double area1 = mesh->getSurfaceArea(); 00130 00131 cout << "Mesh Invariants : " << endl; 00132 cout << " Euler Characteristics : " << euler1 << endl; 00133 cout << " Surface Area : " << area1 << endl; 00134 00135 return 0; 00136 } 00137 00139 00140 void 00141 Jaal::set_regular_node_tag(Mesh *mesh, const string &name) 00142 { 00143 int relexist = mesh->build_relations(0, 2); 00144 00145 size_t numnodes = mesh->getSize(0); 00146 for (size_t i = 0; i < numnodes; i++) { 00147 Vertex *vertex = mesh->getNodeAt(i); 00148 int nsize = vertex->getNumRelations(2); 00149 if (nsize >= 6) vertex->setAttribute( name , 0); 00150 if (nsize == 4) vertex->setAttribute( name , 1); 00151 if (nsize < 4) vertex->setAttribute( name , 2); 00152 if (nsize == 5) vertex->setAttribute( name , 3); 00153 } 00154 00155 if (!relexist) 00156 mesh->clear_relations(0, 2); 00157 } 00158 00160 00161 int 00162 QuadCleanUp::reduce_boundary_vertex_degree( Vertex *vertex ) 00163 { 00164 if (!vertex->isBoundary() || !vertex->isActive() ) return 1; 00165 00166 int vdegree = vertex->getNumRelations(0); 00167 00168 if ( vdegree <= (vertex->get_ideal_face_degree(Face::QUADRILATERAL)+1) ) return 2; 00169 00170 NodeSequence vneighs, wneighs; 00171 vertex->getRelations( vneighs ); 00172 00173 // First try with swapping edges .... 00174 for (int k = 0; k < vdegree; k++) { 00175 vneighs[k]->getRelations( wneighs ); 00176 if (!vneighs[k]->isBoundary() && wneighs.size() > 3) { 00177 SwapQuadEdge edge(mesh, vertex, vneighs[k]); 00178 int err = edge.apply_bound_rule(); 00179 if (!err) return 0; 00180 } 00181 } 00182 00183 00184 // If failed, try to close one of the face. 00185 FaceSequence vfaces; 00186 vertex->getRelations( vfaces ); 00187 for( size_t i = 0; i < vfaces.size(); i++) { 00188 Face *face = vfaces[i]; 00189 int pos = face->getPosOf(vertex); 00190 Vertex *v1 = face->getNodeAt( pos + 1 ); 00191 Vertex *v3 = face->getNodeAt( pos + 3 ); 00192 if( !v1->isBoundary() && !v3->isBoundary() ) { 00193 FaceClose closeface(mesh, face, v1, v3); 00194 if( closeface.build() == 0) { 00195 if( closeface.commit() == 0) return 0; 00196 } 00197 } 00198 } 00199 00200 return 3; 00201 } 00202 00204 00205 int 00206 QuadCleanUp::boundary_vertex_degree_reduction_once() 00207 { 00208 int relexist0 = mesh->build_relations(0, 0); 00209 int relexist2 = mesh->build_relations(0, 2); 00210 00211 mesh->search_boundary(); 00212 00213 size_t numnodes = mesh->getSize(0); 00214 00215 size_t ncount = 0; 00216 for (size_t i = 0; i < numnodes; i++) { 00217 Vertex *vertex = mesh->getNodeAt(i); 00218 int err = reduce_boundary_vertex_degree( vertex ); 00219 if( !err) ncount++; 00220 } 00221 00222 if (!relexist0) 00223 mesh->clear_relations(0, 0); 00224 00225 if (!relexist2) 00226 mesh->clear_relations(0, 2); 00227 00228 return ncount; 00229 } 00230 00232 int 00233 QuadCleanUp::reduce_internal_vertex_degree( Vertex *vertex ) 00234 { 00235 if (vertex->isBoundary() || !vertex->isActive() ) return 1; 00236 00237 int nSize = vertex->getNumRelations(0); 00238 if( nSize <= 4) return 2; 00239 00240 NodeSequence vneighs, wneighs; 00241 vertex->getRelations( vneighs ); 00242 00243 sort(vneighs.begin(), vneighs.end(), HighVertexDegreeCompare()); 00244 00245 for (int k = 0; k < nSize; k++) { 00246 vneighs[k]->getRelations( wneighs ); 00247 if (wneighs.size() > 3) { 00248 SwapQuadEdge edge(mesh, vertex, vneighs[k]); 00249 int err = edge.apply_reduce_degree_rule(); 00250 if (!err) return 0; 00251 } 00252 } 00253 00254 return 3; 00255 } 00256 00258 00259 int 00260 QuadCleanUp::internal_vertex_degree_reduction_once() 00261 { 00262 int relexist0 = mesh->build_relations(0, 0); 00263 int relexist2 = mesh->build_relations(0, 2); 00264 mesh->search_boundary(); 00265 00266 NodeSequence nodes; 00267 mesh->getNodes( nodes ); 00268 00269 sort(nodes.begin(), nodes.end(), HighVertexDegreeCompare()); 00270 00271 size_t numnodes = nodes.size(); 00272 00273 size_t ncount = 0; 00274 for (size_t i = 0; i < numnodes; i++) { 00275 Vertex *vertex = nodes[i]; 00276 int err = reduce_internal_vertex_degree( vertex ); 00277 if( !err ) ncount++; 00278 } 00279 00280 if (!relexist0) 00281 mesh->clear_relations(0, 0); 00282 00283 if (!relexist2) 00284 mesh->clear_relations(0, 2); 00285 00286 return ncount; 00287 } 00288 00290 00291 int 00292 QuadCleanUp::vertex_degree_reduction() 00293 { 00294 cout << "#Irregular Nodes " << mesh->count_irregular_nodes(4) << endl; 00295 00296 int ncount = 0; 00297 while (1) { 00298 int ncount1 = boundary_vertex_degree_reduction_once(); 00299 int ncount2 = internal_vertex_degree_reduction_once(); 00300 if (ncount1 + ncount2 == 0) break; 00301 ncount += (ncount1 + ncount2 ); 00302 } 00303 00304 cout << "#Edges Swapped : " << ncount << endl; 00305 cout << "#Irregular Nodes " << mesh->count_irregular_nodes(4) << endl; 00306 00307 return ncount; 00308 } 00309 00311 00312 FaceSequence 00313 QuadCleanUp::search_flat_quads() 00314 { 00315 size_t numfaces = mesh->getSize(2); 00316 00317 int relexist = mesh->build_relations(0, 2); 00318 00319 mesh->search_boundary(); 00320 00321 assert(mesh->getAdjTable(0, 2)); 00322 00323 FaceSequence flatQ, neighs; 00324 00325 int edgefaces[4]; 00326 (void) edgefaces; 00327 for (size_t iface = 0; iface < numfaces; iface++) { 00328 Face *face = mesh->getFaceAt(iface); 00329 assert(face); 00330 if (face->getSize(0) == 4) { 00331 int boundary = 1; 00332 for (int j = 0; j < 4; j++) { 00333 Vertex *vb = face->getNodeAt(j); 00334 if (!vb->isBoundary()) { 00335 boundary = 0; 00336 break; 00337 } 00338 } 00339 00340 if (boundary) { 00341 int bound_edges = 0; 00342 for (int j = 0; j < 4; j++) { 00343 Vertex *v0 = face->getNodeAt(j + 0); 00344 Vertex *v1 = face->getNodeAt(j + 1); 00345 Mesh::getRelations112(v0, v1, neighs); 00346 if (neighs.size() == 1) 00347 bound_edges++; 00348 edgefaces[j] = neighs.size(); 00349 } 00350 00351 if (bound_edges == 3) { 00352 /* 00353 Point3D v1 = make_vector( neighs[0], node ); 00354 Point3D v2 = make_vector( neighs[1], node ); 00355 double angle = getVectorAngle(v1,v2); 00356 if( angle > cutOffAngle ) 00357 degree2nodes.push_back(node); 00358 flatQ.push_back(face); 00359 */ 00360 } 00361 00362 } 00363 } 00364 } 00365 00366 if (!relexist) 00367 mesh->clear_relations(0, 2); 00368 00369 cout << "Number of flat Quads " << flatQ.size() << endl; 00370 return flatQ; 00371 } 00372 00374 00375 FaceSequence 00376 QuadCleanUp::search_restricted_faces() 00377 { 00378 size_t numfaces = mesh->getSize(2); 00379 00380 mesh->search_boundary(); 00381 00382 FaceSequence restricted_faces; 00383 00384 for (size_t i = 0; i < numfaces; i++) { 00385 Face *face = mesh->getFaceAt(i); 00386 if( face->isActive() ) { 00387 Vertex *v0 = face->getNodeAt(0); 00388 Vertex *v1 = face->getNodeAt(1); 00389 Vertex *v2 = face->getNodeAt(2); 00390 Vertex *v3 = face->getNodeAt(3); 00391 if ((v0->isBoundary() && v2->isBoundary()) || (v1->isBoundary() && v3->isBoundary())) { 00392 restricted_faces.push_back(face); 00393 } 00394 } 00395 } 00396 00397 cout << "Info: Number of restricted faces detected : " << restricted_faces.size() << endl; 00398 00399 return restricted_faces; 00400 } 00401 00403 00404 /* 00405 int 00406 RestrictedEdge::build() 00407 { 00408 assert(connect[0] != NULL); 00409 assert(connect[1] != NULL); 00410 00411 Vertex *resnode = connect[0]; 00412 Vertex *bndnode = connect[1]; 00413 00414 assert(!resnode->isBoundary()); 00415 assert(bndnode->isBoundary()); 00416 00417 FaceSequence vneighs; 00418 bndnode->getRelations( vneighs ); 00419 if (vneighs.size() != 2) return 2; 00420 00421 adjFaces[0] = vneighs[0]; 00422 adjFaces[1] = vneighs[1]; 00423 00424 Face *face0 = vneighs[0]; 00425 if (face0->isRemoved()) return 3; 00426 00427 int pos0 = face0->getPosOf(bndnode); 00428 assert(pos0 >= 0); 00429 Vertex *v0 = face0->getNodeAt(pos0 + 2); 00430 00431 Face *face1 = vneighs[1]; 00432 if (face1->isRemoved()) return 4; 00433 int pos1 = face1->getPosOf(bndnode); 00434 assert(pos1 >= 0); 00435 Vertex *v2 = face1->getNodeAt(pos1 + 2); 00436 00437 double area_before = face0->getArea() + face1->getArea(); 00438 00439 // One new node will be inserted :: 00440 Vertex *vnew = Vertex::newObject(); 00441 Point3D xyz; 00442 Vertex::mid_point(v0, v2, xyz); 00443 vnew->setXYZCoords(xyz); 00444 newNodes.resize(1); 00445 newNodes[0] = vnew; 00446 00447 // Three new faces will be created ... 00448 newFaces.resize(3); 00449 00450 Face *newface; 00451 NodeSequence connect(4); 00452 00453 // Face : 1 00454 connect[0] = resnode; 00455 connect[1] = v0; 00456 connect[2] = vnew; 00457 connect[3] = v2; 00458 00459 newface = Face::newObject(); 00460 newface->setNodes(connect); 00461 newFaces[0] = newface; 00462 00463 // Face : 2 00464 Vertex *v3 = NULL; 00465 if (face0->getNodeAt(pos0 + 1) == resnode) 00466 v3 = face0->getNodeAt(pos0 + 3 ); 00467 00468 if (face0->getNodeAt(pos0 + 3) == resnode) 00469 v3 = face0->getNodeAt(pos0 + 1); 00470 00471 assert(v3); 00472 connect[0] = vnew; 00473 connect[1] = v0; 00474 connect[2] = v3; 00475 connect[3] = bndnode; 00476 00477 newface = Face::newObject(); 00478 newface->setNodes(connect); 00479 newFaces[1] = newface; 00480 00481 // Face : 3 00482 Vertex *v4 = NULL; 00483 if (face1->getNodeAt(pos1 + 1) == resnode) 00484 v4 = face1->getNodeAt(pos1 + 3); 00485 00486 if (face1->getNodeAt(pos1 + 3) == resnode) 00487 v4 = face1->getNodeAt(pos1 + 1); 00488 00489 assert(v4); 00490 connect[0] = vnew; 00491 connect[1] = bndnode; 00492 connect[2] = v4; 00493 connect[3] = v2; 00494 00495 newface = Face::newObject(); 00496 newface->setNodes(connect); 00497 newFaces[2] = newface; 00498 00499 double area_after = 0.0; 00500 for (int i = 0; i < 3; i++) 00501 area_after += newFaces[i]->getArea(); 00502 00503 if (fabs(area_after - area_before) > 1.0E-10) { 00504 delete newFaces[0]; 00505 delete newFaces[1]; 00506 delete newFaces[2]; 00507 newFaces.clear(); 00508 return 4; 00509 } 00510 00511 for (int i = 0; i < 3; i++) { 00512 if (!newFaces[i]->isConvex()) { 00513 delete newFaces[0]; 00514 delete newFaces[1]; 00515 delete newFaces[2]; 00516 newFaces.clear(); 00517 return 5; 00518 } 00519 } 00520 00521 return 0; 00522 } 00523 */ 00524 00526 00527 void 00528 QuadCleanUp::cleanup_internal_boundary_face() 00529 { 00530 int relexist = mesh->build_relations(0, 2); 00531 00532 size_t numfaces = mesh->getSize(2); 00533 00534 FaceSequence boundfaces; 00535 00536 for (size_t i = 0; i < numfaces; i++) { 00537 Face *face = mesh->getFaceAt(i); 00538 if (face->hasBoundaryNode()) { 00539 int nfnodes = face->getSize(0); 00540 Vertex *v0 = NULL; 00541 Vertex *v1 = NULL; 00542 for (int j = 0; j < nfnodes; j++) { 00543 Vertex *v = face->getNodeAt(j); 00544 if (v->isBoundary()) { 00545 v0 = face->getNodeAt( j + 1 ); 00546 v1 = face->getNodeAt( j + 3 ); 00547 if (!v0->isBoundary() && !v1->isBoundary()) { 00548 FaceClose closeface(mesh, face, v0, v1); 00549 break; 00550 } 00551 } 00552 } 00553 } 00554 } 00555 00556 mesh->prune(); 00557 00558 if (!relexist) 00559 mesh->clear_relations(0, 2); 00560 } 00561 00563 00564 int QuadCleanUp::refine_degree3_faces() 00565 { 00566 int relexist2 = mesh->build_relations(0, 2); 00567 00568 size_t numnodes = mesh->getSize(0); 00569 00570 Vertex *vertex; 00571 FaceSequence vfaces; 00572 for (size_t i = 0; i < numnodes; i++) { 00573 vertex = mesh->getNodeAt(i); 00574 vertex->getRelations( vfaces ); 00575 int nsize = vfaces.size(); 00576 if ( nsize == 3) { 00577 for (int j = 0; j < nsize; j++) { 00578 vertex = vfaces[j]->getNodeAt(0); 00579 if (vertex->getNumRelations(2) > 4) continue; 00580 00581 vertex = vfaces[j]->getNodeAt(1); 00582 if (vertex->getNumRelations(2) > 4) continue; 00583 00584 vertex = vfaces[j]->getNodeAt(2); 00585 if (vertex->getNumRelations(2) > 4) continue; 00586 00587 vertex = vfaces[j]->getNodeAt(3); 00588 if (vertex->getNumRelations(2) > 4) continue; 00589 00590 mesh->refine_quad15(vfaces[j]); 00591 } 00592 } 00593 } 00594 mesh->prune(); 00595 mesh->collect_garbage(); 00596 00597 if (!relexist2) 00598 mesh->clear_relations(0, 2); 00599 00600 return 0; 00601 } 00602 00604 00605 void QuadCleanUp::report() 00606 { 00607 if (mesh == NULL) return; 00608 cout << "Info: Reporting mesh information " << endl; 00609 cout << "#Nodes " << mesh->getSize(0) << endl; 00610 cout << "#Faces " << mesh->getSize(2) << endl; 00611 mesh->get_topological_statistics(); 00612 cout << "#Irregular Nodes (internal) " << mesh->count_irregular_nodes(4) << endl; 00613 cout << "#Concave Quads : " << mesh->count_concave_faces() << endl; 00614 00615 } 00616 00618 /* 00619 void QuadCleanUp :: build_irregular_nodes_set() 00620 { 00621 // Get all the irregular nodes from the mesh ( only the internal ones ); 00622 irregular_nodes_set.clear(); 00623 NodeSequence nset = mesh->get_irregular_nodes(4 ); 00624 for( size_t i = 0; i < nset.size(); i++) 00625 irregular_nodes_set.insert( nset[i] ); 00626 00627 } 00628 */ 00629 00631 00632 00633 #ifdef REMOVE_LATER 00634 00635 int QuadCleanUp::has_interior_nodes_degree_345() 00636 { 00637 int relexist = mesh->build_relations(0, 2); 00638 00639 assert(mesh->getAdjTable(0, 2)); 00640 00641 size_t numnodes = mesh->getSize(0); 00642 00643 vector<int> degree(numnodes); 00644 FaceSequence neighs; 00645 for (size_t i = 0; i < numnodes; i++) { 00646 Vertex *v = mesh->getNodeAt(i); 00647 neighs = v->getRelations2(); 00648 if( neighs.size() < 3 || neighs.size() > 5 ) return 0; 00649 } 00650 00651 return 1; 00652 } 00654 00655 int 00656 QuadCleanUp::free_restricted_nodes_once() 00657 { 00658 vector<Vertex*> vrestrict = search_restricted_nodes (); 00659 00660 if (vrestrict.size () == 0) return 0; 00661 00662 int relexist0 = mesh->build_relations (0, 0); 00663 int relexist2 = mesh->build_relations (0, 2); 00664 00665 vector<Vertex*> vneighs; 00666 vector<RestrictedEdge> redges; 00667 00668 for (size_t i = 0; i < vrestrict.size (); i++) { 00669 Vertex *vertex = vrestrict[i]; 00670 vneighs = vertex->getRelations0 (); 00671 for (size_t j = 0; j < vneighs.size (); j++) { 00672 if (vneighs[j]->isBoundary ()) { 00673 RestrictedEdge edge (mesh, vertex, vneighs[j]); 00674 int err = edge.build (); 00675 if (!err) { 00676 redges.push_back (edge); 00677 } 00678 } 00679 } 00680 } 00681 00682 if (redges.size ()) 00683 cout << "Info: # of valid restricted edges : " << redges.size () << endl; 00684 00685 int ncount = 0; 00686 for (size_t i = 0; i < redges.size (); i++) { 00687 int err = redges[i].commit (); 00688 if (!err) ncount++; 00689 } 00690 00691 if (ncount) { 00692 mesh->prune (); 00693 mesh->enumerate (0); 00694 mesh->enumerate (2); 00695 cout << "Info: # of restricted edges committed : " << ncount << endl; 00696 } 00697 00698 if (!relexist0) 00699 mesh->clear_relations (0, 0); 00700 00701 if (!relexist2) 00702 mesh->clear_relations (0, 2); 00703 00704 return ncount; 00705 return 1; 00706 } 00707 00709 00710 void 00711 QuadCleanUp::free_restricted_nodes() 00712 { 00713 int ncount; 00714 while (1) { 00715 ncount = free_restricted_nodes_once(); 00716 if (ncount == 0) break; 00717 } 00718 00719 if (!mesh->isConsistentlyOriented()) 00720 mesh->makeConsistentlyOriented(); 00721 } 00722 00724 00725 void 00726 QuadCleanUp::cleanup_boundary(double cutOffAngle) 00727 { 00728 int rel0exist = mesh->build_relations(0, 0); 00729 int rel2exist = mesh->build_relations(0, 2); 00730 00731 mesh->search_boundary(); 00732 mesh->setFeatureLength(); 00733 00734 Point3D pf, pb, pn; 00735 double flen, len, t; 00736 00737 size_t numnodes = mesh->getSize(0); 00738 00739 NodeSequence bound_neighs, free_neighs; 00740 FaceSequence vfaces; 00741 00742 NodeSequence updated; 00743 00744 for (int iter = 0; iter < 10; iter++) { 00745 updated.clear(); 00746 00747 for (size_t i = 0; i < numnodes; i++) { 00748 Vertex *bndnode = mesh->getNodeAt(i); 00749 if (bndnode->isBoundary()) { 00750 bound_neighs = bndnode->getRelations0(); 00751 for (size_t j = 0; j < bound_neighs.size(); j++) { 00752 Vertex *freenode = bound_neighs[j]; 00753 if (!freenode->isBoundary()) { 00754 free_neighs = freenode->getRelations0(); 00755 int ncount = 0; 00756 for (size_t k = 0; k < free_neighs.size(); k++) 00757 if (free_neighs[k]->isBoundary()) ncount++; 00758 if (ncount == 1) { 00759 flen = bndnode->getFeatureLength(); 00760 len = Vertex::length(bndnode, freenode); 00761 if (len > 2.0 * flen) { 00762 pf = freenode->getXYZCoords(); 00763 pb = bndnode->getXYZCoords(); 00764 t = 0.75; 00765 pn[0] = t * pf[0] + (1 - t) * pb[0]; 00766 pn[1] = t * pf[1] + (1 - t) * pb[1]; 00767 pn[2] = t * pf[2] + (1 - t) * pb[2]; 00768 freenode->setXYZCoords(pn); 00769 vfaces = freenode->getRelations2(); 00770 bool pass = 1; 00771 for (size_t iface = 0; iface < vfaces.size(); iface++) { 00772 if (!vfaces[iface]->isConvex()) { 00773 pass = 0.0; 00774 break; 00775 } 00776 } 00777 if (!pass) { 00778 freenode->setXYZCoords(pf); 00779 } else 00780 updated.push_back(freenode); 00781 } 00782 } 00783 } 00784 } 00785 } 00786 } 00787 00788 if (updated.empty()) break; 00789 00790 for (size_t i = 0; i < updated.size(); i++) 00791 updated[i]->setConstrainedMark(1); 00792 00793 lapsmooth->execute(); 00794 00795 for (size_t i = 0; i < updated.size(); i++) 00796 updated[i]->setConstrainedMark(0); 00797 00798 } 00799 00800 if (!rel0exist) 00801 mesh->clear_relations(0, 0); 00802 00803 if (!rel2exist) 00804 mesh->clear_relations(0, 2); 00805 00806 return; 00807 00809 // First try to handle flat node... 00811 00812 NodeSequence degree2nodes; 00813 00814 00815 Vertex* node, *onode; 00816 for (size_t i = 0; i < numnodes; i++) { 00817 node = mesh->getNodeAt(i); 00818 if (node->isBoundary()) { 00819 neighs = node->getRelations0(); 00820 if (neighs.size() == 2) { 00821 if (neighs[0]->isBoundary() && neighs[1]->isBoundary()) { 00822 Point3D v1 = make_vector(neighs[0], node); 00823 Point3D v2 = make_vector(neighs[1], node); 00824 double angle = Math::getVectorAngle(v1, v2); 00825 if (angle > cutOffAngle) 00826 degree2nodes.push_back(node); 00827 } 00828 } 00829 } 00830 } 00831 00832 00833 relexist = mesh->build_relations(0, 2); 00834 00835 Face *boundface; 00836 FaceSequence faceneighs; 00837 for (size_t i = 0; i < degree2nodes.size(); i++) { 00838 node = degree2nodes[i]; 00839 faceneighs = node->getRelations2(); 00840 if (faceneighs.size() == 1) { 00841 boundface = faceneighs[0]; 00842 if (boundface->getSize(0) == 4) { 00843 int j = boundface->getPosOf(node); 00844 onode = boundface->getNodeAt((j + 2) % 4); 00845 if (!onode->isBoundary()) 00846 insert_doublet(boundface, node, onode); 00847 } 00848 } 00849 } 00850 00851 mesh->prune(); 00852 mesh->enumerate(0); 00853 mesh->enumerate(2); 00854 00855 if (!relexist) 00856 mesh->clear_relations(0, 2); 00857 00858 mesh->setBoundaryKnown(0); 00859 } 00860 00861 #endif 00862 00864 int QuadCleanUp :: shift_irregular_nodes() 00865 { 00866 int rel0exist = mesh->build_relations(0, 0); 00867 int rel2exist = mesh->build_relations(0, 2); 00868 00869 mesh->setWavefront(0); 00870 mesh->setWavefront(2); 00871 00872 while(1) { 00873 int ncount = 0; 00874 size_t numnodes = mesh->getSize(0); 00875 for( size_t i = 0; i < numnodes; i++) { 00876 Vertex *v = mesh->getNodeAt(i); 00877 if( !v->isRemoved() && v->getNumRelations(2) == 3 ) { 00878 int err = apply_shift_node3_rule(v); 00879 if( !err ) ncount++; 00880 } 00881 } 00882 if( ncount == 0) break; 00883 } 00884 00885 if (!rel0exist) mesh->clear_relations(0, 0); 00886 if (!rel2exist) mesh->clear_relations(0, 2); 00887 00888 return 0; 00889 } 00891 00892 int QuadCleanUp::apply_shift_node3_rule(Vertex *vertex) 00893 { 00894 #ifdef CHANGE_IT 00895 if( vertex->isRemoved() ) return 1; 00896 00897 int layerID = vertex->getLayerID(); 00898 00899 FaceSequence vfaces; 00900 vertex->getRelations( vfaces ); 00901 if (vfaces.size() != 3) return 1; 00902 00903 // Find the face inside the domain i.e. in the higher level.. 00904 Face *face = NULL; 00905 for (size_t i = 0; i < vfaces.size(); i++) { 00906 if (vfaces[i]->getLayerID() == layerID) { 00907 face = vfaces[i]; 00908 break; 00909 } 00910 } 00911 if (face == NULL) return 1; 00912 00913 int pos = face->getPosOf(vertex); 00914 assert(pos >= 0); 00915 00916 Vertex *opp_vertex = face->getNodeAt(pos + 2); 00917 00918 int nopp = opp_vertex->getNumRelations(2); 00919 // if ( nopp == 3) return refine_3434_pattern(face, pos); 00920 if ( nopp == 4) return refine_3444_pattern(face, pos); 00921 if ( nopp == 5) return refine_3454_pattern(face, pos); 00922 #endif 00923 return 0; 00924 } 00925 00927 00928 int QuadCleanUp::refine_3434_pattern(Face *face, int pos) 00929 { 00930 #ifdef CHANGE 00931 Point3D xyz; 00932 NodeSequence localnodes(10); 00933 for( int i = 0; i < 10; i++) 00934 localnodes[i] = NULL; 00935 00936 localnodes[0] = face->getNodeAt(pos + 0); 00937 localnodes[1] = face->getNodeAt(pos + 1); 00938 localnodes[2] = face->getNodeAt(pos + 2); 00939 localnodes[3] = face->getNodeAt(pos + 3); 00940 00941 int layerid = localnodes[0]->getLayerID(); 00942 00943 if (localnodes[1]->getLayerID() != layerid) return 1; 00944 if (localnodes[2]->getLayerID() <= layerid) return 1; 00945 if (localnodes[3]->getLayerID() != layerid) return 1; 00946 00947 if( localnodes[0]->getNumRelations(2) != 3 ) return 1; 00948 if( localnodes[1]->getNumRelations(2) != 4 ) return 1; 00949 if( localnodes[2]->getNumRelations(2) != 3 ) return 1; 00950 if( localnodes[3]->getNumRelations(2) != 4 ) return 1; 00951 00952 Face *neigh1 = NULL; 00953 Face *neigh2 = NULL; 00954 00955 FaceSequence adjFaces; 00956 00957 Mesh::getRelations112(localnodes[1], localnodes[2], adjFaces); 00958 assert( adjFaces.size() == 2 ) ; 00959 00960 if (adjFaces[0] == face) neigh1 = adjFaces[1]; 00961 if (adjFaces[1] == face) neigh1 = adjFaces[0]; 00962 localnodes[4] = Face::opposite_node(neigh1, localnodes[2]); 00963 localnodes[5] = Face::opposite_node(neigh1, localnodes[1]); 00964 00965 Mesh::getRelations112(localnodes[2], localnodes[3], adjFaces); 00966 assert( adjFaces.size() == 2); 00967 00968 if (adjFaces[0] == face) neigh2 = adjFaces[1]; 00969 if (adjFaces[1] == face) neigh2 = adjFaces[0]; 00970 localnodes[6] = Face::opposite_node(neigh2, localnodes[2]); 00971 00972 xyz = Vertex::mid_point(localnodes[0], localnodes[2]); 00973 localnodes[9] = Vertex::newObject(); 00974 localnodes[9]->setXYZCoords(xyz); 00975 00976 xyz = Vertex::mid_point(localnodes[9], localnodes[1]); 00977 localnodes[7] = Vertex::newObject(); 00978 localnodes[7]->setXYZCoords(xyz); 00979 00980 xyz = Vertex::mid_point(localnodes[9], localnodes[3]); 00981 localnodes[8] = Vertex::newObject(); 00982 localnodes[8]->setXYZCoords(xyz); 00983 00984 assert( neigh1 ); 00985 assert( neigh2 ); 00986 00987 Face * newfaces[5]; 00988 NodeSequence connect(4); 00989 00990 connect[0] = localnodes[0]; 00991 connect[1] = localnodes[1]; 00992 connect[2] = localnodes[7]; 00993 connect[3] = localnodes[9]; 00994 newfaces[0] = Face::newObject(); 00995 newfaces[0]->setNodes(connect); 00996 00997 connect[0] = localnodes[1]; 00998 connect[1] = localnodes[4]; 00999 connect[2] = localnodes[5]; 01000 connect[3] = localnodes[7]; 01001 newfaces[1] = Face::newObject(); 01002 newfaces[1]->setNodes(connect); 01003 01004 connect[0] = localnodes[0]; 01005 connect[1] = localnodes[9]; 01006 connect[2] = localnodes[8]; 01007 connect[3] = localnodes[3]; 01008 newfaces[2] = Face::newObject(); 01009 newfaces[2]->setNodes(connect); 01010 01011 connect[0] = localnodes[3]; 01012 connect[1] = localnodes[8]; 01013 connect[2] = localnodes[5]; 01014 connect[3] = localnodes[6]; 01015 newfaces[3] = Face::newObject(); 01016 newfaces[3]->setNodes(connect); 01017 01018 connect[0] = localnodes[9]; 01019 connect[1] = localnodes[7]; 01020 connect[2] = localnodes[5]; 01021 connect[3] = localnodes[8]; 01022 newfaces[4] = Face::newObject(); 01023 newfaces[4]->setNodes(connect); 01024 01025 int pass = 1; 01026 for( int i = 0; i < 5; i++) { 01027 if (!newfaces[i]->isSimple() ) pass = 0; 01028 } 01029 01030 if( ! pass ) { 01031 cout << " 3434 Effort failed " << endl; 01032 for( int i = 0; i < 5; i++) delete newfaces[i]; 01033 delete localnodes[7]; 01034 delete localnodes[8]; 01035 delete localnodes[9]; 01036 return 1; 01037 } 01038 01039 mesh->remove( face ); 01040 mesh->remove( neigh1 ); 01041 mesh->remove( neigh2 ); 01042 01043 mesh->remove ( localnodes[2] ); // Caused by doublet .. 01044 mesh->addNode( localnodes[7] ); 01045 mesh->addNode( localnodes[8] ); 01046 mesh->addNode( localnodes[9] ); 01047 for( int i = 0; i < 5; i++) mesh->addFace( newfaces[i] ); 01048 01049 // Update front levels ... 01050 localnodes[7]->setLayerID(layerid + 1); 01051 localnodes[8]->setLayerID(layerid + 1); 01052 localnodes[9]->setLayerID(layerid + 1); 01053 01054 newfaces[0]->setLayerID(layerid); 01055 newfaces[1]->setLayerID(layerid); 01056 newfaces[2]->setLayerID(layerid + 1); 01057 newfaces[3]->setLayerID(layerid + 1); 01058 newfaces[4]->setLayerID(layerid + 2); 01059 #endif 01060 01061 return 0; 01062 } 01063 01064 01065 int QuadCleanUp::refine_3454_pattern(Face *face, int pos) 01066 { 01067 #ifdef CHANGE 01068 Point3D xyz; 01069 NodeSequence localnodes(13); 01070 01071 localnodes[0] = face->getNodeAt(pos + 0); 01072 localnodes[1] = face->getNodeAt(pos + 1); 01073 localnodes[2] = face->getNodeAt(pos + 2); 01074 localnodes[3] = face->getNodeAt(pos + 3); 01075 01076 int layerid = localnodes[0]->getLayerID(); 01077 01078 if (localnodes[1]->getLayerID() != layerid) return 1; 01079 if (localnodes[2]->getLayerID() <= layerid) return 1; 01080 if (localnodes[3]->getLayerID() != layerid) return 1; 01081 01082 if( localnodes[0]->getNumRelations(2) != 3 ) return 1; 01083 if( localnodes[1]->getNumRelations(2) != 4 ) return 1; 01084 if( localnodes[2]->getNumRelations(2) != 5 ) return 1; 01085 if( localnodes[3]->getNumRelations(2) != 4 ) return 1; 01086 01087 Face *neigh1 = NULL; 01088 Face *neigh2 = NULL; 01089 Face *neigh3 = NULL; 01090 Face *neigh4 = NULL; 01091 01092 FaceSequence adjFaces; 01093 01094 Mesh::getRelations112(localnodes[1], localnodes[2], adjFaces); 01095 assert( adjFaces.size() == 2 ) ; 01096 01097 if (adjFaces[0] == face) neigh1 = adjFaces[1]; 01098 if (adjFaces[1] == face) neigh1 = adjFaces[0]; 01099 localnodes[4] = Face::opposite_node(neigh1, localnodes[2]); 01100 localnodes[5] = Face::opposite_node(neigh1, localnodes[1]); 01101 xyz = Vertex::mid_point(localnodes[2], localnodes[5]); 01102 localnodes[11] = Vertex::newObject(); 01103 localnodes[11]->setXYZCoords(xyz); 01104 01105 Mesh::getRelations112(localnodes[2], localnodes[5], adjFaces); 01106 assert( adjFaces.size() == 2); 01107 01108 if (adjFaces[0] == neigh1) neigh2 = adjFaces[1]; 01109 if (adjFaces[1] == neigh1) neigh2 = adjFaces[0]; 01110 localnodes[8] = Face::opposite_node(neigh2, localnodes[2]); 01111 localnodes[9] = Face::opposite_node(neigh2, localnodes[5]); 01112 01113 Mesh::getRelations112(localnodes[2], localnodes[3], adjFaces); 01114 assert( adjFaces.size() == 2); 01115 01116 if (adjFaces[0] == face) neigh3 = adjFaces[1]; 01117 if (adjFaces[1] == face) neigh3 = adjFaces[0]; 01118 localnodes[6] = Face::opposite_node(neigh3, localnodes[3]); 01119 localnodes[7] = Face::opposite_node(neigh3, localnodes[2]); 01120 xyz = Vertex::mid_point(localnodes[2], localnodes[6]); 01121 localnodes[12] = Vertex::newObject(); 01122 localnodes[12]->setXYZCoords(xyz); 01123 01124 Mesh::getRelations112(localnodes[2], localnodes[6], adjFaces); 01125 assert( adjFaces.size() == 2); 01126 01127 if (adjFaces[0] == neigh3) neigh4 = adjFaces[1]; 01128 if (adjFaces[1] == neigh3) neigh4 = adjFaces[0]; 01129 localnodes[10] = Face::opposite_node(neigh4, localnodes[2]); 01130 01131 assert( neigh1 ); 01132 assert( neigh2 ); 01133 assert( neigh3 ); 01134 assert( neigh4 ); 01135 01136 Face * newfaces[7]; 01137 NodeSequence connect(4); 01138 01139 connect[0] = localnodes[0]; 01140 connect[1] = localnodes[1]; 01141 connect[2] = localnodes[11]; 01142 connect[3] = localnodes[2]; 01143 newfaces[0] = Face::newObject(); 01144 newfaces[0]->setNodes(connect); 01145 01146 connect[0] = localnodes[1]; 01147 connect[1] = localnodes[4]; 01148 connect[2] = localnodes[5]; 01149 connect[3] = localnodes[11]; 01150 newfaces[1] = Face::newObject(); 01151 newfaces[1]->setNodes(connect); 01152 01153 connect[0] = localnodes[11]; 01154 connect[1] = localnodes[5]; 01155 connect[2] = localnodes[8]; 01156 connect[3] = localnodes[9]; 01157 newfaces[2] = Face::newObject(); 01158 newfaces[2]->setNodes(connect); 01159 01160 connect[0] = localnodes[0]; 01161 connect[1] = localnodes[2]; 01162 connect[2] = localnodes[12]; 01163 connect[3] = localnodes[3]; 01164 newfaces[3] = Face::newObject(); 01165 newfaces[3]->setNodes(connect); 01166 01167 connect[0] = localnodes[3]; 01168 connect[1] = localnodes[12]; 01169 connect[2] = localnodes[6]; 01170 connect[3] = localnodes[7]; 01171 newfaces[4] = Face::newObject(); 01172 newfaces[4]->setNodes(connect); 01173 01174 connect[0] = localnodes[6]; 01175 connect[1] = localnodes[12]; 01176 connect[2] = localnodes[9]; 01177 connect[3] = localnodes[10]; 01178 newfaces[5] = Face::newObject(); 01179 newfaces[5]->setNodes(connect); 01180 01181 connect[0] = localnodes[2]; 01182 connect[1] = localnodes[11]; 01183 connect[2] = localnodes[9]; 01184 connect[3] = localnodes[12]; 01185 newfaces[6] = Face::newObject(); 01186 newfaces[6]->setNodes(connect); 01187 01188 int pass = 1; 01189 for( int i = 0; i < 7; i++) { 01190 if (newfaces[i]->concaveAt() >= 0) pass = 0; 01191 } 01192 01193 if( ! pass ) { 01194 cout << "Effort failed " << endl; 01195 for( int i = 0; i < 7; i++) delete newfaces[i]; 01196 delete localnodes[11]; 01197 delete localnodes[12]; 01198 return 1; 01199 } 01200 01201 mesh->remove( face ); 01202 mesh->remove( neigh1 ); 01203 mesh->remove( neigh2 ); 01204 mesh->remove( neigh3 ); 01205 mesh->remove( neigh4 ); 01206 01207 mesh->addNode( localnodes[11] ); 01208 mesh->addNode( localnodes[12] ); 01209 for( int i = 0; i < 7; i++) mesh->addFace( newfaces[i] ); 01210 01211 /* 01212 // Do backup of Coordinates. Only 11 nodes to be backed up. 01213 Point3D backupCoords[11]; 01214 for (int i = 0; i < 11; i++) 01215 backupCoords[i] = localnodes[i]->getXYZCoords(); 01216 01217 Face * backupFaces[5]; 01218 vfaces = localnodes[2]->getRelations2(); 01219 for (int i = 0; i < 5; i++) 01220 { 01221 backupFaces[i] = vfaces[i]; 01222 mesh->remove(vfaces[i]); // Goes to garbage but not deallocated. 01223 } 01224 01225 // Update new nodes and faces ... 01226 mesh->addNode(localnodes[11]); 01227 mesh->addNode(localnodes[12]); 01228 for (int i = 0; i < 7; i++) 01229 mesh->addFace(newfaces[i]); 01230 01231 LaplaceLengthWeight lw; 01232 LaplaceSmoothing lapsmooth(mesh); 01233 lapsmooth.setWeight(&lw); 01234 lapsmooth.setNumIterations(10); 01235 lapsmooth.localized_at(localnodes); 01236 01237 set<Face*> faces_to_check; 01238 for (int i = 0; i < 13; i++) 01239 { 01240 FaceSequence vfaces = localnodes[i]->getRelations2(); 01241 for (int j = 0; j < vfaces.size(); j++) 01242 faces_to_check.insert(vfaces[j]); 01243 } 01244 01245 bool pass = 1; 01246 set<Face*>::const_iterator siter; 01247 for (siter = faces_to_check.begin(); siter != faces_to_check.end(); ++siter) 01248 { 01249 Face *f = *siter; 01250 if (f->invertedAt() >= 0) 01251 { 01252 pass = 0; 01253 break; 01254 } 01255 } 01256 01257 if (!pass) 01258 { 01259 for (int i = 0; i < 7; i++) 01260 mesh->remove(newfaces[i]); 01261 01262 for (int i = 0; i < 5; i++) 01263 mesh->addFace(backupFaces[i]); // Reactivated now ... 01264 01265 for (int i = 0; i < 11; i++) 01266 localnodes[i]->setXYZCoords(backupCoords[i]); 01267 01268 mesh->remove(localnodes[11]); 01269 mesh->remove(localnodes[12]); 01270 return 1; 01271 } 01272 */ 01273 01274 // Update front levels ... 01275 localnodes[11]->setLayerID(layerid + 1); 01276 localnodes[12]->setLayerID(layerid + 1); 01277 01278 newfaces[0]->setLayerID(layerid); 01279 newfaces[1]->setLayerID(layerid); 01280 newfaces[2]->setLayerID(layerid + 1); 01281 01282 newfaces[3]->setLayerID(layerid); 01283 newfaces[4]->setLayerID(layerid); 01284 newfaces[5]->setLayerID(layerid + 1); 01285 01286 newfaces[6]->setLayerID(layerid + 1); 01287 #endif 01288 01289 return 0; 01290 } 01291 01293 01294 int QuadCleanUp::refine_3444_pattern(Face *face, int pos) 01295 { 01296 #ifdef CHANGE 01297 Point3D xyz; 01298 NodeSequence localnodes(12); 01299 01300 localnodes[0] = face->getNodeAt( pos + 0 ); 01301 localnodes[1] = face->getNodeAt( pos + 1 ); 01302 localnodes[2] = face->getNodeAt( pos + 2 ); 01303 localnodes[3] = face->getNodeAt( pos + 3 ); 01304 01305 int layerid = localnodes[0]->getLayerID(); 01306 01307 if (localnodes[1]->getLayerID() != layerid) return 1; 01308 if (localnodes[2]->getLayerID() <= layerid) return 1; 01309 if (localnodes[3]->getLayerID() != layerid) return 1; 01310 01311 if( localnodes[0]->getNumRelations(2) != 3) return 1; 01312 if( localnodes[1]->getNumRelations(2) != 4) return 1; 01313 if( localnodes[2]->getNumRelations(2) != 4) return 1; 01314 if( localnodes[3]->getNumRelations(2) != 4) return 1; 01315 01316 Face *neigh1 = NULL; 01317 Face *neigh2 = NULL; 01318 Face *neigh3 = NULL; 01319 01320 FaceSequence adjFaces; 01321 01322 Mesh::getRelations112(localnodes[1], localnodes[2], adjFaces); 01323 if (adjFaces.size() != 2) return 1; 01324 01325 if (adjFaces[0] == face) neigh1 = adjFaces[1]; 01326 if (adjFaces[1] == face) neigh1 = adjFaces[0]; 01327 localnodes[4] = Face::opposite_node(neigh1, localnodes[2]); 01328 localnodes[5] = Face::opposite_node(neigh1, localnodes[1]); 01329 01330 xyz = Vertex::mid_point(localnodes[2], localnodes[5]); 01331 localnodes[9] = Vertex::newObject(); 01332 localnodes[9]->setXYZCoords(xyz); 01333 01334 Mesh::getRelations112(localnodes[2], localnodes[5], adjFaces); 01335 if (adjFaces.size() != 2) return 1; 01336 if (adjFaces[0] == neigh1) neigh2 = adjFaces[1]; 01337 if (adjFaces[1] == neigh1) neigh2 = adjFaces[0]; 01338 localnodes[8] = Face::opposite_node(neigh2, localnodes[2]); 01339 01340 Mesh::getRelations112(localnodes[2], localnodes[3], adjFaces); 01341 if (adjFaces.size() != 2) return 1; 01342 if (adjFaces[0] == face) neigh3 = adjFaces[1]; 01343 if (adjFaces[1] == face) neigh3 = adjFaces[0]; 01344 localnodes[6] = Face::opposite_node(neigh3, localnodes[3]); 01345 localnodes[7] = Face::opposite_node(neigh3, localnodes[2]); 01346 xyz = Vertex::mid_point(localnodes[2], localnodes[6]); 01347 localnodes[11] = Vertex::newObject(); 01348 localnodes[11]->setXYZCoords(xyz); 01349 01350 xyz = Vertex::mid_point(localnodes[2], localnodes[8]); 01351 localnodes[10] = Vertex::newObject(); 01352 localnodes[10]->setXYZCoords(xyz); 01353 01354 Face * newfaces[7]; 01355 NodeSequence connect(4); 01356 01357 connect[0] = localnodes[0]; 01358 connect[1] = localnodes[1]; 01359 connect[2] = localnodes[9]; 01360 connect[3] = localnodes[2]; 01361 newfaces[0] = Face::newObject(); 01362 newfaces[0]->setNodes(connect); 01363 01364 connect[0] = localnodes[1]; 01365 connect[1] = localnodes[4]; 01366 connect[2] = localnodes[5]; 01367 connect[3] = localnodes[9]; 01368 newfaces[1] = Face::newObject(); 01369 newfaces[1]->setNodes(connect); 01370 01371 connect[0] = localnodes[9]; 01372 connect[1] = localnodes[5]; 01373 connect[2] = localnodes[8]; 01374 connect[3] = localnodes[10]; 01375 newfaces[2] = Face::newObject(); 01376 newfaces[2]->setNodes(connect); 01377 01378 connect[0] = localnodes[0]; 01379 connect[1] = localnodes[2]; 01380 connect[2] = localnodes[11]; 01381 connect[3] = localnodes[3]; 01382 newfaces[3] = Face::newObject(); 01383 newfaces[3]->setNodes(connect); 01384 01385 connect[0] = localnodes[3]; 01386 connect[1] = localnodes[11]; 01387 connect[2] = localnodes[6]; 01388 connect[3] = localnodes[7]; 01389 newfaces[4] = Face::newObject(); 01390 newfaces[4]->setNodes(connect); 01391 01392 connect[0] = localnodes[6]; 01393 connect[1] = localnodes[11]; 01394 connect[2] = localnodes[10]; 01395 connect[3] = localnodes[8]; 01396 newfaces[5] = Face::newObject(); 01397 newfaces[5]->setNodes(connect); 01398 01399 connect[0] = localnodes[2]; 01400 connect[1] = localnodes[9]; 01401 connect[2] = localnodes[10]; 01402 connect[3] = localnodes[11]; 01403 newfaces[6] = Face::newObject(); 01404 newfaces[6]->setNodes(connect); 01405 01406 int pass = 1; 01407 for( int i = 0; i < 7; i++) { 01408 if (newfaces[i]->concaveAt() >= 0) pass = 0; 01409 } 01410 01411 if( ! pass ) { 01412 cout << " Effort failed " << endl; 01413 for( int i = 0; i < 7; i++) delete newfaces[i]; 01414 delete localnodes[9]; 01415 delete localnodes[10]; 01416 delete localnodes[11]; 01417 return 1; 01418 } 01419 01420 mesh->remove( face ); 01421 mesh->remove( neigh1 ); 01422 mesh->remove( neigh2 ); 01423 mesh->remove( neigh3 ); 01424 01425 mesh->addNode( localnodes[9] ); 01426 mesh->addNode( localnodes[10] ); 01427 mesh->addNode( localnodes[11] ); 01428 01429 for( int i = 0; i < 7; i++) mesh->addFace( newfaces[i] ); 01430 01431 /* 01432 Point3D backupCoords[9]; 01433 for (int i = 0; i < 9; i++) 01434 backupCoords[i] = localnodes[i]->getXYZCoords(); 01435 01436 Face * backupFaces[4]; 01437 vfaces = localnodes[2]->getRelations2(); 01438 for (int i = 0; i < 4; i++) 01439 { 01440 backupFaces[i] = vfaces[i]; 01441 mesh->remove(vfaces[i]); // Send to garbage, but don't delete .. 01442 } 01443 01444 // Update the data structures ... 01445 mesh->addNode(localnodes[9]); 01446 mesh->addNode(localnodes[10]); 01447 mesh->addNode(localnodes[11]); 01448 for (int i = 0; i < 7; i++) 01449 mesh->addFace(newfaces[i]); 01450 01451 LaplaceLengthWeight lw; 01452 LaplaceSmoothing lapsmooth(mesh); 01453 lapsmooth.setWeight(&lw); 01454 lapsmooth.setNumIterations(10); 01455 lapsmooth.localized_at(localnodes); 01456 01457 FaceSet faces_to_check; 01458 for (int i = 0; i < 12; i++) 01459 { 01460 FaceSequence vfaces = localnodes[i]->getRelations2(); 01461 for (int j = 0; j < vfaces.size(); j++) 01462 faces_to_check.insert(vfaces[j]); 01463 } 01464 01465 bool pass = 1; 01466 set<Face*>::const_iterator siter; 01467 for (siter = faces_to_check.begin(); siter != faces_to_check.end(); ++siter) 01468 { 01469 Face *f = *siter; 01470 if (f->invertedAt() >= 0) 01471 { 01472 pass = 0; 01473 break; 01474 } 01475 } 01476 01477 if (!pass) 01478 { 01479 for (int i = 0; i < 7; i++) 01480 mesh->remove(newfaces[i]); 01481 01482 for (int i = 0; i < 4; i++) 01483 mesh->addFace(backupFaces[i]); 01484 01485 for (int i = 0; i < 9; i++) 01486 localnodes[i]->setXYZCoords(backupCoords[i]); 01487 01488 mesh->remove(localnodes[9]); 01489 mesh->remove(localnodes[10]); 01490 mesh->remove(localnodes[11]); 01491 01492 return 1; 01493 } 01494 */ 01495 // Update front levels ... 01496 localnodes[9]->setLayerID(layerid + 1); 01497 localnodes[10]->setLayerID(layerid + 2); 01498 localnodes[11]->setLayerID(layerid + 1); 01499 01500 newfaces[0]->setLayerID(layerid); 01501 newfaces[1]->setLayerID(layerid); 01502 newfaces[2]->setLayerID(layerid + 1); 01503 01504 newfaces[3]->setLayerID(layerid); 01505 newfaces[4]->setLayerID(layerid); 01506 newfaces[5]->setLayerID(layerid + 1); 01507 01508 newfaces[6]->setLayerID(layerid + 1); 01509 #endif 01510 01511 return 0; 01512 } 01513