MeshKit
1.0
|
00001 #ifndef MESH_H 00002 #define MESH_H 00003 00004 #include <iostream> 00005 #include <cassert> 00006 #include <fstream> 00007 #include <math.h> 00008 #include <string> 00009 #include <limits> 00010 00011 #include <vector> 00012 #include <list> 00013 #include <map> 00014 #include <set> 00015 #include <deque> 00016 #include <queue> 00017 #include <algorithm> 00018 00019 #include <meshkit/array_qm.hpp> 00020 00021 #ifdef HAVE_MESQUITE 00022 #include <Mesquite_all_headers.hpp> 00023 #endif 00024 00025 #ifdef HAVE_VERDICT 00026 #include <verdict.h> 00027 #endif 00028 00029 #include "meshkit/myany.hpp" 00030 00031 #define FOR_EACH(container, iter ) for(iter = container.begin(); iter != container.end(); ++iter) 00032 00033 #include "basic_math.hpp" 00034 #include "tfiblend.hpp" 00035 00036 #define JAAL_SUCCESS 0 00037 #define JAAL_GEOMETRIC_FAILURE 1 00038 #define JAAL_TOP0LOGICAL_FAILURE 100 00039 00040 #define Break() \ 00041 { \ 00042 cout << "Break in file " << __FILE__ << " at " << __LINE__ << endl; \ 00043 getchar(); \ 00044 } \ 00045 00046 00047 00048 using namespace std; 00049 00050 typedef std::pair<size_t, size_t> FacePair; 00051 00052 #ifdef USE_HASHMAP 00053 #include <tr1/unordered_set> 00054 #include <tr1/unordered_map> 00055 #endif 00056 00057 namespace Jaal { 00058 00059 class Vertex; 00060 class Face; 00061 class Edge; 00062 class Mesh; 00063 00064 typedef Vertex* PNode; 00065 typedef Edge* PEdge; 00066 typedef Face* PFace; 00067 00068 typedef std::vector<PNode> NodeSequence; 00069 typedef std::vector<PEdge> EdgeSequence; 00070 typedef std::vector<PFace> FaceSequence; 00071 00072 typedef std::list<PNode> NodeList; 00073 typedef std::list<PEdge> EdgeList; 00074 typedef std::list<PFace> FaceList; 00075 00076 typedef std::set<PNode> NodeSet; 00077 typedef std::set<PFace> FaceSet; 00078 00080 00081 template <class T> 00082 int split_stl_vector(const std::vector<T> &a, size_t pos, std::vector<T> &b, std::vector<T> &c) 00083 { 00084 size_t nSize = a.size(); 00085 if (pos >= nSize ) return 1; 00086 00087 b.resize(pos); 00088 00089 size_t index = 0; 00090 for (size_t i = 0; i < pos; i++) 00091 b[index++] = a[i]; 00092 00093 c.resize(nSize - pos + 1); 00094 index = 0; 00095 00096 for (size_t i = pos - 1; i < nSize; i++) 00097 c[index++] = a[i]; 00098 00099 return 0; 00100 } 00101 00103 00104 template <class T> 00105 int split_stl_vector(const std::deque<T> &a, size_t pos, std::deque<T> &b, std::deque<T> &c) 00106 { 00107 size_t nSize = a.size(); 00108 00109 if (pos >= nSize) return 1; 00110 00111 b.resize(pos); 00112 00113 size_t index = 0; 00114 for (size_t i = 0; i < pos; i++) 00115 b[index++] = a[i]; 00116 00117 c.resize(nSize - pos + 1); 00118 index = 0; 00119 for (size_t i = pos - 1; i < nSize; i++) 00120 c[index++] = a[i]; 00121 00122 return 0; 00123 } 00124 00126 00127 struct Attribute { 00128 public: 00129 Attribute() {} 00130 Attribute(const std::string &s, const myany &p) { 00131 name = s; 00132 value = p; 00133 } 00134 00135 template <typename T> Attribute(T n) { value = n; } 00136 00137 std::string name; 00138 myany value; 00139 }; 00140 00141 template<class T> 00142 struct VecAttribute { 00143 std::vector<T> values; 00144 }; 00145 00146 template<class T, int n> 00147 struct ArrayAttribute { 00148 meshkit::array <T,n> values; 00149 }; 00150 00151 template<class T> 00152 struct ListAttribute { 00153 std::list<T> values; 00154 }; 00155 00156 template<class T> 00157 struct SetAttribute { 00158 std::set<T> values; 00159 }; 00160 00162 struct RelationRep { 00163 void clearRelations(int t); 00164 00165 void addRelation(Vertex *vertex); 00166 void addRelation(Edge *edge); 00167 void addRelation(Face* face); 00168 00169 int getNumRelations( int e ) const { 00170 if( e == 0) return relations0.size(); 00171 if( e == 1) return relations1.size(); 00172 if( e == 2) return relations2.size(); 00173 return 0; 00174 } 00175 00176 bool hasRelation(const Vertex* vertex) const; 00177 bool hasRelation(const Edge* edge) const; 00178 bool hasRelation(const Face* face) const; 00179 00180 void removeRelation(const Vertex *vertex); 00181 void removeRelation(const Edge *edge); 00182 void removeRelation(const Face *face); 00183 00184 int getRelations( NodeSequence &seq, bool cyclic_ordered = 0) const { 00185 seq.clear(); 00186 size_t nSize = relations0.size(); 00187 if( nSize == 0) return 1; 00188 seq.resize( nSize ); 00189 for( size_t i = 0; i< nSize; i++) 00190 seq[i] = relations0[i]; 00191 return 0; 00192 } 00193 00194 int getRelations( EdgeSequence &seq, bool cyclic_ordered = 0) const { 00195 seq.clear(); 00196 size_t nSize = relations1.size(); 00197 if( nSize == 0) return 1; 00198 seq.resize( nSize ); 00199 for( size_t i = 0; i< nSize; i++) 00200 seq[i] = relations1[i]; 00201 return 0; 00202 } 00203 00204 00205 int getRelations( FaceSequence &seq, bool cyclic_ordered = 0) const { 00206 seq.clear(); 00207 size_t nSize = relations2.size(); 00208 if( nSize == 0) return 1; 00209 seq.resize( nSize ); 00210 for( size_t i = 0; i< nSize; i++) 00211 seq[i] = relations2[i]; 00212 return 0; 00213 } 00214 00215 NodeSequence relations0; // vertex-vertex 00216 EdgeSequence relations1; // vertex-vertex 00217 FaceSequence relations2; // vertex-face 00218 }; 00219 00220 struct AttribRep { 00221 void removeAll() { 00222 for( size_t i = 0; i < attributes.size(); i++) 00223 delete attributes[i]; 00224 } 00225 template<class T> 00226 int setAttribute(const string &s, const T &val) { 00227 int nAttribs = attributes.size(); 00228 for( int i = 0; i < nAttribs; i++) { 00229 if( attributes[i]->name == s ) { 00230 attributes[i]->value = val; 00231 return 0; 00232 } 00233 } 00234 Attribute *a = new Attribute(s,val); 00235 attributes.push_back( a ); 00236 return 0; 00237 } 00238 00239 template<class T> 00240 int getAttribute(const string &s, T &val) const { 00241 int nAttribs = attributes.size(); 00242 for( int i = 0; i < nAttribs; i++) { 00243 if( attributes[i]->name == s ) { 00244 val = any_cast <T>( attributes[i]->value); 00245 return 0; 00246 } 00247 } 00248 return 1; 00249 } 00250 00251 int hasAttribute(const string &s) const { 00252 int nAttribs = attributes.size(); 00253 for( int i = 0; i < nAttribs; i++) 00254 if( attributes[i]->name == s ) return 1; 00255 return 0; 00256 } 00257 00258 void removeAttribute( const string &s) { 00259 } 00260 00261 std::vector<Attribute*> attributes; 00262 }; 00263 00264 class MeshEntity { 00265 public: 00266 00267 typedef size_t idtype; 00268 static const int ACTIVE = 0; 00269 static const int REMOVE = 1; 00270 static const int INACTIVE = 2; 00271 00272 MeshEntity() { 00273 visitMark = 0; // Default: Not yet visited. 00274 statusMark = ACTIVE; // Default: Active< not removable. 00275 constrained = 0; // Default: No Contrainted 00276 boundarymark = 0; // Default: Internal entity 00277 relationRep = NULL; 00278 attribRep = NULL; 00279 } 00280 00281 ~MeshEntity() { 00282 if( attribRep ) attribRep->removeAll(); 00283 } 00284 00285 void setVisitMark(bool r) { 00286 visitMark = r; 00287 } 00288 00289 bool isVisited() const { 00290 return visitMark; 00291 } 00292 00293 int getStatus() const { 00294 return statusMark; 00295 } 00296 00297 bool isRemoved() const { 00298 if (statusMark == REMOVE) return 1; 00299 return 0; 00300 } 00301 00302 bool isActive() const { 00303 if (statusMark == ACTIVE) return 1; 00304 return 0; 00305 } 00306 00307 bool isBoundary() const { 00308 return boundarymark; 00309 } 00310 00311 void setBoundaryMark(int b) { 00312 boundarymark = b; 00313 } 00314 00315 int getBoundaryMark() const { 00316 return boundarymark; 00317 } 00318 00319 bool isConstrained() const { 00320 if (boundarymark > 0 || constrained) return 1; 00321 return 0; 00322 } 00323 00324 void setConstrainedMark(int b) { 00325 constrained = b; 00326 } 00327 00328 void setID(idtype id) { 00329 gid = id; 00330 } 00331 00332 const idtype &getID() const { 00333 return gid; 00334 } 00335 00336 template<class T> 00337 int setAttribute(const string &s, const T &val) { 00338 if( attribRep == NULL ) attribRep = new AttribRep; 00339 return attribRep->setAttribute(s,val); 00340 } 00341 00342 template<class T> 00343 int getAttribute(const string &s, T &val) const { 00344 if( attribRep ) 00345 return attribRep->getAttribute(s,val); 00346 return 1; 00347 } 00348 00349 int hasAttribute(const string &s) const { 00350 if( attribRep ) 00351 return attribRep->hasAttribute(s); 00352 return 0; 00353 } 00354 00355 void removeAttribute(const string &s) const { 00356 if( attribRep ) attribRep->removeAttribute(s); 00357 } 00358 00359 void clearRelations(int e) { 00360 if( relationRep ) relationRep->clearRelations(e); 00361 } 00362 00363 void addRelation(Vertex *vertex) { 00364 if( relationRep == NULL ) relationRep = new RelationRep; 00365 relationRep->addRelation(vertex); 00366 } 00367 00368 void addRelation(Edge *edge) { 00369 if( relationRep == NULL ) relationRep = new RelationRep; 00370 relationRep->addRelation(edge); 00371 } 00372 00373 void addRelation(Face* face) { 00374 if( relationRep == NULL ) relationRep = new RelationRep; 00375 relationRep->addRelation(face); 00376 } 00377 00378 int getNumRelations( int e ) const { 00379 if( relationRep ) 00380 return relationRep->getNumRelations(e); 00381 return 0; 00382 } 00383 00384 bool hasRelation(const Vertex* vertex) const { 00385 if( relationRep ) 00386 return relationRep->hasRelation( vertex ); 00387 return 0; 00388 } 00389 00390 bool hasRelation(const Edge* edge) const { 00391 if( relationRep ) 00392 return relationRep->hasRelation( edge ); 00393 return 0; 00394 } 00395 00396 bool hasRelation(const Face* face) const { 00397 if( relationRep ) 00398 return relationRep->hasRelation( face ); 00399 return 0; 00400 } 00401 00402 void removeRelation(const Vertex *vertex) { 00403 if( relationRep ) relationRep->removeRelation( vertex ); 00404 } 00405 void removeRelation(const Face *face) { 00406 if( relationRep ) relationRep->removeRelation( face ); 00407 } 00408 00409 int getRelations( NodeSequence &seq, bool cyclic_ordered = 0) const { 00410 seq.clear(); 00411 if( relationRep ) 00412 return relationRep->getRelations(seq,cyclic_ordered); 00413 return 1; 00414 } 00415 00416 int getRelations( EdgeSequence &seq, bool cyclic_ordered = 0) const { 00417 seq.clear(); 00418 if( relationRep ) 00419 return relationRep->getRelations(seq,cyclic_ordered); 00420 return 1; 00421 } 00422 00423 int getRelations( FaceSequence &seq, bool cyclic_ordered = 0) const { 00424 seq.clear(); 00425 if( relationRep ) 00426 return relationRep->getRelations(seq,cyclic_ordered); 00427 return 1; 00428 } 00429 00430 void setStatus(int a) { 00431 statusMark = a; 00432 } 00433 00434 protected: 00435 idtype gid; 00436 int boundarymark; 00437 bool constrained; 00438 volatile bool visitMark; 00439 volatile short int statusMark; 00440 RelationRep *relationRep; 00441 AttribRep *attribRep; 00442 }; 00443 00444 struct EntityRemovedPred { 00445 00446 bool operator() (const MeshEntity * entity) const { 00447 if (entity) return entity->isRemoved(); 00448 return 0; 00449 } 00450 }; 00451 00453 00454 struct BaseVertex : public MeshEntity { 00455 }; 00456 00457 class Vertex : public BaseVertex { 00458 static size_t global_id; 00459 public: 00460 00461 static PNode newObject(); 00462 00463 Vertex() { 00464 visitMark = 0; 00465 statusMark = MeshEntity::ACTIVE; 00466 boundarymark = 0; 00467 } 00468 00469 static double length(const Vertex *v0, const Vertex *v1); 00470 static double length2(const Vertex *v0, const Vertex *v1); 00471 static void mid_point(const Vertex *v0, const Vertex *v1, Point3D &p, double alpha = 0.5); 00472 static Vertex* mid_node(const Vertex *v0, const Vertex *v1, double alpha = 0.5); 00473 static double point_orient( const Point3D &p0, const Point3D &p1, const Point3D &qpoint); 00474 00475 void setXYZCoords(const Point3D &p) { 00476 xyz[0] = p[0]; 00477 xyz[1] = p[1]; 00478 xyz[2] = p[2]; 00479 } 00480 00481 const Point3D &getXYZCoords() const { 00482 return xyz; 00483 } 00484 00485 Vertex* getClone() const; 00486 00487 double getSpanAngle() const; 00488 double getFeatureLength() const; 00489 int get_ideal_face_degree( int n ) const; 00490 00491 private: 00492 Point3D xyz; 00493 }; 00494 00496 00497 struct LowVertexDegreeCompare { 00498 bool operator() (const Vertex *vertex1, const Vertex * vertex2) const { 00499 size_t d1 = vertex1->getNumRelations(0); 00500 size_t d2 = vertex2->getNumRelations(0); 00501 return d1 < d2; 00502 } 00503 }; 00505 00506 struct HighVertexDegreeCompare { 00507 bool operator() (const Vertex *vertex1, const Vertex * vertex2) const { 00508 size_t d1 = vertex1->getNumRelations(0); 00509 size_t d2 = vertex2->getNumRelations(0); 00510 return d1 > d2; 00511 } 00512 }; 00514 00515 struct LowLayerCompare { 00516 00517 bool operator() (const Vertex *vertex1, const Vertex * vertex2) const { 00518 int val1, val2; 00519 vertex1->getAttribute("Layer", val1); 00520 vertex2->getAttribute("Layer", val2); 00521 return val1 < val2; 00522 } 00523 }; 00524 00526 00527 struct BaseEdge : public MeshEntity { 00528 }; 00529 00530 class Edge : public BaseEdge { 00531 public: 00532 static PEdge newObject(); 00533 00534 Edge() { 00535 } 00536 00537 Edge(PNode n1, PNode n2) { 00538 setNodes(n1, n2); 00539 } 00540 00541 Vertex* getHashNode() const { 00542 return min(connect[0], connect[1]); 00543 } 00544 00545 void setNodes(const NodeSequence &v) { 00546 assert(v.size() == 2); 00547 setNodes(v[0], v[1]); 00548 } 00549 00550 void setNodes(Vertex *v1, Vertex *v2) { 00551 assert(v1 != v2); 00552 connect[0] = v1; 00553 connect[1] = v2; 00554 } 00555 00556 const PNode &getNodeAt(int id) const { 00557 return connect[id]; 00558 } 00559 00560 bool isSameAs(const Edge &rhs) { 00561 if ((connect[0] == rhs.connect[0]) && (connect[1] == rhs.connect[1])) return 1; 00562 if ((connect[0] == rhs.connect[1]) && (connect[1] == rhs.connect[0])) return 1; 00563 return 0; 00564 } 00565 00566 bool hasCrease() const { 00567 return 0; 00568 } 00569 00570 Edge* getClone() const { 00571 Edge *newedge = new Edge(connect[0], connect[1]); 00572 return newedge; 00573 } 00574 00575 private: 00576 // void * operator new( size_t size, void *); 00577 00578 PNode connect[2]; 00579 }; 00580 00582 00583 struct BaseFace : public MeshEntity { 00584 }; 00585 00586 class Face : public BaseFace { 00587 public: 00588 static const int POLYGON = 0; 00589 static const int TRIANGLE = 3; 00590 static const int QUADRILATERAL = 4; 00591 00592 static PFace newObject(); 00593 00594 static PFace create_quad(const PFace t1, const PFace t2, int replace = 0); 00595 00596 // This function is for concave quads. Arrange vertices so that OpenGL can render them 00597 // correctly. When you save the mesh, probably the connectivity may change. 00598 static int quad_tessalate(const NodeSequence &orgNodes, NodeSequence &rotatedNodes); 00599 static int hexagon_2_quads(const NodeSequence &hexnodes, FaceSequence &quads, int start_from); 00600 00601 static int is_3_sided_convex_loop_quad_meshable(const int *s, int *sdiv); 00602 static int is_5_sided_convex_loop_quad_meshable(const int *s, int *sdiv); 00603 static int is_cyclic_quad(const Point3D &p0, const Point3D &p1, const Point3D &p2, const Point3D &p3); 00604 00605 // Centroid of Triangle element ... 00606 static Vertex *centroid(const Vertex *v0, const Vertex *v1, const Vertex *v2); 00607 00608 // Centroid of Quad element ... 00609 static Vertex *centroid(const Vertex *v0, const Vertex *v1, const Vertex *v2, 00610 const Vertex *v3, const Vertex *v4); 00611 00612 // Distortion of a triangle element ... 00613 static double distortion(const Vertex *v0, const Vertex *v1, const Vertex *v2); 00614 00615 // Distortion of a quad element ... 00616 static double distortion(const Vertex *v0, const Vertex *v1, const Vertex *v2, 00617 const Vertex *v3, const Vertex *v4); 00618 00620 // Use modified Heron formula for find out the area of a triangle 00622 00623 static double tri_area(const Point3D &p0, const Point3D &p1, const Point3D &p2); 00624 00625 static Vec3D normal(const Vertex *v0, const Vertex *v1, const Vertex *v2); 00626 static Vec3D normal(const Point3D &p0, const Point3D &p1, const Point3D &v2); 00627 00628 static void bilinear_weights(double xi, double eta, vector<double> &weight); 00629 static double linear_interpolation(const vector<double> &x, const vector<double> &w); 00630 00632 // Calculate Area of Quadrilateral: 00633 // Example : Convex Case 00634 // Coorindates (0.0,0.0) ( 1.0, 1.0), (2.0, 0.0), (1,0, -1.0) 00635 // Result : 2*( 0.5*2.0*1.0 ) = 2.0; 00636 // Concave case: 00637 // Coodinates: ( 0.0, 0.0), 10, 2), (2.0, 0.0), (10, -2) 00638 // Result : 2 *( 0.5*2.0* 2.0) = 4.0 00640 static double quad_area(const Point3D &p0, const Point3D &p1, 00641 const Point3D &p2, const Point3D &p3); 00642 00643 static bool is_convex_quad(const Point3D &p0, const Point3D &p1, 00644 const Point3D &p2, const Point3D &p3); 00645 00646 static PNode opposite_node(const PFace quad, const PNode n1); 00647 static PNode opposite_node(const PFace tri, PNode n1, PNode n2); 00648 static void opposite_nodes(const PFace quad, PNode n1, PNode n2, 00649 PNode &n3, PNode &n4); 00650 00651 static int check_on_boundary(const PFace tri); 00652 00653 Face() { 00654 statusMark = 0; 00655 boundarymark = 0; 00656 visitMark = 0; 00657 } 00658 00659 Face( const Vertex *v0, const Vertex *v1, const Vertex *v2) { 00660 NodeSequence seq(3); 00661 seq[0] = const_cast<Vertex*>(v0); 00662 seq[1] = const_cast<Vertex*>(v1); 00663 seq[2] = const_cast<Vertex*>(v2); 00664 setNodes(seq); 00665 } 00666 00667 Face( const Vertex *v0, const Vertex *v1, const Vertex *v2, const Vertex *v3) { 00668 NodeSequence seq(4); 00669 seq[0] = const_cast<Vertex*>(v0); 00670 seq[1] = const_cast<Vertex*>(v1); 00671 seq[2] = const_cast<Vertex*>(v2); 00672 seq[3] = const_cast<Vertex*>(v3); 00673 setNodes(seq); 00674 } 00675 00676 Vertex* getHashNode() const { 00677 return *min_element(connect.begin(), connect.end()); 00678 } 00679 00680 int getType() const { 00681 if (connect.size() == 3) return Face::TRIANGLE; 00682 if (connect.size() == 4) return Face::QUADRILATERAL; 00683 return Face::POLYGON; 00684 } 00685 00686 int concaveAt() const; 00687 bool isSimple() const; 00688 00689 bool isSameAs(const Face *rhs) const { 00690 if (rhs->getSize(0) != getSize(0)) return 0; 00691 00692 for (int i = 0; i < getSize(0); i++) 00693 if (!rhs->hasNode(connect[i])) return 0; 00694 00695 return 1; 00696 } 00697 00698 bool hasNode(const PNode &vertex) const { 00699 if (find(connect.begin(), connect.end(), vertex) != connect.end()) return 1; 00700 return 0; 00701 } 00702 00703 int getPosOf(const Vertex *vertex) const { 00704 int nSize = connect.size(); 00705 for (int i = 0; i < nSize; i++) 00706 if (connect[i] == vertex) return i; 00707 00708 return -1; 00709 } 00710 00711 void reverse() { 00712 std::reverse(connect.begin(), connect.end()); 00713 } 00714 00715 int getOrientation(const Vertex *ev0, const Vertex *ev1) const { 00716 int nSize = connect.size(); 00717 00718 for (int i = 0; i < nSize; i++) { 00719 Vertex *v0 = connect[(i + 0) % nSize]; 00720 Vertex *v1 = connect[(i + 1) % nSize]; 00721 if (v0 == ev0 && v1 == ev1) return +1; 00722 if (v0 == ev1 && v1 == ev0) return -1; 00723 } 00724 return 0; 00725 } 00726 00727 int replaceNode(Vertex *oldvertex, Vertex *newvertex) { 00728 00729 int nSize = connect.size(); 00730 for (int i = 0; i < nSize; i++) { 00731 if (connect[i] == oldvertex) { 00732 connect[i] = newvertex; 00733 return 0; 00734 } 00735 } 00736 return 1; 00737 } 00738 00739 int getSize(int etype) const { 00740 if (etype == 0) return connect.size(); 00741 return 0; 00742 } 00743 00744 int setNodes(const NodeSequence &v) { 00745 int nSize = v.size(); 00746 bool err = 0; 00747 for (int i = 0; i < nSize; i++) { 00748 for (int j = i+1; j < nSize; j++) 00749 if(v[i] == v[j]) err = 1; 00750 } 00751 if( !err ) { 00752 connect = v; 00753 } 00754 return err; 00755 } 00756 00757 const NodeSequence &getNodes() const { 00758 return connect; 00759 } 00760 00761 const PNode &getNodeAt(size_t id) const { 00762 return connect[id%connect.size()]; 00763 } 00764 00765 void getAvgPos( Point3D &p) const; 00766 00767 bool hasBoundaryNode() const { 00768 int nSize = connect.size(); 00769 for (int i = 0; i < nSize; i++) 00770 if (connect[i]->isBoundary()) return 1; 00771 return 0; 00772 } 00773 00774 bool has_all_bound_nodes() const; 00775 bool has_boundary_edge() const; 00776 00777 int getRelations02( FaceSequence &seq); 00778 int getRelations12( FaceSequence &seq); 00779 int getRelations( NodeSequence &seq); 00780 00781 bool isConvex() const { 00782 if (connect.size() <= 3) return 1; 00783 00784 if (connect.size() == 4) 00785 return is_convex_quad(connect[0]->getXYZCoords(), 00786 connect[1]->getXYZCoords(), 00787 connect[2]->getXYZCoords(), 00788 connect[3]->getXYZCoords()); 00789 00790 cout << "Warning: General Polygon not supported " << endl; 00791 return 0; 00792 } 00793 00794 double getAngleAt(const Vertex *v) const; 00795 00796 int get_interior_angles(vector<double> &angles) const; 00797 00798 double getAspectRatio(); 00799 00800 double getArea() { 00801 if (connect.size() == 3) { 00802 return tri_area(connect[0]->getXYZCoords(), 00803 connect[1]->getXYZCoords(), 00804 connect[2]->getXYZCoords()); 00805 } 00806 00807 if (connect.size() == 4) { 00808 return quad_area(connect[0]->getXYZCoords(), 00809 connect[1]->getXYZCoords(), 00810 connect[2]->getXYZCoords(), 00811 connect[3]->getXYZCoords()); 00812 } 00813 return 0.0; 00814 } 00815 00816 int triangulate( vector<Face> &f) const; 00817 00818 bool isValid() const; 00819 00820 int refine_quad14(NodeSequence &newnodes, FaceSequence &newfaces); 00821 int refine_quad15(NodeSequence &newnodes, FaceSequence &newfaces); 00822 00823 void start_from_concave_corner(); 00824 00825 Face* getClone() const { 00826 Face *newface = Face::newObject(); 00827 newface->setNodes(connect); 00828 return newface; 00829 } 00830 00831 private: 00832 NodeSequence connect; 00833 00834 int refine_convex_quad15(NodeSequence &newnodes, FaceSequence &newfaces); 00835 int refine_concave_quad15(NodeSequence &newnodes, FaceSequence &newfaces); 00836 }; 00837 00839 00840 struct BoundingBox { 00841 00842 double getLength(int d) { 00843 assert(d >= 0 && d < 3); 00844 return fabs(upperRightCorner[d] - lowerLeftCorner[d]); 00845 } 00846 00847 void setLowerLeftCorner(const Point3D & p) { 00848 lowerLeftCorner = p; 00849 } 00850 00851 const Point3D & getLowerLeftCorner() const { 00852 return lowerLeftCorner; 00853 } 00854 00855 void setUpperRightCorner(const Point3D & p) { 00856 upperRightCorner = p; 00857 } 00858 00859 const Point3D & getUpperRightCorner() const { 00860 return upperRightCorner; 00861 } 00862 00863 private: 00864 Point3D lowerLeftCorner; 00865 Point3D upperRightCorner; 00866 }; 00867 00868 inline 00869 PNode 00870 Vertex::newObject() 00871 { 00872 Vertex *v = new Vertex; 00873 assert(v); 00874 v->setID(global_id); 00875 global_id++; 00876 return v; 00877 } 00878 00880 00881 inline PNode Vertex::getClone() const 00882 { 00883 Vertex *v = new Vertex; 00884 assert(v); 00885 v->setID(global_id); 00886 v->setXYZCoords(xyz); 00887 return v; 00888 } 00889 00891 00892 inline PEdge Edge::newObject() 00893 { 00894 Edge *e = new Edge; 00895 assert(e); 00896 return e; 00897 } 00898 00900 00901 inline PFace Face::newObject() 00902 { 00903 Face *f = new Face; 00904 assert(f); 00905 return f; 00906 } 00907 00909 inline double Face:: getAngleAt( const Vertex *v) const 00910 { 00911 int pos = getPosOf(v); 00912 assert( pos >= 0); 00913 00914 int nnodes = getSize(0); 00915 00916 if( nnodes == 3 ) { 00917 const Point3D &p0 = getNodeAt((pos+0)%nnodes)->getXYZCoords(); 00918 const Point3D &p1 = getNodeAt((pos+1)%nnodes)->getXYZCoords(); 00919 const Point3D &p2 = getNodeAt((pos+2)%nnodes)->getXYZCoords(); 00920 return Math::getTriAngle(p0, p1, p2); 00921 } 00922 00923 if( nnodes == 4 ) { 00924 const Point3D &p0 = getNodeAt((pos+0)%nnodes)->getXYZCoords(); 00925 const Point3D &p1 = getNodeAt((pos+1)%nnodes)->getXYZCoords(); 00926 const Point3D &p2 = getNodeAt((pos+2)%nnodes)->getXYZCoords(); 00927 const Point3D &p3 = getNodeAt((pos+3)%nnodes)->getXYZCoords(); 00928 double a1 = Math::getTriAngle(p0, p1, p2); 00929 double a2 = Math::getTriAngle(p0, p2, p3); 00930 return a1 + a2; 00931 } 00932 00933 cout << "Error: Not implemented for general polygons " << endl; 00934 exit(0); 00935 return 0; 00936 } 00937 00939 00940 inline double Vertex :: getSpanAngle() const 00941 { 00942 FaceSequence vfaces; 00943 this->getRelations( vfaces ); 00944 int nSize = vfaces.size(); 00945 double sum = 0.0; 00946 for( int i = 0; i < nSize; i++) { 00947 Face *face = vfaces[i]; 00948 sum += face->getAngleAt( this ); 00949 } 00950 return sum; 00951 } 00953 00954 #define TOPOLOGICAL_DISTANCE 0 00955 #define EUCLIDEAN_DISTANCE 1 00956 #define EUCLIDEAN_DISTANCE2 2 00957 #define CITY_BLOCK_DISTANCE 3 00958 00960 00961 struct MeshFilter { 00962 00963 virtual bool pass(const Vertex * v) const { 00964 cout << "Warning: passing the base " << endl; 00965 return 1; 00966 } 00967 virtual bool pass(const Face * v) const { 00968 return 1; 00969 } 00970 virtual ~MeshFilter() { 00971 } 00972 ; 00973 }; 00974 00975 class Mesh { 00976 public: 00977 static NodeSequence generate_nodes(size_t n); 00978 static FaceSequence generate_faces(size_t n); 00979 00980 static int getRelations112(const PNode v0, const PNode v1, FaceSequence &seq); 00981 static int getRelations102(const PNode v0, const PNode v1, FaceSequence &seq); 00982 static int make_chain(vector<Edge> &edges); 00983 static int is_closed_chain(const vector<Edge> &edges); 00984 static int is_closeable_chain(const vector<Edge> &edges); 00985 static int rotate_chain(vector<Edge> &edges, Vertex* start_vertex); 00986 static NodeSequence boundary_chain_nodes(Vertex *v0, Vertex *v1); 00987 static NodeSequence chain_nodes(const vector<Edge> &e); 00988 00989 Mesh() { 00990 for (int i = 0; i < 4; i++) { 00991 for (int j = 0; j < 4; j++) adjTable[i][j] = 0; 00992 } 00993 hasdual = 0; 00994 meshname = "unknown"; 00995 boundary_known = 0; 00996 } 00997 00998 ~Mesh() { 00999 emptyAll(); 01000 collect_garbage(); 01001 } 01002 01003 void objects_from_pool( size_t n, NodeSequence &objects); 01004 void objects_from_pool( size_t n, FaceSequence &objects); 01005 01006 void setName(const string &s) { 01007 meshname = s; 01008 } 01009 01010 string getName() const { 01011 return meshname; 01012 } 01013 01014 void reserve(size_t nSize, int entity) { 01015 if (entity == 0) nodes.reserve(nSize); 01016 if (entity == 1) edges.reserve(nSize); 01017 if (entity == 2) faces.reserve(nSize); 01018 } 01019 01020 bool hasDual() const { 01021 return hasdual; 01022 } 01023 01024 void setDual(bool d) { 01025 hasdual = d; 01026 } 01027 01028 int remove_nodes_attribute(const string &s); 01029 int remove_edges_attribute(const string &s); 01030 int remove_faces_attribute(const string &s); 01031 01032 int isHomogeneous() const; 01033 01034 int hasConvexCells(); 01035 01036 size_t count_convex_faces(); 01037 size_t count_concave_faces(); 01038 size_t count_inverted_faces(); 01039 size_t count_irregular_nodes(int regdef); 01040 01041 Mesh* deep_copy(); 01042 Mesh* shallow_copy(); 01043 01044 BoundingBox getBoundingBox() const; 01045 01046 int getNumComponents(bool stop_at_interface = 0); 01047 Mesh *getComponent(int id); 01048 01049 int readFromFile(const string &f); 01050 bool getAdjTable(int i, int j) const { 01051 return adjTable[i][j]; 01052 } 01053 Mesh * load(const string &fname, Mesh *m); 01054 Mesh *getPartMesh( int p); 01055 int getNumPartitions(int e ); 01056 01057 int getEulerCharacteristic(); 01058 01059 Vertex* nearest_neighbour(const Vertex *v, double &d); 01060 01061 size_t getSize(int d) { 01062 if (d == 0) return nodes.size(); 01063 if (d == 1) return count_edges(); 01064 if (d == 2) return faces.size(); 01065 return 0; 01066 } 01067 01068 size_t getCapacity(int d) { 01069 if (d == 0) return nodes.capacity(); 01070 if (d == 2) return faces.capacity(); 01071 return 0; 01072 } 01073 01074 // If the topology of the mesh is changed, make sure to setBoundaryStatus = 0 01075 // so that it is again determined. 01076 01077 void setBoundaryKnown(bool v) { 01078 boundary_known = v; 01079 } 01080 01081 // If the boundary nodes and faces are knowm, return the value = 1. otherwise 0 01082 01083 bool isBoundaryKnown() const { 01084 return boundary_known; 01085 } 01086 01087 // A mesh is simple, when each edge is shared by at the most two faces which is 01088 // topological simple. A geometrically simple mesh will not have any crossing, 01089 // or overlapping edges, but this has not been checked right now. 01090 bool isSimple(); 01091 01092 // A mesh is consistently oriented when an edge shared by two faces, traversed in 01093 // opposite direction. Such a mesh will have proper normals ( either all inside or 01094 // or all outside ). 01095 bool is_consistently_oriented(); 01096 01097 // Make the mesh consistent. 01098 void make_consistently_oriented(); 01099 01100 // How many strongly connected components this mesh has ? 01101 int getNumConnectedComponents(); 01102 01103 // Get #of boundary nodes, edges, and faces information. 01104 size_t getBoundarySize(int d) ; 01105 01106 // Appends a node in the mesh. 01107 01108 void addNode(PNode v) { 01109 nodes.push_back(v); 01110 v->setStatus(MeshEntity::ACTIVE); 01111 } 01112 01113 // Appends a bulk of nodes in the mesh. 01114 01115 void addNodes(const NodeSequence &vnodes) { 01116 size_t nSize = vnodes.size(); 01117 for (size_t i = 0; i < nSize; i++) 01118 addNode(vnodes[i]); 01119 } 01120 01121 void addNodes(NodeList &nlist) { 01122 while (!nlist.empty()) { 01123 PNode anode = nlist.front(); 01124 nlist.pop_front(); 01125 addNode(anode); 01126 } 01127 } 01128 01129 int remove(PNode v); 01130 int deactivate(PNode v); 01131 int reactivate(PNode v); 01132 01133 // Get the node at the specified position in the container. 01134 01135 const PNode &getNodeAt(size_t id) const { 01136 assert(id < nodes.size()); 01137 return nodes[id]; 01138 } 01139 01140 // Get All the nodes in the mesh after lazy prunning ( Garbage collection ). 01141 01142 int getNodes(NodeSequence &seq) const { 01143 size_t nSize = nodes.size(); 01144 01145 seq.clear(); 01146 seq.reserve( nSize ); 01147 for( size_t i = 0; i < nSize; i++) { 01148 Vertex *v = getNodeAt(i); 01149 if( v->isActive() ) seq.push_back(v); 01150 } 01151 return 0; 01152 } 01153 01154 int getNodes(NodeList &l) const; 01155 int getFaces(FaceList &l) const; 01156 01157 // 01158 // Return irregular nodes in the domain. 01159 // regular_count = 6 : For triangle mesh; 01160 // regular_count = 4 : For Quad mesh; 01161 // where = 0 : From the inner nodes only 01162 // where = 1 : From the boundary nodes only 01163 // 01164 int get_irregular_nodes(NodeSequence &seq, int regular_count, int where = 0); 01165 01166 const PEdge &getEdgeAt(size_t id) const { 01167 assert(id < edges.size()); 01168 if( edges[id]->getNodeAt(0)->isRemoved() || edges[id]->getNodeAt(1)->isRemoved() ) 01169 edges[id]->setStatus( MeshEntity::REMOVE ); 01170 return edges[id]; 01171 } 01172 01173 int get_sharp_edges(EdgeSequence &e, double angle); //Specify the angle in degree. 01174 01175 void addFeatureEdge(PEdge e) { 01176 feature_edges.push_back(e); 01177 // 01178 // Feature edge vertices are always constrained, by design. some codes 01179 // will break if this is modified in future. 01180 // 01181 Vertex *v; 01182 01183 v = e->getNodeAt(0); 01184 v->setConstrainedMark(1); 01185 01186 v = e->getNodeAt(1); 01187 v->setConstrainedMark(1); 01188 } 01189 01190 bool hasFeatureEdge(const Edge &query_edge) const { 01191 size_t nSize = feature_edges.size(); 01192 for (size_t i = 0; i < nSize; i++) 01193 if (feature_edges[i]->isSameAs(query_edge)) return 1; 01194 return 0; 01195 } 01196 01197 // Add a face in the mesh. No duplication is checked.. 01198 int addFace(PFace f); 01199 int remove(PFace f); 01200 01201 int deactivate(PFace f); 01202 int reactivate(PFace f); 01203 01204 // Add bulk of faces in the mesh. No duplication is checked.. 01205 01206 void addFaces(FaceSequence &vfaces) { 01207 size_t nSize = vfaces.size(); 01208 for (size_t i = 0; i < nSize; i++) 01209 addFace(vfaces[i]); 01210 } 01211 01212 void addFaces(FaceList &flist) { 01213 while (!flist.empty()) { 01214 PFace f = flist.front(); 01215 flist.pop_front(); 01216 addFace(f); 01217 } 01218 } 01219 01220 // Get the face at the specified position in the container. 01221 01222 const PFace &getFaceAt(size_t id) const { 01223 assert(id < faces.size()); 01224 return faces[id]; 01225 } 01226 01227 bool contains(const Vertex *v) const { 01228 if (find(nodes.begin(), nodes.end(), v) == nodes.end()) return 0; 01229 return 1; 01230 } 01231 01232 bool contains(const Face *f) const { 01233 if (find(faces.begin(), faces.end(), f) == faces.end()) return 0; 01234 return 1; 01235 } 01236 01237 // Get rid of entities which are marked "removed" from the mesh. 01238 // a la Lazy garbage collection. 01239 // 01240 void prune(); 01241 01242 // Check if the lazy garbage collection is performed.. 01243 bool isPruned() const; 01244 01245 // Renumber mesh entities starting from index = 0 01246 void enumerate(int etype); 01247 01248 // Search the boundary of the mesh (nodes, edges, and faces). 01249 int search_boundary(); 01250 01251 // Build entity-entity relations. 01252 01253 int build_relations(int src, int dst, bool rebuild = 0) { 01254 if (src == 0 && dst == 0) return build_relations00( rebuild ); 01255 if (src == 0 && dst == 1) return build_relations01( rebuild ); 01256 if (src == 0 && dst == 2) return build_relations02( rebuild ); 01257 if (src == 1 && dst == 2) return build_relations12( rebuild ); 01258 return 1; 01259 } 01260 01261 void normalize(); 01262 01263 // clean specified entity-entity relations. 01264 void clear_relations(int src, int dst); 01265 01266 // Return all the edges of the primal mesh ... 01267 int getEdges( EdgeSequence &seq, int directed = 0) { 01268 if (edges.empty()) build_edges(); 01269 seq = edges; 01270 return 0; 01271 } 01272 01273 // Return all the edges of dual mesh... 01274 EdgeSequence getDualEdges() const; 01275 01276 // Returm all the matching edges of the dual graph... 01277 EdgeSequence getMatchingDuals() const; 01278 01279 // Filter out face. 01280 FaceSequence filter(int facetype) const; 01281 01282 // Save the mesh and all its attributes ( in the simple format ). 01283 int saveAs(const string &s); 01284 01285 // Empty every thing in the Mesh, but don't delete the objects. 01286 void emptyAll(); 01287 01288 // Empty every thing in the Mesh, and also deallocate all the objects. 01289 void deleteNodes(); 01290 void deleteEdges(); 01291 void deleteFaces(); 01292 void deleteAll(); 01293 01294 // Reverse the connection of all the faces in the mesh. This will be flip 01295 // the normal of each face. 01296 01297 void reverse() { 01298 01299 size_t nSize = faces.size(); 01300 for (size_t i = 0; i < nSize; i++) 01301 faces[i]->reverse(); 01302 } 01303 01304 // Collect topological information. Ideally an internal vertex has 4 faces. 01305 vector<int> get_topological_statistics(int entity = 0, bool sorted = 1); 01306 01307 // Collect nodes and faces in Depth First Sequence ... 01308 int get_depth_first_ordered_nodes(NodeSequence &seq, Vertex *v = NULL, MeshFilter *mf = NULL); 01309 int get_depth_first_ordered_faces(FaceSequence &seq, Face *f = NULL); 01310 01311 // Collect nodes and faces in Breadth First Sequence ... 01312 int get_breadth_first_ordered_nodes(NodeSequence &seq, Vertex *f = NULL, MeshFilter *mf = NULL); 01313 int get_breadth_first_ordered_faces( FaceSequence &seq, Face *f = NULL); 01314 // 01315 // Creates waves of nodes/faces starting from the boundary. Each vertex/face 01316 // is assigned layerID, denoting the position in the wave fronts. 01317 // Used in smoothing the nodes in Advancing front style. 01318 // 01319 int setWavefront(int ofwhat); 01320 size_t setNodeWavefront(int layerid); 01321 size_t setFaceWavefront(int layerid); 01322 int verify_front_ordering(int ofwhat); 01323 01324 NodeSet get_nearest_neighbors(const Point3D &p, int n = 1); 01325 NodeSet get_topological_neighbors(const NodeSequence &n, int k = 1); 01326 01327 int remove_unreferenced_nodes(); 01328 01329 // 01330 // Connect a strip of faces. Termination occurs when the face is reached 01331 // (1) At the boundary (2) Return back to the starting face. 01332 // There will be two strips per quadrilateral which are orthogonal to each 01333 // other. Using in the Ring Collapse Simplification 01334 // 01335 void get_quad_strips(Face *rootface, FaceSequence &strip1, 01336 FaceSequence &strip2); 01337 01338 // 01339 void set_strip_markers(); 01340 01341 // Collect all the boundary nodes in the mesh.. 01342 int get_bound_nodes( NodeSequence &seq); 01343 01344 // 01345 // Collect all the boundary faces in the mesh. The boundary faces could be 01346 // defined in two ways, bound_what flag is used for that purpose. 01347 // bound_what = 0 At least one vertex is on the boundary 01348 // = 1 At least one edge is on the boundary. 01349 // 01350 int get_bound_faces( FaceSequence &seq, int bound_what = 1); 01351 01352 // 01353 // Get the Aspect ratio of each face in the mesh. Aspect ratio is defined 01354 // as min_edge_length/max_edge_length.. 01355 // 01356 vector<double> getAspectRatio(bool sorted = 1); 01357 01358 // 01359 // Get unsigned surface area of the mesh. The calculation is for both 01360 // 2D and 3D surface elements... 01361 // 01362 double getSurfaceArea(); 01363 01364 // Check the Convexity.. 01365 int check_convexity(); 01366 01367 // Collect Quadlity Statistics 01368 int get_quality_statistics(const string &s); 01369 01370 // Get the nodes coordinates as a stream ( Used for interface with other 01371 // software. example Mesquite ) 01372 int getCoordsArray( vector<double> &a, vector<size_t> &l2g); 01373 01374 // Get the node connectivity as a stream ( Used for interface with other 01375 // software. example Mesquite ) 01376 int getNodesArray( vector<size_t> &a, vector<int> &topo); 01377 01378 // Reset the coordinates of nodes, ( Generally it comes from optimization 01379 // modules. The array size must match in order to reflect changes. 01380 int setCoordsArray(const vector<double> &v, const vector<size_t> &l2g); 01381 01382 // Check if there are duplicate faces in the mesh; 01383 01384 int hasDuplicates(int what); 01385 01386 void getMinMaxVertexDegrees(int &mind, int &maxd); 01387 void getMinMaxFaceArea(double &mind, double &maxd); 01388 01389 void setNormals(); 01390 01391 // 01392 // Refine the mesh into "n" segments and return newnodes and newfaces 01393 // inserted into the mesh structure. Old faces are reused, i.e. 01394 // they are deactivated and then reactivated with new connectivity... 01395 // 01396 // Requirement: At least two segments must be given... 01397 int refine_tri_edge( Vertex *v0, Vertex *v1, int n, 01398 NodeSequence &newnodes, FaceSequence &newfaces); 01399 01400 int collapse_tri_edge( Vertex *v0, Vertex *v1); 01401 01402 int refine_quads14(); 01403 int refine_quads15(); 01404 01405 int refine_quad14(Face *f); 01406 int refine_quad15(Face *f); 01407 01408 void collect_garbage(); 01409 int search_quad_patches(); 01410 01411 void build_edges(); 01412 private: 01413 volatile char adjTable[4][4]; 01414 size_t count_edges(); 01415 string meshname; 01416 01417 double normalize_factor; 01418 double getLength(int dir) const; 01419 01420 bool hasdual; 01421 bool boundary_known; 01422 01423 // Contains all the mesh entities. 01424 NodeSequence nodes; 01425 EdgeSequence edges; 01426 FaceSequence faces; 01427 01428 // Contains the nodes, edges and faces as STL list instead of vector. 01429 // This is dynamic structure to allow efficient refinement purposes. 01430 // 01431 // Contains selected mesh entities. 01432 NodeSequence feature_nodes; 01433 EdgeSequence feature_edges; 01434 FaceSequence feature_faces; 01435 01436 // Lazy garbage collection containers. 01437 NodeList garbageNodes; 01438 EdgeList garbageEdges; 01439 FaceList garbageFaces; 01440 01441 // Build Topological relations... 01442 int build_relations00(bool rebuild = 0); 01443 int build_relations01(bool rebuild = 0); 01444 int build_relations02(bool rebuild = 0); 01445 int build_relations12(bool rebuild = 0); 01446 01447 // Build wavefronts ... 01448 int setNodeWavefront(); 01449 int setFaceWavefront(); 01450 }; 01451 01452 //int mesh_unit_tests(); 01453 01454 struct MeshImporter { 01455 static const int SIMPLE_FORMAT = 0; 01456 static const int OFF_FORMAT = 1; 01457 static const int OBJ_FORMAT = 2; 01458 static const int VTK_FORMAT = 3; 01459 static const int TRIANGLE_FORMAT = 4; 01460 static const int CUBIT_FORMAT = 5; 01461 01462 Mesh * load(const string &fname, Mesh *m = NULL) { 01463 mesh = m; 01464 if (mesh == NULL) mesh = new Mesh; 01465 01466 int err = 1; 01467 if (fname.rfind(".vtk") != string::npos) { 01468 err = vtk_file(fname); 01469 } 01470 01471 if (fname.rfind(".off") != string::npos) { 01472 err = off_file(fname); 01473 } 01474 01475 if (fname.rfind(".dat") != string::npos) { 01476 err = simple_file(fname); 01477 } 01478 01479 if (fname.rfind(".cub") != string::npos) { 01480 err = cubit_file(fname); 01481 } 01482 01483 if (err) { 01484 err = triangle_file(fname); 01485 } 01486 01487 if( err ) return NULL; 01488 01489 if( !mesh->is_consistently_oriented() ) 01490 mesh->make_consistently_oriented(); 01491 01492 global2local.clear(); 01493 01494 return mesh; 01495 } 01496 01497 private: 01498 Mesh *mesh; 01499 std::map<int, int> global2local; 01500 void readTriNodes(const string & s); 01501 void readTriEdges(const string & s); 01502 void readTriFaces(const string & s); 01503 01504 // Different format files ... 01505 int vtk_file(const string & s); 01506 int off_file(const string & s); 01507 int simple_file(const string & s); 01508 int triangle_file(const string & s); 01509 int xml_file(const string & s); 01510 int cubit_file(const string & s); 01511 }; 01512 01513 struct MeshExporter { 01514 01515 static const int SIMPLE_FORMAT = 0; 01516 static const int OFF_FORMAT = 1; 01517 static const int OBJ_FORMAT = 2; 01518 static const int VTK_FORMAT = 3; 01519 static const int TRIANGLE_FORMAT = 4; 01520 static const int XML_FORMAT = 5; 01521 01522 int saveAs(Mesh *m, const string & fname) { 01523 01524 int err = 1; 01525 if (fname.rfind(".vtk") != string::npos) { 01526 err = vtk_file(m, fname); 01527 } 01528 01529 if (fname.rfind(".off") != string::npos) { 01530 err = off_file(m, fname); 01531 } 01532 01533 if (fname.rfind(".dat") != string::npos) { 01534 err = simple_file(m, fname); 01535 } 01536 01537 if (fname.rfind(".xml") != string::npos) { 01538 err = xml_file(m, fname); 01539 } 01540 01541 return err; 01542 } 01543 01544 private: 01545 int off_file(Mesh *m, const string & s); 01546 int simple_file(Mesh *m, const string & s); 01547 int vtk_file(Mesh *m, const string & s); 01548 int xml_file(Mesh *m, const string & s); 01549 }; 01550 01551 class MeshOptimization { 01552 public: 01553 static const int STEEPEST_DESCENT = 0; 01554 static const int QUASI_NEWTON = 1; 01555 static const int TRUST_REGION = 2; 01556 static const int FEASIBLE_NEWTON = 3; 01557 static const int CONJUGATE_GRADIENT = 4; 01558 static const int LAPLACIAN = 5; 01559 01560 int shape_optimize(Mesh * m, int algo = QUASI_NEWTON , int numiter = 10); 01561 01562 int bandwidth_reduction(Mesh * m); 01563 private: 01564 Mesh *inmesh; 01565 int execute(Mesh * m); 01566 01567 int algorithm; 01568 int numIter; 01569 01570 vector<int> vfixed; 01571 vector<size_t> vNodes; 01572 vector<int> etopo; 01573 vector<size_t> l2g; 01574 vector<double> vCoords; 01575 01576 #ifdef HAVE_MESQUITE 01577 Mesquite::QualityImprover *improver; 01578 Mesquite::ArrayMesh* jaal_to_mesquite(Mesh *m); 01579 #endif 01580 }; 01581 01583 01584 struct SurfPatch { 01585 public: 01586 void build() { 01587 search_boundary(); 01588 } 01589 01590 int count_boundary_segments() { 01591 return corners.size(); 01592 } 01593 01594 bool isClosed(); 01595 bool isSimple(); 01596 01597 NodeSequence get_boundary_segment_nodes(int i) { 01598 int ib = cornerPos[i]; 01599 int ie = cornerPos[i + 1]; 01600 return get_bound_nodes(bound_nodes[ib], bound_nodes[ie]); 01601 } 01602 01603 FaceSet faces; 01604 private: 01605 vector<int> segSize; // How many nodes on each segment. 01606 vector<int> cornerPos; // Positions of the corners in the bound_nodes. 01607 NodeSet corners; // Corners of the Blob 01608 NodeSet inner_nodes; // Inner nodes ( not on the boundary ) of the blob 01609 NodeSequence bound_nodes; // Boundary nodes 01610 vector<Edge> boundary; // boundary of the blob. 01611 NodeSequence get_bound_nodes(const Vertex *src, const Vertex * dst); 01612 int search_boundary(); 01613 int getPosOf(const Vertex * v); 01614 void set_boundary_segments(); 01615 int reorient_4_sided_loop(); 01616 void start_boundary_loop_from(Vertex * v); 01617 }; 01618 01620 01621 inline void RelationRep::addRelation(Vertex *vertex) 01622 { 01623 if (!hasRelation(vertex)) relations0.push_back(vertex); 01624 sort(relations0.begin(), relations0.end()); 01625 } 01626 01627 inline void RelationRep::addRelation(Edge *edge) 01628 { 01629 if (!hasRelation(edge)) relations1.push_back(edge); 01630 sort(relations1.begin(), relations1.end()); 01631 } 01632 01633 inline void RelationRep ::addRelation(Face* face) 01634 { 01635 if (!hasRelation(face)) relations2.push_back(face); 01636 sort(relations2.begin(), relations2.end()); 01637 } 01638 01639 inline void RelationRep::removeRelation(const Vertex *vertex) 01640 { 01641 if (hasRelation(vertex)) { 01642 NodeSequence::iterator it; 01643 it = remove(relations0.begin(), relations0.end(), vertex); 01644 relations0.erase(it, relations0.end()); 01645 } 01646 } 01647 01648 inline void RelationRep::removeRelation(const Edge *edge) 01649 { 01650 if (hasRelation(edge)) { 01651 EdgeSequence::iterator it; 01652 it = remove(relations1.begin(), relations1.end(), edge); 01653 relations1.erase(it, relations1.end()); 01654 } 01655 } 01656 01657 inline void RelationRep ::removeRelation(const Face *face) 01658 { 01659 if (hasRelation(face)) { 01660 FaceSequence::iterator it; 01661 it = remove(relations2.begin(), relations2.end(), face); 01662 relations2.erase(it, relations2.end()); 01663 } 01664 } 01665 01666 inline void RelationRep ::clearRelations(int t) 01667 { 01668 if (t == 0) relations0.clear(); 01669 if (t == 1) relations1.clear(); 01670 if (t == 2) relations2.clear(); 01671 } 01672 01673 inline bool RelationRep ::hasRelation(const Vertex* vertex) const 01674 { 01675 if (relations0.empty()) return 0; 01676 01677 NodeSequence::const_iterator it; 01678 01679 it = find(relations0.begin(), relations0.end(), vertex); 01680 if (it == relations0.end()) return 0; 01681 01682 return 1; 01683 } 01684 01685 inline bool RelationRep ::hasRelation(const Edge* edge) const 01686 { 01687 if (relations1.empty()) return 0; 01688 01689 EdgeSequence::const_iterator it; 01690 01691 it = find(relations1.begin(), relations1.end(), edge); 01692 if (it == relations1.end()) return 0; 01693 01694 return 1; 01695 } 01697 01698 inline bool RelationRep ::hasRelation(const Face* face) const 01699 { 01700 if (relations2.empty()) return 0; 01701 FaceSequence::const_iterator it; 01702 01703 it = find(relations2.begin(), relations2.end(), face); 01704 if (it == relations2.end()) return 0; 01705 01706 return 1; 01707 } 01708 01710 01711 inline int Vertex::get_ideal_face_degree(int n) const 01712 { 01713 if( n == 3 ) { 01714 if (!isBoundary()) return 6; 01715 01716 if (getSpanAngle() <= 90.0 ) return 1; 01717 if (getSpanAngle() <= 220.0) return 3; 01718 if (getSpanAngle() <= 300.0) return 4; 01719 return 5; 01720 } 01721 01722 if( n == 4 ) { 01723 if (!isBoundary()) return 4; 01724 01725 if (getSpanAngle() <= 100 ) return 1; 01726 if (getSpanAngle() <= 220.0) return 2; 01727 if (getSpanAngle() <= 300.0) return 3; 01728 return 4; 01729 } 01730 01731 cout << "Error: Ideal vertex degree only for Quad right now " << endl; 01732 exit(0); 01733 } 01734 01736 01737 inline void Face::start_from_concave_corner() 01738 { 01739 int pos = concaveAt(); 01740 if (pos < 1) return; 01741 01742 int nsize = getSize(0); 01743 NodeSequence rotated(nsize); 01744 for (int i = 0; i < nsize; i++) 01745 rotated[i] = connect[ (pos + i) % nsize ]; 01746 connect = rotated; 01747 } 01749 01750 inline NodeSequence Mesh::generate_nodes(size_t n) 01751 { 01752 assert(n > 0); 01753 NodeSequence seq(n); 01754 for (size_t i = 0; i < n; i++) 01755 seq[i] = Vertex::newObject(); 01756 return seq; 01757 } 01759 01760 inline FaceSequence Mesh::generate_faces(size_t n) 01761 { 01762 assert(n > 0); 01763 FaceSequence seq(n); 01764 for (size_t i = 0; i < n; i++) 01765 seq[i] = Face::newObject(); 01766 return seq; 01767 } 01769 01770 inline int Mesh::remove(PNode v) 01771 { 01772 if (v == NULL) return 1; 01773 01774 if (v->isRemoved()) return 0; 01775 01776 size_t nSize; 01777 01778 FaceSequence vfaces; 01779 NodeSequence vneighs; 01780 01781 if( v->isActive() ) { 01782 01783 if (adjTable[0][2]) { 01784 v->getRelations( vfaces ); 01785 nSize = vfaces.size(); 01786 for (size_t i = 0; i < nSize; i++) { 01787 if (!vfaces[i]->isRemoved()) { 01788 cout << "Warning: The vertex is currently used by face: vertex not removed" << endl; 01789 cout << "Debug : Vertex ID : " << v->getID() << endl; 01790 cout << "Face: "; 01791 for( int j = 0; j < vfaces[i]->getSize(0); j++) 01792 cout << vfaces[i]->getNodeAt(j)->getID() << " "; 01793 cout << endl; 01794 return 1; 01795 } 01796 } 01797 v->clearRelations(2); 01798 } 01799 01800 if (adjTable[0][0]) { 01801 v->getRelations( vneighs ); 01802 nSize = vneighs.size(); 01803 for (size_t i = 0; i < nSize; i++) 01804 vneighs[i]->removeRelation(v); 01805 v->clearRelations(0); 01806 } 01807 } 01808 01809 v->setStatus(MeshEntity::REMOVE); 01810 garbageNodes.push_back(v); 01811 01812 return 0; 01813 } 01814 01816 01817 inline int Mesh::addFace(PFace f) 01818 { 01819 faces.push_back(f); 01820 int nSize = f->getSize(0); 01821 01822 adjTable[2][0] = 1; 01823 01824 if (adjTable[0][2]) { 01825 for (int i = 0; i < nSize; i++) { 01826 Vertex *v = f->getNodeAt(i); 01827 v->addRelation(f); 01828 } 01829 } 01830 01831 if (adjTable[1][0]) { 01832 for (int i = 0; i < nSize; i++) { 01833 Vertex *v0 = f->getNodeAt(i); 01834 Vertex *v1 = f->getNodeAt(i+1); 01835 Vertex *vi = min( v0, v1); 01836 Vertex *vj = max( v0, v1); 01837 if( !vi->hasRelation(vj) ) { 01838 Edge *edge = new Edge(vi, vj); 01839 edges.push_back(edge); 01840 vi->addRelation(vj); 01841 vj->addRelation(vi); 01842 } 01843 } 01844 } 01845 01846 if (adjTable[0][0]) { 01847 for (int i = 0; i < nSize; i++) { 01848 Vertex *vi = f->getNodeAt((i + 0)); 01849 Vertex *vj = f->getNodeAt((i + 1)); 01850 vi->addRelation(vj); 01851 vj->addRelation(vi); 01852 } 01853 } 01854 01855 f->setStatus(MeshEntity::ACTIVE); 01856 return 0; 01857 } 01858 01860 01861 inline int Mesh::remove(PFace f) 01862 { 01863 if( f == NULL ) return 0; 01864 if( f->isRemoved() ) return 0; 01865 01866 int nSize = f->getSize(0); 01867 01868 FaceSequence vfaces; 01869 01870 if( f->isActive() ) { 01871 if (adjTable[0][0]) { 01872 for (int i = 0; i < nSize; i++) { 01873 Vertex *vi = f->getNodeAt(i + 0); 01874 Vertex *vj = f->getNodeAt(i + 1); 01875 Mesh::getRelations112(vi, vj, vfaces); 01876 if (vfaces.size() == 1) { 01877 vi->removeRelation(vj); 01878 vj->removeRelation(vi); 01879 } 01880 } 01881 } 01882 01883 if (adjTable[0][2]) { 01884 for (int i = 0; i < nSize; i++) { 01885 Vertex *v = f->getNodeAt(i); 01886 v->removeRelation(f); 01887 } 01888 } 01889 } 01890 f->setStatus(MeshEntity::REMOVE); 01891 garbageFaces.push_back(f); 01892 01893 return 0; 01894 } 01895 01897 01898 inline int Mesh::deactivate(PNode vi) 01899 { 01900 assert(!vi->isRemoved()); 01901 01902 NodeSequence vneighs; 01903 if (adjTable[0][0]) { 01904 vi->getRelations( vneighs ); 01905 int nSize = vneighs.size(); 01906 for (int j = 0; j < nSize; j++) { 01907 Vertex *vj = vneighs[j]; 01908 vj->removeRelation(vi); 01909 } 01910 vi->clearRelations(0); 01911 } 01912 01913 if (adjTable[0][2]) vi->clearRelations(2); 01914 01915 vi->setStatus(MeshEntity::INACTIVE); 01916 01917 return 0; 01918 } 01920 01921 inline int Mesh::deactivate(PFace face) 01922 { 01923 // For the time being. but if you change the API, reimplement it. 01924 // The "remove" function can remove the elements immediately and 01925 // free the memory, but deactivate doesn't free it until garbage] 01926 // collection is called. Therefore, an element can be reused. 01927 // A deactivate element, looses all the information associated with 01928 // it. 01929 01930 assert(!face->isRemoved()); 01931 01932 if (adjTable[0][2]) { 01933 for (int i = 0; i < face->getSize(0); i++) { 01934 Vertex *vertex = face->getNodeAt(i); 01935 vertex->removeRelation(face); 01936 } 01937 } 01938 01939 face->setStatus(MeshEntity::INACTIVE); 01940 01941 return 0; 01942 } 01943 01945 01946 inline int Mesh::reactivate(PNode vertex) 01947 { 01948 FaceSequence vfaces; 01949 if (adjTable[0][0]) { 01950 vertex->getRelations( vfaces ); 01951 int numFaces = vfaces.size(); 01952 for (int i = 0; i < numFaces; i++) { 01953 int nsize = vfaces[i]->getSize(0); 01954 for (int j = 0; j < nsize; j++) { 01955 Vertex *vi = vfaces[i]->getNodeAt(i + 0); 01956 Vertex *vj = vfaces[i]->getNodeAt(i + 1); 01957 vi->addRelation(vj); 01958 vj->addRelation(vi); 01959 } 01960 } 01961 } 01962 vertex->setStatus(MeshEntity::ACTIVE); 01963 01964 return 0; 01965 } 01966 01968 01969 inline int Mesh::reactivate(PFace face) 01970 { 01971 int nsize = face->getSize(0); 01972 01973 if (adjTable[0][0]) { 01974 for (int i = 0; i < nsize; i++) { 01975 Vertex *vi = face->getNodeAt(i + 0); 01976 Vertex *vj = face->getNodeAt(i + 1); 01977 assert(!vi->isRemoved()); 01978 assert(!vj->isRemoved()); 01979 vi->addRelation(vj); 01980 vj->addRelation(vi); 01981 } 01982 } 01983 01984 if (adjTable[0][2]) { 01985 for (int i = 0; i < nsize; i++) { 01986 Vertex *vi = face->getNodeAt(i); 01987 assert(!vi->isRemoved()); 01988 vi->addRelation(face); 01989 } 01990 } 01991 01992 face->setStatus(MeshEntity::ACTIVE); 01993 return 0; 01994 } 01995 01997 01998 Mesh *create_structured_mesh(double *origin, double *length, int *griddim, int spacedim); 01999 Mesh* quad_to_tri4( Mesh *quadmesh, vector<Vertex*> &steiner); 02000 Mesh* quad_to_tri2( Mesh *quadmesh ); 02001 02002 void set_tfi_coords(int i, int j, int nx, int ny, vector<Vertex*> &qnodes); 02003 02004 void linear_interpolation(Mesh *m, Vertex *v0, Vertex *v1, int n, NodeSequence &seq); 02005 02006 void advancing_front_triangle_cleanup ( Mesh *mesh ); 02007 // 02008 // QTrack is similar to "Motorcycle graph" proposed by Eppestein group. 02009 // But somehow, I don't like this term. 02010 // 02011 02012 struct QTrack { 02013 const static int END_AT_TERMINALS = 0; 02014 const static int END_AT_CROSSINGS = 1; 02015 02016 Mesh *mesh; 02017 02018 NodeSequence sequence; 02019 02020 bool operator ==(const QTrack & rhs) const { 02021 size_t nSize = sequence.size(); 02022 if (nSize != rhs.sequence.size()) return 0; 02023 02024 Vertex *v0src = sequence.front(); 02025 Vertex *v0dst = sequence.back(); 02026 Vertex *v1src = rhs.sequence.front(); 02027 Vertex *v1dst = rhs.sequence.back(); 02028 02029 if (v0src == v1src && v0dst == v1dst) return 1; 02030 if (v0src == v1dst && v0dst == v1src) return 1; 02031 02032 return 0; 02033 } 02034 02035 bool operator<(const QTrack & rhs) const { 02036 return sequence.size() < rhs.sequence.size(); 02037 } 02038 02040 // There are two ways to advance along the track. 02041 // (1) Incremental: All track propagate simulateneously and 02042 // at the intersection, only one is allowed 02043 // to proceed towards other irregular node. 02044 // (11) Greedy : Start from one vertex and complete its 02045 // track. 02046 // It is not clear which method is better, but "greedy" may likely 02047 // give very high aspect ratio quad patches. Incremental on the 02048 // other hand may produce many small patches.. 02049 // 02051 02052 void advance(int endat); 02053 private: 02054 int advance_single_step(int endat); 02055 }; 02056 02057 vector<QTrack> generate_quad_partitioning(Mesh *mesh); 02058 02060 02061 struct StructuredMesh2D { 02062 02063 StructuredMesh2D() { 02064 nx = ny = 0; 02065 } 02066 int nx, ny; 02067 02068 FaceSequence faces; 02069 NodeSequence nodes; 02070 02071 NodeSet cornerNodes; 02072 02073 void clearAll() { 02074 nodes.clear(); 02075 faces.clear(); 02076 neighs.clear(); 02077 cornerNodes.clear(); 02078 nx = 0; 02079 ny = 0; 02080 } 02081 02082 bool operator<(const StructuredMesh2D & rhs) const { 02083 return this->getSize(2) < rhs.getSize(2); 02084 } 02085 02086 size_t getSize(int e) const { 02087 if (e == 0) return nodes.size(); 02088 if (e == 2) return faces.size(); 02089 return 0; 02090 } 02091 02092 int myID; 02093 vector<int> neighs; 02094 }; 02095 02097 // Set Tag Values for Visualzation and sometimes debugging 02099 void set_layer_tag(Mesh *m, const string &s = "Layer"); 02100 void set_inverted_tag(Mesh *m, const string &s = "Inverted" ); 02101 void set_boundary_tag(Mesh *m, const string &s = "Boundary"); 02102 void set_partition_tag(Mesh *m, const string &s = "Partition"); 02103 void set_convexity_tag(Mesh *m , const string &s = "Convexity" ); 02104 void set_regular_node_tag(Mesh *m, const string &s = "Regularity" ); 02105 02106 void set_visit_tags(Mesh *m); 02107 void set_allboundnodes_tag(Mesh *m); 02108 void set_constrained_tag(Mesh *m); 02109 void set_feature_angle_tag(Mesh *m); 02110 void set_ideal_node_tag(Mesh *m, int elemtype); 02111 void set_large_area_tag(Mesh *m); 02112 void set_tiny_area_tag(Mesh *m, double val = 1.0E-06); 02113 void set_irregular_path_tag(Mesh *m, vector<QTrack> &qp); 02114 02116 // Graph Matching operations .... 02118 02119 int quadrangulate(Mesh *mesh); 02120 02122 //Helper functions .... 02124 Mesh *struct_tri_grid(int nx, int ny); 02125 Mesh *struct_quad_grid(int nx, int ny); 02126 02128 // Mesh Optimization ... 02130 02131 struct LaplaceWeight { 02132 virtual double get(const Vertex *apex, const Vertex * neigh) = 0; 02133 }; 02134 02135 struct LaplaceNoWeight : public LaplaceWeight { 02136 02137 double get(const Vertex *apex, const Vertex * neigh) { 02138 return 1.0; 02139 } 02140 }; 02141 02142 struct LaplaceLengthWeight : public LaplaceWeight { 02143 02144 double get(const Vertex *apex, const Vertex * neigh) { 02145 double len = Vertex::length(apex, neigh); 02146 return len; 02147 } 02148 }; 02149 02150 struct LaplaceAreaWeight : public LaplaceWeight { 02151 02152 FaceSequence vfaces; 02153 double get(const Vertex *apex, const Vertex * neighs) { 02154 neighs->getRelations( vfaces ); 02155 double area = 0.0; 02156 for (size_t i = 0; i < vfaces.size(); i++) 02157 area += vfaces[i]->getArea(); 02158 return area; 02159 } 02160 }; 02161 02162 class LaplaceSmoothing { 02163 public: 02164 02165 LaplaceSmoothing(Mesh *m, int n = 100) { 02166 mesh = m; 02167 numIters = n; 02168 verbose = 0; 02169 lambda = 1.0; 02170 lapweight = NULL; 02171 method = 0; 02172 maxerror = 0; 02173 } 02174 02175 void setMethod(int m) { 02176 method = m; 02177 } 02178 02179 void setNumIterations(int n) { 02180 numIters = n; 02181 } 02182 02183 int execute(); 02184 02185 void setWeight(LaplaceWeight *w) { 02186 lapweight = w; 02187 } 02188 02189 int localized_at(const NodeSequence &q); 02190 02191 int convexify(); 02192 02193 double getError() { 02194 return maxerror; 02195 } 02196 02197 private: 02198 Mesh *mesh; 02199 int global_smoothing(); 02200 02201 struct LVertex { 02202 Vertex *apex; 02203 map<Vertex*, NodeSequence> neighs; 02204 }; 02205 02206 vector<LVertex> lnodes; 02207 LaplaceWeight *lapweight; 02208 vector<double> backupCoordsArray; 02209 vector<double> facearea; 02210 int method; 02211 int verbose; 02212 int numIters; 02213 double lambda; 02214 double maxerror; 02215 Point3D displace(const Point3D &src, const Point3D &dst, double r); 02216 02217 double update_vertex_position(Vertex *vertex); 02218 double update_vertex_position(Vertex *vertex, const Point3D &p); 02219 }; 02220 02221 int quad_concave_tests(); 02222 } // namespace Jaal 02223 02224 void plot_all_quad_quality_measures( Jaal::Mesh *mesh ); 02225 void plot_all_tri_quality_measures( Jaal::Mesh *mesh ); 02226 02227 #endif 02228