MeshKit
1.0
|
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