MeshKit  1.0
QuadPatches.cpp
Go to the documentation of this file.
00001 #include "meshkit/Mesh.hpp"
00002 
00003 using namespace Jaal;
00004 
00005 //
00006 // QTrack is similar to "Motorcycle graph" proposed by Eppestein group.
00007 // But somehow, I don't like this term.
00008 //
00009 
00010 #ifdef CSV
00011 struct QTrack {
00012     const static int END_AT_TERMINALS = 0;
00013     const static int END_AT_CROSSINGS = 1;
00014 
00015     NodeSequence sequence;
00016 
00017     bool operator ==(const QTrack & rhs) const {
00018         size_t nSize = sequence.size();
00019         if (nSize != rhs.sequence.size()) return 0;
00020 
00021         Vertex *v0src = sequence.front();
00022         Vertex *v0dst = sequence.back();
00023         Vertex *v1src = rhs.sequence.front();
00024         Vertex *v1dst = rhs.sequence.back();
00025 
00026         if (v0src == v1src && v0dst == v1dst) return 1;
00027         if (v0src == v1dst && v0dst == v1src) return 1;
00028 
00029         return 0;
00030     }
00031 
00032     bool operator<(const QTrack & rhs) const {
00033         return sequence.size() < rhs.sequence.size();
00034     }
00035 
00037     // There are two ways to advance along the track.
00038     // (1) Incremental:  All track propagate simulateneously and
00039     //                   at the intersection, only one is allowed
00040     //                   to proceed towards other irregular node.
00041     // (11) Greedy   :   Start from one vertex and complete its
00042     //                   track.
00043     // It is not clear which method is better, but "greedy" may likely
00044     // give very high aspect ratio quad patches. Incremental on the
00045     // other hand may produce many small patches..
00046     //
00048 
00049     int advance_single_step(int endat) {
00051         //                   **********************
00052         //                   *         *          *
00053         //                   *         * Next     *
00054         //                   *         *          *
00055         //           Avoid   **********************  Avoid
00056         //                   *         *          *
00057         //                   *         * Current  *
00058         //                   *         *          *
00059         //                   *         *          *
00060         //                   **********************
00061         //                            Source
00062         // A Source vertex and Current edge is chosen.
00063         // We want to avoid two edges and want to select "Next" edge.
00065         Vertex *v0, *v1, *v2, *v3, *v4;
00066 
00067         vector<Face*> adjFaces;
00068         vector<Vertex*> vneighs;
00069         set<Vertex*> vset;
00070 
00071         size_t index = sequence.size();
00072         v0 = sequence[index - 2];
00073         v1 = sequence[index - 1];
00074         v0->setVisitMark(1);
00075 
00076         if (endat == END_AT_CROSSINGS && v1->isVisited()) return 0;
00077         if (v1->isBoundary()) return 0;
00078 
00079         v1->setVisitMark(1);
00080         vneighs = v1->getRelations0();
00081         if (vneighs.size() != 4) return 0;
00082 
00083         adjFaces = Mesh::getRelations112(v0, v1);
00084         assert(adjFaces.size() == 2);
00085         v2 = Face::opposite_node(adjFaces[0], v0);
00086         v3 = Face::opposite_node(adjFaces[1], v0);
00087 
00088         vset.clear();
00089         vset.insert(vneighs[0]);
00090         vset.insert(vneighs[1]);
00091         vset.insert(vneighs[2]);
00092         vset.insert(vneighs[3]);
00093         vset.erase(v0);
00094         vset.erase(v2);
00095         vset.erase(v3);
00096         assert(vset.size() == 1);
00097         v4 = *vset.begin();
00098         sequence.push_back(v4);
00099         return 1;
00100     }
00101 
00102     void advance(int endat) {
00103         assert(sequence.size() == 2);
00104 
00105         // Starting node is always irregular ...
00106         vector<Face*> vfaces = sequence[0]->getRelations2();
00107         assert(vfaces.size() != 4);
00108 
00109         while (1) {
00110             int progress = advance_single_step(endat);
00111             if (!progress) break;
00112         }
00113 
00114 /*
00115         // The path is reversible and therefore, we will give a direction
00116         // from the lower source node to higher destination node.
00117         if (sequence.front() > sequence.back())
00118             reverse(sequence.begin(), sequence.end());
00119         assert(sequence.front() < sequence.back());
00120 */
00121         // Checking the correctness..
00122         if (endat == END_AT_TERMINALS) {
00123             vfaces = sequence.front()->getRelations2();
00124             assert(vfaces.size() != 4);
00125             vfaces = sequence.back()->getRelations2();
00126             assert(vfaces.size() != 4);
00127             for (int i = 1; i < sequence.size() - 1; i++) {
00128                 vfaces = sequence[i]->getRelations2();
00129                 assert(vfaces.size() == 4);
00130             }
00131 
00132         }
00133     }
00134 
00135 };
00136 
00138 
00139 struct StructuredMesh2D {
00140 
00141     StructuredMesh2D() {
00142         nx = ny = 0;
00143     }
00144     int nx, ny;
00145 
00146     vector<Face*> faces;
00147     vector<Vertex*> nodes;
00148     set<Vertex*> cornerNodes;
00149 
00150     void clearAll() {
00151         nodes.clear();
00152         faces.clear();
00153         neighs.clear();
00154         cornerNodes.clear();
00155         nx = 0;
00156         ny = 0;
00157     }
00158 
00159     bool operator<(const StructuredMesh2D & rhs) const {
00160         return this->getSize(2) < rhs.getSize(2);
00161     }
00162 
00163     size_t getSize(int e) const {
00164         if (e == 0) return nodes.size();
00165         if (e == 2) return faces.size();
00166         return 0;
00167     }
00168 
00169     int myID;
00170     vector<int> neighs;
00171 };
00172 #endif
00173 
00175 
00176 void build_submesh_topology(StructuredMesh2D &smesh) 
00177 {
00178 /*
00179     smesh.neighs.clear();
00180 
00181     FaceSequence adjfaces;
00182     set<int> nset;
00183 
00184     size_t numFaces = smesh.faces.size();
00185     for (size_t i = 0; i < numFaces; i++) {
00186         Face *face = smesh.faces[i];
00187         for (int j = 0; j < 4; j++) {
00188             Vertex *v0 = face->getNodeAt(j + 0);
00189             Vertex *v1 = face->getNodeAt(j + 1);
00190             Mesh::getRelations112(v0, v1, adjfaces);
00191             int numneighs = adjfaces.size();
00192             for (int k = 0; k < numneighs; k++) {
00193                 int nid = adjfaces[k]->getTag();
00194                 nset.insert(nid);
00195             }
00196         }
00197     }
00198 
00199     nset.erase(smesh.myID);
00200     set<int>::const_iterator it1;
00201     for (it1 = nset.begin(); it1 != nset.end(); ++it1)
00202         smesh.neighs.push_back(*it1);
00203 */
00204 }
00205 
00207 
00208 Face *getSeedFace(Jaal::Mesh *mesh) {
00209     size_t numfaces = mesh->getSize(2);
00210     for (size_t i = 0; i < numfaces; i++) {
00211         Face *f = mesh->getFaceAt(i);
00212         if (!f->isVisited()) return f;
00213     }
00214     return NULL;
00215 }
00216 
00218 
00219 size_t independent_components(Jaal::Mesh *mesh) {
00220 
00221     size_t numfaces = mesh->getSize(2);
00222     size_t numneighs;
00223 
00224     for (size_t i = 0; i < numfaces; i++) {
00225         Face *f = mesh->getFaceAt(i);
00226         f->setVisitMark(0);
00227         f->setAttribute( "Partition", 0);
00228     }
00229 
00230     size_t compid = 0;
00231     deque<Face*> faceQ;
00232     FaceSequence adjfaces;
00233     while (1) {
00234         Face *currface = getSeedFace(mesh);
00235         if (currface == NULL) break;
00236         faceQ.push_back(currface);
00237         while (!faceQ.empty()) {
00238             currface = faceQ.front();
00239             faceQ.pop_front();
00240             if (!currface->isVisited()) {
00241                 currface->setAttribute( "Partition", compid);
00242                 currface->setVisitMark(1);
00243                 for (int i = 0; i < 4; i++) {
00244                     Vertex *v0 = currface->getNodeAt(i + 0);
00245                     Vertex *v1 = currface->getNodeAt(i + 1);
00246                     if (v0->isVisited() && v1->isVisited()) continue;
00247                     Mesh::getRelations112(v0, v1, adjfaces);
00248                     numneighs= adjfaces.size();
00249                     for (size_t j = 0; j < numneighs; j++)
00250                         faceQ.push_back(adjfaces[j]);
00251                 }
00252             }
00253         }
00254         compid++;
00255     }
00256 
00257 #ifdef DEBUG
00258     for (size_t i = 0; i < numfaces; i++) {
00259         Face *f = mesh->getFaceAt(i);
00260         assert(f->isVisited());
00261     }
00262 #endif
00263 
00264     return compid;
00265 }
00266 
00268 
00269 int merge_submesh(StructuredMesh2D &amesh, StructuredMesh2D &bmesh) {
00270     if (amesh.myID == bmesh.myID) return 1;
00271 
00272     if (amesh.cornerNodes.size() != 4) return 2;
00273     if (bmesh.cornerNodes.size() != 4) return 2;
00274 
00275     vector<Vertex*> common;
00276     set_intersection(amesh.cornerNodes.begin(), amesh.cornerNodes.end(),
00277             bmesh.cornerNodes.begin(), bmesh.cornerNodes.end(),
00278             back_inserter(common));
00279 
00280     if (common.size() != 2) return 3;
00281 
00282     size_t numFaces;
00283 
00284     FaceSequence vfaces;
00285     numFaces = amesh.faces.size();
00286     for (size_t i = 0; i < numFaces; i++) {
00287         for (int j = 0; j < 4; j++) {
00288             Vertex *v = amesh.faces[i]->getNodeAt(j);
00289             if (!v->isBoundary()) {
00290                 if ( v->getNumRelations(2) != 4) return 4;
00291             }
00292         }
00293     }
00294 
00295     numFaces = bmesh.faces.size();
00296     for (size_t i = 0; i < numFaces; i++) {
00297         for (int j = 0; j < 4; j++) {
00298             Vertex *v = bmesh.faces[i]->getNodeAt(j);
00299             if (!v->isBoundary()) {
00300                 if ( v->getNumRelations(2) != 4) return 4;
00301             }
00302         }
00303     }
00304 
00305     numFaces = bmesh.faces.size();
00306     for (size_t i = 0; i < numFaces; i++) {
00307         amesh.faces.push_back(bmesh.faces[i]);
00308         bmesh.faces[i]->setAttribute("Partition", amesh.myID);
00309     }
00310 
00311     NodeSet::const_iterator it;
00312     for (it = bmesh.cornerNodes.begin(); it != bmesh.cornerNodes.end(); ++it)
00313         amesh.cornerNodes.insert(*it);
00314 
00315     assert(amesh.cornerNodes.size() == 6);
00316 
00317     amesh.cornerNodes.erase(common[0]);
00318     amesh.cornerNodes.erase(common[1]);
00319 
00320     bmesh.clearAll();
00321 
00322     return 0;
00323 }
00325 
00326 StructuredMesh2D getQuadPatch(Jaal::Mesh *mesh, int compid) {
00327     StructuredMesh2D smesh;
00328     smesh.myID = compid;
00329     smesh.nx = 1;
00330     smesh.ny = 1;
00331 
00332     size_t numfaces = mesh->getSize(2);
00333 
00334     set<Face*> faceSet;
00335     set<Face*>::const_iterator fit;
00336     set<Vertex*> nodeSet;
00337     set<Vertex*>::const_iterator nit;
00338 
00339     int ival = 0;
00340     for (size_t i = 0; i < numfaces; i++) {
00341         Face *face = mesh->getFaceAt(i);
00342         if( face->isActive() ) {
00343         face->getAttribute("Partition", ival );
00344         if ( ival == compid) {
00345             faceSet.insert(face);
00346             nodeSet.insert(face->getNodeAt(0));
00347             nodeSet.insert(face->getNodeAt(1));
00348             nodeSet.insert(face->getNodeAt(2));
00349             nodeSet.insert(face->getNodeAt(3));
00350         }
00351         }
00352     }
00353     if (faceSet.empty()) return smesh;
00354 
00355     NodeSet boundNodes, cornerNodes;
00356     FaceSet boundFaces, cornerFaces;
00357 
00358     FaceSequence vfaces;
00359     int     ncount;
00360     size_t  numneighs;
00361     for (nit = nodeSet.begin(); nit != nodeSet.end(); ++nit) {
00362         Vertex *vertex = *nit;
00363         vertex->getRelations( vfaces);
00364         ncount = 0;
00365         numneighs = vfaces.size();
00366         for (size_t j = 0; j < numneighs; j++)
00367             if (faceSet.find(vfaces[j]) != faceSet.end()) ncount++;
00368 
00369         if (ncount == 1) {
00370             cornerNodes.insert(vertex);
00371             for (size_t j = 0; j < numneighs; j++)
00372                 if (faceSet.find(vfaces[j]) != faceSet.end()) cornerFaces.insert(vfaces[j]);
00373         }
00374 
00375         if (ncount != 4) boundNodes.insert(vertex);
00376     }
00377 
00378     for (fit = faceSet.begin(); fit != faceSet.end(); ++fit)
00379         smesh.faces.push_back(*fit);
00380 
00381     for (nit = nodeSet.begin(); nit != nodeSet.end(); ++nit)
00382         smesh.nodes.push_back(*nit);
00383 
00384     smesh.cornerNodes = cornerNodes;
00385 
00386     build_submesh_topology(smesh);
00387 
00388     return smesh;
00389 
00390 }
00392 
00393 int Mesh::search_quad_patches() 
00394 {
00395     int nTopo = isHomogeneous();
00396     if (nTopo != 4) {
00397         cout << "Error: The mesh must be all Quads " << endl;
00398         return 1;
00399     }
00400 
00401     int relexist2 = build_relations(0, 2);
00402     int relexist0 = build_relations(0, 0);
00403 
00404     search_boundary();
00405 
00406     size_t numnodes = getSize(0);
00407     for (size_t i = 0; i < numnodes; i++) {
00408         Vertex *vertex = getNodeAt(i);
00409         vertex->setVisitMark(0);
00410     }
00411 
00412     size_t numfaces = getSize(2);
00413     for (size_t i = 0; i < numfaces; i++) {
00414         Face *face = getFaceAt(i);
00415         face->setVisitMark(0);
00416     }
00417 
00418     vector<QTrack> qpath;
00419     QTrack qp;
00420     qp.sequence.resize(2); // As we know the starting edge
00421 
00422     size_t nCount = 0;
00423     NodeSequence vnodes;
00424     for (size_t i = 0; i < numnodes; i++) {
00425         Vertex *vertex = getNodeAt(i);
00426         if (!vertex->isBoundary()) {
00427             vertex->getRelations( vnodes );
00428             size_t numneighs = vnodes.size();
00429             if (numneighs  != 4)  {
00430                 qp.sequence[0] = vertex;
00431                 for (size_t j = 0; j < numneighs; j++) {
00432                      qp.sequence[1] = vnodes[j];
00433                      nCount++;
00434                      qpath.push_back(qp);
00435                 }
00436             }
00437         }
00438     }
00439 
00440     if (qpath.empty()) {
00441         cout << "Info: There are no irregular nodes in the mesh" << endl;
00442         return 0;
00443     } else
00444         cout << "# of branches spawned " << nCount << endl;
00445 
00446     for (size_t j = 0; j < qpath.size(); j++) 
00447         qpath[j].advance(0);
00448 
00449     sort(qpath.begin(), qpath.end());
00450 
00451 /*
00452     saveAs("b.dat");
00453     for (int i = 0; i < qpath.size(); i++) {
00454         if (qpath[i].sequence.front()->isBoundary()) continue;
00455         if (qpath[i].sequence.back()->isBoundary() ) continue;
00456         int found = 0;
00457         cout << " PATH SIZE " << qpath[i].sequence.size() << endl;
00458         for (int k = 0; k < qpath[i].sequence.size(); k++)
00459                cout << qpath[i].sequence[k]->getID() << " ";
00460         cout << endl;
00461         for (int j = 0; j < qpath.size(); j++) {
00462             if ((i != j) && (qpath[i] == qpath[j])) {
00463                 found = 1;
00464                 cout << "Same path " << i << " " << j << endl;
00465                 for (int k = 0; k < qpath[j].sequence.size(); k++)
00466                     cout << qpath[j].sequence[k]->getID() << " ";
00467                 cout << endl;
00468             }
00469         }
00470         assert(found);
00471     }
00472 */
00473     exit(0);
00474 
00475     int numPatches = independent_components(this);
00476 
00477     deque<StructuredMesh2D> submesh(numPatches);
00478 
00479     // New we can merge some sub-meshes
00480     for (int i = 0; i < numPatches; i++) {
00481         StructuredMesh2D sm = getQuadPatch(this, i);
00482         submesh[i] = sm;
00483     }
00484     sort(submesh.begin(), submesh.end());
00485 
00486     while (1) {
00487         int  nSize = submesh.size();
00488         cout << "#Submeshes " << submesh.size() << endl;
00489         size_t count_merged = 0;
00490         for (int i = 0; i < nSize; i++) {
00491             for (int j = i + 1; j < nSize; j++) {
00492                 int err = merge_submesh(submesh[i], submesh[j]);
00493                 if (!err) count_merged++;
00494             }
00495         }
00496         cout << " #of Submesh merged " << count_merged << endl;
00497         if (count_merged == 0) break;
00498 
00499         //
00500         // Retain only those submeshes which are not empty. ( Note
00501         // that when two submeshes merge, one of them become empty.
00502         //
00503         for (int i = 0; i < nSize; i++) {
00504             StructuredMesh2D sm = submesh.front();
00505             submesh.pop_front();
00506             if (sm.getSize(2)) submesh.push_back(sm);
00507         }
00508     }
00509 
00510     sort(submesh.begin(), submesh.end());
00511 
00512     exit(0);
00513 
00514     /*
00515     for (size_t i = 0; i < numnodes; i++) {
00516         Vertex *vertex = getNodeAt(i);
00517         vertex->setTag(vertex->isVisited());
00518     }
00519     */
00520 
00521     if (relexist0)
00522         clear_relations(0, 0);
00523 
00524     if (relexist2)
00525         clear_relations(0, 2);
00526     return submesh.size();
00527 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines