MeshKit  1.0
FaceClose.cpp
Go to the documentation of this file.
00001 #include "meshkit/QuadCleanUp.hpp"
00002 
00003 using namespace Jaal;
00004 
00006 
00007 void
00008 Jaal::set_diamond_tag(Mesh *mesh, const string &aname)
00009 {
00010      QuadCleanUp qClean(mesh);
00011      vector<Diamond> diamonds = qClean.search_diamonds();
00012 
00013      cout << "#Dianonds " << diamonds.size() << endl;
00014 
00015      size_t numfaces = mesh->getSize(2);
00016      for (size_t i = 0; i < numfaces; i++) {
00017           Face *face = mesh->getFaceAt(i);
00018           if( face->isActive() )
00019                face->setAttribute( aname, 0);
00020      }
00021 
00022      set<Face*>::const_iterator it;
00023      for (size_t i = 0; i < diamonds.size(); i++) {
00024           Face *face = diamonds[i].face;
00025           if( face->isActive() )
00026                face->setAttribute( aname, 1);
00027      }
00028 }
00029 
00031 bool
00032 FaceClose::isSafe() const
00033 {
00034      if (!face->isActive()) return 0;
00035 
00036      if (!vertex0->isActive()) return 0;
00037      if (!vertex2->isActive()) return 0;
00038 
00039      if (vertex0->isBoundary()) return 0;
00040      if (vertex2->isBoundary()) return 0;
00041 
00042      int vpos = face->getPosOf(vertex0);
00043      assert(vpos >= 0);
00044 
00045      if (face->getNodeAt(vpos + 2) != vertex2) {
00046           cout << "Warning: Face-open requires opposite vertices " << endl;
00047           cout << "Debug  : Face is : " << face->getNodeAt(0)->getID() << " "
00048                << face->getNodeAt(1)->getID() << " "
00049                << face->getNodeAt(2)->getID() << " "
00050                << face->getNodeAt(3)->getID() << endl;
00051           cout << "Opposite ends are " << vertex0->getID() << " " << vertex2->getID() << endl;
00052           return 1;
00053      }
00054 
00055      assert(face->hasNode(vertex0));
00056      assert(face->hasNode(vertex2));
00057 
00058      FaceSequence neighs;
00059      vertex0->getRelations( neighs );
00060      int nSize = neighs.size();
00061      for (int  j = 0; j < nSize; j++) {
00062           if (neighs[j] != face) {
00063                int val0 = neighs[j]->hasNode(vertex0);
00064                int val1 = neighs[j]->hasNode(vertex2);
00065                if (val0 + val1 == 2) return 0;
00066           }
00067      }
00068 
00069      vertex2->getRelations( neighs );
00070      nSize = neighs.size();
00071      for (int j = 0; j < nSize; j++) {
00072           if (neighs[j] != face) {
00073                int val0 = neighs[j]->hasNode(vertex0);
00074                int val1 = neighs[j]->hasNode(vertex2);
00075                if (val0 + val1 == 2) return 0;
00076           }
00077      }
00078 
00079      return 1;
00080 }
00081 
00083 
00084 int
00085 FaceClose::build()
00086 {
00087      if (!isSafe()) return 1;
00088 
00089      assert(face->getSize(0) == 4);
00090 
00091      Vertex *v0 = vertex0;
00092      Vertex *v2 = vertex2;
00093 
00094      Point3D p0 = v0->getXYZCoords();
00095      Point3D p2 = v2->getXYZCoords();
00096 
00097      Point3D p3d;
00098      Vertex::mid_point(v0, v2, p3d);
00099 
00100      // Both nodes will merge at the same point...
00101      vertex0->setXYZCoords(p3d);
00102      vertex2->setXYZCoords(p3d);
00103 
00104      int pass = 1;
00105 
00106      FaceSequence vfaces;
00107      if( pass ) {
00108           vertex0->getRelations( vfaces );
00109           for( size_t i = 0; i < vfaces.size(); i++) {
00110                if( vfaces[i] !=  face ) {
00111                     if (vfaces[i]->concaveAt() >= 0) {
00112                          pass = 0;
00113                          break;
00114                     }
00115                }
00116           }
00117      }
00118 
00119      if( pass ) {
00120           vertex2->getRelations( vfaces );
00121           for( size_t i = 0; i < vfaces.size(); i++) {
00122                if( vfaces[i] !=  face ) {
00123                     if (vfaces[i]->concaveAt() >= 0) {
00124                          pass = 0;
00125                          break;
00126                     }
00127                }
00128           }
00129      }
00130 
00131      if( !pass ) {
00132           vertex0->setXYZCoords( p0 );
00133           vertex2->setXYZCoords( p2 );
00134           return 1;
00135      }
00136 
00137      replacedNode = Vertex::newObject();
00138      replacedNode->setXYZCoords(p3d);
00139 
00140      return 0;
00141 }
00142 
00144 
00145 int
00146 FaceClose::commit()
00147 {
00148      assert(mesh->getAdjTable(0, 2));
00149 
00150      if (replacedNode == NULL) return 1;
00151 
00152      mesh->addNode(replacedNode);
00153 
00154      NodeSequence fnodes;
00155      FaceSequence vfaces;
00156      vertex0->getRelations( vfaces );
00157      size_t nSize = vfaces.size();
00158 
00159      for (size_t i = 0; i < nSize; i++) {
00160           if (vfaces[i] != face) {
00161                fnodes = vfaces[i]->getNodes();
00162                int nv = fnodes.size();
00163                for( int j = 0; j < nv; j++)  {
00164                     if( fnodes[j] == vertex0) {
00165                          fnodes[j] = replacedNode;
00166                     }
00167                }
00168                mesh->deactivate(vfaces[i]);  // remove all existing relationships.
00169                vfaces[i]->setNodes( fnodes );
00170                mesh->reactivate(vfaces[i]);  // rebuilds new relationships.
00171           }
00172      }
00173 
00174      vertex2->getRelations( vfaces );
00175      nSize = vfaces.size();
00176      for (size_t i = 0; i < vfaces.size(); i++) {
00177           if (vfaces[i] != face) {
00178                fnodes = vfaces[i]->getNodes();
00179                int nv = fnodes.size();
00180                for( int j = 0; j < nv; j++)   {
00181                     if( fnodes[j] == vertex2) {
00182                          fnodes[j] = replacedNode;
00183                     }
00184                }
00185                mesh->deactivate(vfaces[i]); // remove all existing relatioships
00186                vfaces[i]->setNodes( fnodes );
00187                mesh->reactivate(vfaces[i]); // rebuilds new relationships..
00188           }
00189      }
00190 
00191      // Two nodes and face go away from the mesh..
00192      mesh->remove(face);
00193      mesh->remove(vertex0);
00194      mesh->remove(vertex2);
00195 
00196      replacedNode = NULL; // So that destructor can delete if this is not used.
00197 
00198      return 0;
00199 }
00200 
00202 
00203 bool
00204 QuadCleanUp::isDiamond(Face *face, int &pos, int type)
00205 {
00206      pos = -1;
00207      const Vertex *v0 = face->getNodeAt(0);
00208      const Vertex *v1 = face->getNodeAt(1);
00209      const Vertex *v2 = face->getNodeAt(2);
00210      const Vertex *v3 = face->getNodeAt(3);
00211 
00212      int d0 = v0->getNumRelations(2);
00213      int d1 = v1->getNumRelations(2);
00214      int d2 = v2->getNumRelations(2);
00215      int d3 = v3->getNumRelations(2);
00216 
00217      // Boundary Cases ...
00218      if (v0->isBoundary() || v2->isBoundary()) {
00219           if( d0 <= v0->get_ideal_face_degree( Face::QUADRILATERAL ) ) return 0;
00220           if( d2 <= v2->get_ideal_face_degree( Face::QUADRILATERAL ) ) return 0;
00221           if (!v1->isBoundary() && !v3->isBoundary()) {
00222                if (d1 == 3 && d3 == 3) {
00223                     pos = 1;
00224                     return 1;
00225                }
00226           }
00227      }
00228 
00229      if (v1->isBoundary() || v3->isBoundary()) {
00230           if( d1 <= v1->get_ideal_face_degree( Face::QUADRILATERAL ) ) return 0;
00231           if( d3 <= v3->get_ideal_face_degree( Face::QUADRILATERAL ) ) return 0;
00232 
00233           if (!v0->isBoundary() && !v2->isBoundary()) {
00234                if ((d0 == 3 && d2 == 3)) {
00235                     pos = 0;
00236                     return 1;
00237                }
00238           }
00239      }
00240 
00241      if (v0->isBoundary()) return 0;
00242      if (v1->isBoundary()) return 0;
00243      if (v2->isBoundary()) return 0;
00244      if (v3->isBoundary()) return 0;
00245 
00246      if( type == 33 ) {
00247           if ((d0 == 3 && d2 == 3)) {
00248                if( d1 < 4 || d3 < 4)  return 0;
00249                pos = 0;
00250                return 1;
00251           }
00252 
00253           if (d1 == 3 && d3 == 3) {
00254                if( d0 < 4 || d2 < 4)  return 0;
00255                pos = 1;
00256                return 1;
00257           }
00258      }
00259 
00260      if( type == 34 ) {
00261           if ( (d0 == 3 && d2 == 4) || ( d0 == 4 && d2 == 3)) {
00262                if( d1 < 4 || d3 < 4)  return 0;
00263                pos = 0;
00264                return 1;
00265           }
00266 
00267           if ( (d1 == 4 && d3 == 3) || (d1 == 3 && d3 == 4)) {
00268                if( d0 < 4 || d2 < 4)  return 0;
00269                pos = 1;
00270                return 1;
00271           }
00272      }
00273 
00274      if( type == 55 ) {
00275           if (d1 == 5 && d3 == 5) {
00276                if ((d0 == 3 && d2 == 4) || (d0 == 4 && d2 == 3)) {
00277                     pos = 0;
00278                     return 1;
00279                }
00280           }
00281 
00282           if (d0 == 5 && d2 == 5) {
00283                if ((d1 == 3 && d3 == 4) || (d1 == 4 && d3 == 3)) {
00284                     pos = 1;
00285                     return 1;
00286                }
00287           }
00288      }
00289 
00290      return 0;
00291 }
00292 
00294 
00295 vector<Diamond>
00296 QuadCleanUp::search_diamonds(int type)
00297 {
00298      if (!mesh->isPruned()) mesh->prune();
00299 
00300      size_t numfaces = mesh->getSize(2);
00301 
00302      mesh->search_boundary();
00303 
00304      int relexist = mesh->build_relations(0, 2);
00305 
00306      int pos;
00307 
00308      assert(mesh->isBoundaryKnown());
00309 
00310      vDiamonds.clear();
00311      for (size_t iface = 0; iface < numfaces; iface++) {
00312           Face *face = mesh->getFaceAt(iface);
00313           if (isDiamond(face, pos, type)) {
00314                Diamond diamond(mesh, face, pos);
00315                vDiamonds.push_back(diamond);
00316           }
00317      }
00318 
00319      if (!relexist)
00320           mesh->clear_relations(0, 2);
00321 
00322      if (vDiamonds.size())
00323           cout << "# of Diamonds : " << vDiamonds.size() << endl;
00324 
00325      return vDiamonds;
00326 }
00327 
00329 
00330 int
00331 Diamond::build()
00332 {
00333      faceclose = new FaceClose(mesh, face, vertex0, vertex2);
00334      return faceclose->build();
00335 }
00336 
00338 
00339 int
00340 Diamond::commit()
00341 {
00342      if (faceclose) {
00343           int err = faceclose->commit();
00344           delete faceclose;
00345           faceclose = NULL;
00346           return err;
00347      }
00348 
00349      return 1;
00350 }
00352 
00353 int
00354 QuadCleanUp::remove_diamonds_once()
00355 {
00356      // Essential step because only the faces are updated.
00357      size_t numfaces = mesh->getSize(2);
00358      for (size_t i = 0; i < numfaces; i++) {
00359           Face *face = mesh->getFaceAt(i);
00360           face->setVisitMark(0);
00361      }
00362 
00363      int err, pos, ncount = 0;
00364 
00365      for (size_t i = 0; i < numfaces; i++) {
00366           Face *face = mesh->getFaceAt(i);
00367           if(face->isActive() ) {
00368                if (isDiamond(face, pos)) {
00369                     Diamond diamond(mesh, face, pos);
00370                     err = diamond.build();
00371                     if (!err) {
00372                          err = diamond.commit();
00373                          if (!err) ncount++;
00374                     }
00375                }
00376           }
00377      }
00378 
00379      return ncount;
00380 }
00381 
00383 int
00384 QuadCleanUp::degree_5_dominated()
00385 {
00386      cout << "Info: Removing type 34 Diamonds ... " << endl;
00387      int rel0exist = mesh->build_relations(0, 0); // Need for laplace smoothing
00388      int rel2exist = mesh->build_relations(0, 2);
00389 
00390      mesh->search_boundary();
00391 
00392      // Essential step because only the faces are updated.
00393      size_t numfaces = mesh->getSize(2);
00394      for (size_t i = 0; i < numfaces; i++) {
00395           Face *face = mesh->getFaceAt(i);
00396           face->setVisitMark(0);
00397      }
00398 
00399      int err, pos, nfound = 0, ncommit = 0;
00400 
00401      for (size_t i = 0; i < numfaces; i++) {
00402           Face *face = mesh->getFaceAt(i);
00403           if( face->isActive() ) {
00404                if (isDiamond(face, pos, 34)) {
00405                     nfound++;
00406                     Diamond diamond(mesh, face, pos);
00407                     err = diamond.build();
00408                     if (!err) {
00409                          err = diamond.commit();
00410                          if (!err) ncommit++;
00411                     }
00412                }
00413           }
00414      }
00415      cout << "#Diamonds found " << nfound << " and removed : " << ncommit << endl;
00416 
00417      if (!rel0exist) mesh->clear_relations(0, 0);
00418      if (!rel2exist) mesh->clear_relations(0, 2);
00419 
00420      return ncommit;
00421 }
00422 
00424 
00425 
00426 int
00427 QuadCleanUp::remove_diamonds_in_layer(int layerid)
00428 {
00429 
00430 #ifdef CHANGE
00431      // Essential step because only the faces are updated only.
00432      size_t numfaces = mesh->getSize(2);
00433      for (size_t i = 0; i < numfaces; i++) {
00434           Face *face = mesh->getFaceAt(i);
00435           face->setVisitMark(0);
00436      }
00437 
00438      int err, pos, ncount = 0;
00439 
00440      size_t faceid = 0;
00441      while (1) {
00442           if (faceid >= mesh->getSize(2)) break;
00443           Face *face = mesh->getFaceAt(faceid);
00444           if (face->getLayerID() == layerid) {
00445                if (isDiamond(face, pos)) {
00446                     Diamond diamond(mesh, face, pos);
00447                     err = diamond.build();
00448                     if (!err) {
00449                          err = diamond.commit();
00450                          if (!err) ncount++;
00451                     }
00452                }
00453           }
00454           faceid++;
00455      }
00456 
00457      vDiamonds.clear();
00458 
00459      return ncount;
00460 #endif
00461      return 0;
00462 }
00463 
00465 
00466 int
00467 QuadCleanUp::remove_diamonds()
00468 {
00469      int rel0exist = mesh->build_relations(0, 0); // Need for laplace smoothing
00470      int rel2exist = mesh->build_relations(0, 2);
00471 
00472      mesh->search_boundary();
00473 
00474      int ncount1 = 0;
00475      while (1) {
00476           int ncount = remove_diamonds_once();
00477           if (ncount == 0) break;
00478           ncount1 += ncount;
00479      }
00480 
00481      if (!rel0exist) mesh->clear_relations(0, 0);
00482      if (!rel2exist) mesh->clear_relations(0, 2);
00483 
00484      cout << "Info: Diamonds removed ... " << ncount1 << endl;
00485    
00486 
00487 
00488      return ncount1;
00489 }
00490 
00492 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines