MeshKit  1.0
QuadCleanUp.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines