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