├── .gitignore
├── Acknowledgments.txt
├── README
├── VS_files
├── SimplexMesh.sln
├── SimplexMesh.vcxproj
└── Test.vcxproj
├── headers
├── IncidenceMatrix.h
├── SimplexHandles.h
├── SimplexIterators.h
├── SimplexProperty.h
└── SimplicialComplex.h
├── src
├── IncidenceMatrix.cpp
├── SimplexIterators.cpp
└── SimplicialComplex.cpp
└── test
└── test.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | *.sdf
2 | *.user
3 | *.suo
4 | *.filters
5 | *.obj
6 | *.lib
7 | *.log
8 | *.tlog
9 | *.manifest
10 | *.lastbuildstate
11 | *.pdb
12 | *.opensdf
13 | *.ipch
14 | *.exe
15 |
--------------------------------------------------------------------------------
/Acknowledgments.txt:
--------------------------------------------------------------------------------
1 | This code was initially developed primarily by Christopher Batty during a postdoc under Eitan Grinspun in Columbia University's Computer Graphics Group (C2G2), supported by a Banting Postdoctoral Fellowship. The C2G2 lab itself is supported in part by the Sloan Foundation, the NSF (grants CMMI-11-29917, IIS-11-17257, IIS-10-48948, IIS-09-16129, CCF-06-43268), and generous gifts from Adobe, Autodesk, Intel, mental images, NVIDIA, Side Effects Software, and The Walt Disney Company.
2 |
3 | Thanks are also due to other members of the lab for helpful discussions and suggestions, including Andres Uribe, Fang Da, Danny Kaufman, and Breannan Smith.
4 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | The goal is to construct a general non-manifold, non-regular simplicial mesh data structure and library for representing simplicial complexes up to 3D (verts, edges, faces, tets) and associated data stored on the simplices.
2 | (This essentially means a mesh that mixes and matches regions of solo vertices, segments, triangles and tetrahedra, rather than requiring restrictions, e.g. only triangles, embedded in 3D, with no non-manifold edges.)
3 | Priority is given to simplicity and usability over speed, hence the choice (for now at least) of using a representation based loosely on sparse incidence matrices. Our goal is to facilitate research in non-manifold mesh processing and simulation.
4 |
5 | Because of the potential complexity of such meshes, the intention is for mesh operations to rely on a core set of "atomic" operations of the form addSimplex/deleteSimplex, and write all other operations in terms of these ones. Only common operations that would be significantly accelerated by being integrated into the core data structure should be implemented within SimplicialComplex itself, while all others should be relegated to external utility functions/classes.
6 |
7 | The underlying data structure is analogous to that discussed in "Building Your Own DEC at Home" by Sharif Elcott and Peter Schroeder, again emphasizing simplicity. Ultimately, it should be possible to swap this out for a more efficient (but complex) one, if desired. E.g. the IA* data structure from the SMI paper "IA*: An Adjacency-Based Representation for Non-Manifold Simplicial Shapes in Arbitrary Dimensions" by Canino, de Floriani, and Weiss.
8 |
9 | Likewise, since the code is intended for research purposes, we should err on the side of safety when we can, by spending extra effort to make handles (and possibly some iterators) robust in the face of mesh editing. This has not been done yet.
10 |
11 | We aim for a similar degree of ease of use (and relatively comparable API) as the recent Surface_mesh library for triangle meshes, by Daniel Sieger and Mario Botsch described in the IMR paper "Design, Implementation, and Evaluation of the Surface mesh Data Structure".
12 |
--------------------------------------------------------------------------------
/VS_files/SimplexMesh.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 11.00
3 | # Visual Studio 2010
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimplexMesh", "SimplexMesh.vcxproj", "{B5F86F74-CB6D-424B-99DC-3A34EC8B374F}"
5 | EndProject
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "Test.vcxproj", "{4DF8B7AC-56CE-4F35-88C6-FC0ACC739EE0}"
7 | ProjectSection(ProjectDependencies) = postProject
8 | {B5F86F74-CB6D-424B-99DC-3A34EC8B374F} = {B5F86F74-CB6D-424B-99DC-3A34EC8B374F}
9 | EndProjectSection
10 | EndProject
11 | Global
12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
13 | Debug|Win32 = Debug|Win32
14 | Release|Win32 = Release|Win32
15 | EndGlobalSection
16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
17 | {B5F86F74-CB6D-424B-99DC-3A34EC8B374F}.Debug|Win32.ActiveCfg = Debug|Win32
18 | {B5F86F74-CB6D-424B-99DC-3A34EC8B374F}.Debug|Win32.Build.0 = Debug|Win32
19 | {B5F86F74-CB6D-424B-99DC-3A34EC8B374F}.Release|Win32.ActiveCfg = Release|Win32
20 | {B5F86F74-CB6D-424B-99DC-3A34EC8B374F}.Release|Win32.Build.0 = Release|Win32
21 | {4DF8B7AC-56CE-4F35-88C6-FC0ACC739EE0}.Debug|Win32.ActiveCfg = Debug|Win32
22 | {4DF8B7AC-56CE-4F35-88C6-FC0ACC739EE0}.Debug|Win32.Build.0 = Debug|Win32
23 | {4DF8B7AC-56CE-4F35-88C6-FC0ACC739EE0}.Release|Win32.ActiveCfg = Release|Win32
24 | {4DF8B7AC-56CE-4F35-88C6-FC0ACC739EE0}.Release|Win32.Build.0 = Release|Win32
25 | EndGlobalSection
26 | GlobalSection(SolutionProperties) = preSolution
27 | HideSolutionNode = FALSE
28 | EndGlobalSection
29 | EndGlobal
30 |
--------------------------------------------------------------------------------
/VS_files/SimplexMesh.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {B5F86F74-CB6D-424B-99DC-3A34EC8B374F}
15 | SimplexMesh
16 |
17 |
18 |
19 | StaticLibrary
20 | true
21 | MultiByte
22 | v110
23 |
24 |
25 | StaticLibrary
26 | false
27 | true
28 | MultiByte
29 | v110
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | Level3
45 | Disabled
46 | C:\Users\Christopher Batty\Documents\Research\GitHub\SimplexMesh\headers;%(AdditionalIncludeDirectories)
47 |
48 |
49 | true
50 |
51 |
52 |
53 |
54 | Level3
55 | MaxSpeed
56 | true
57 | true
58 | ..\headers;%(AdditionalIncludeDirectories)
59 |
60 |
61 | true
62 | true
63 | true
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/VS_files/Test.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 |
15 |
16 |
17 | {4DF8B7AC-56CE-4F35-88C6-FC0ACC739EE0}
18 | Win32Proj
19 | Test
20 |
21 |
22 |
23 | Application
24 | true
25 | Unicode
26 | v110
27 |
28 |
29 | Application
30 | false
31 | true
32 | Unicode
33 | v110
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | true
47 |
48 |
49 | false
50 |
51 |
52 |
53 |
54 |
55 | Level3
56 | Disabled
57 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
58 |
59 |
60 | Console
61 | true
62 |
63 |
64 |
65 |
66 | Level3
67 |
68 |
69 | MaxSpeed
70 | true
71 | true
72 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
73 | ..\headers;%(AdditionalIncludeDirectories)
74 |
75 |
76 | Console
77 | true
78 | true
79 | true
80 | ..\VS_files\Release;%(AdditionalLibraryDirectories)
81 | SimplexMesh.lib;%(AdditionalDependencies)
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/headers/IncidenceMatrix.h:
--------------------------------------------------------------------------------
1 | #ifndef INCIDENCEMATRIX_H
2 | #define INCIDENCEMATRIX_H
3 |
4 | #include
5 | #include
6 |
7 | namespace SimplexMesh {
8 |
9 | //A simple std::vector-based sparse compressed row incidence matrix
10 | //to store the topology of our simplex mesh structure.
11 | //It needs to be resize-able in order to add/delete simplices.
12 | class IncidenceMatrix {
13 |
14 | private:
15 |
16 | //Matrix dimensions
17 | unsigned int n_rows, n_cols;
18 |
19 | //For each row, a list of all column indices, in oriented order where appropriate.
20 | //The sign indicates whether the value is intended to be: +1 or -1.
21 | //NOTE: We shift all column indices up by 1, so the zero'th column is enabled to have a sign!
22 | std::vector< std::vector > m_indices;
23 |
24 | public:
25 | IncidenceMatrix();
26 | IncidenceMatrix(unsigned int rows, unsigned int cols);
27 |
28 | //Matrix dimensions
29 | unsigned int getNumRows() const {return n_rows;}
30 | unsigned int getNumCols() const {return n_cols;}
31 | void addRows(unsigned int rows);
32 | void addCols(unsigned int cols);
33 |
34 | //Regular accessors
35 | void set(unsigned int i, unsigned int j, int new_val);
36 | int get(unsigned int i, unsigned int j) const;
37 | bool exists(unsigned int i, unsigned int j) const;
38 | void remove(unsigned int i, unsigned int j);
39 | void zeroRow(unsigned int i);
40 | void zeroAll();
41 |
42 | void cycleRow(unsigned int index); //permute the row by shifting them all over by 1
43 |
44 | //Constant-time access within the row, by row-index rather than column number
45 | unsigned int getNumEntriesInRow(unsigned int row) const;
46 | unsigned int getColByIndex(unsigned int i, unsigned int index_in_row) const;
47 | int getValueByIndex(unsigned int i, unsigned int index_in_row) const;
48 | void setByIndex(unsigned int i, unsigned int index_in_row, unsigned int col, int val);
49 |
50 | //Debugging
51 | void printMatrix() const;
52 | };
53 |
54 | } // namespace SimplexMesh
55 |
56 |
57 | #endif //INCIDENCEMATRIX_H
--------------------------------------------------------------------------------
/headers/SimplexHandles.h:
--------------------------------------------------------------------------------
1 | #ifndef SIMPLEXHANDLES_H
2 | #define SIMPLEXHANDLES_H
3 |
4 | namespace SimplexMesh {
5 |
6 |
7 | /** Handle for referring to a vertex */
8 | class VertexHandle
9 | {
10 |
11 | private:
12 | int m_idx;
13 | explicit VertexHandle(int idx) : m_idx(idx) {}
14 | int idx() const { return m_idx; }
15 |
16 | public:
17 |
18 | explicit VertexHandle() : m_idx(-1) {}
19 |
20 | friend class VertexIterator;
21 | friend class VertexVertexIterator;
22 | friend class VertexEdgeIterator;
23 | friend class EdgeVertexIterator;
24 | friend class VertexFaceIterator;
25 |
26 | friend class VertexIterator;
27 | friend class VertexEdgeIterator;friend class EdgeVertexIterator;
28 |
29 | friend class SimplicialComplex;
30 |
31 | template friend class VertexProperty;
32 |
33 | bool operator== (const VertexHandle& rhs) const { return m_idx == rhs.m_idx; }
34 | bool operator!= (const VertexHandle& rhs) const { return m_idx != rhs.m_idx; }
35 | bool operator< (const VertexHandle& rhs) const { return m_idx < rhs.m_idx; }
36 |
37 | bool isValid() const { return m_idx >= 0; }
38 | static VertexHandle invalid() { return VertexHandle(-1); }
39 | };
40 |
41 | /** Handle for referring to an edge */
42 | class EdgeHandle
43 | {
44 |
45 | private:
46 | int m_idx;
47 | explicit EdgeHandle(int idx) : m_idx(idx) {}
48 | int idx() const { return m_idx; }
49 |
50 | public:
51 |
52 | explicit EdgeHandle() : m_idx(-1) {}
53 |
54 | friend class EdgeIterator;
55 | friend class VertexEdgeIterator;
56 | friend class EdgeVertexIterator;
57 | friend class FaceEdgeIterator;
58 | friend class EdgeFaceIterator;
59 | friend class FaceVertexIterator;
60 |
61 | friend class EdgeIterator;
62 | friend class VertexEdgeIterator; friend class EdgeVertexIterator;
63 | friend class EdgeFaceIterator; friend class FaceEdgeIterator;
64 |
65 | friend class SimplicialComplex;
66 |
67 | template friend class EdgeProperty;
68 |
69 | bool operator== (const EdgeHandle& rhs) const { return m_idx == rhs.m_idx; }
70 | bool operator!= (const EdgeHandle& rhs) const { return m_idx != rhs.m_idx; }
71 | bool operator< (const EdgeHandle& rhs) const { return m_idx < rhs.m_idx; }
72 |
73 | bool isValid() const { return m_idx >= 0; }
74 |
75 | static EdgeHandle invalid() { return EdgeHandle(-1); }
76 | };
77 |
78 | /** Handle for referring to a face */
79 | class FaceHandle
80 | {
81 | private:
82 | int m_idx;
83 | explicit FaceHandle(int idx) : m_idx(idx) {}
84 | int idx() const { return m_idx; }
85 |
86 | public:
87 |
88 | explicit FaceHandle() : m_idx(-1) {}
89 |
90 | friend class FaceIterator;
91 | friend class FaceEdgeIterator;
92 | friend class EdgeFaceIterator;
93 | friend class FaceVertexIterator;
94 | friend class VertexFaceIterator;
95 | friend class SimplicialComplex;
96 |
97 | friend class FaceIterator;
98 | friend class FaceEdgeIterator;
99 | friend class EdgeFaceIterator;
100 | friend class FaceTetIterator;
101 | friend class TetFaceIterator;
102 |
103 | template friend class FaceProperty;
104 |
105 | bool operator== (const FaceHandle& rhs) const { return m_idx == rhs.m_idx; }
106 | bool operator!= (const FaceHandle& rhs) const { return m_idx != rhs.m_idx; }
107 | bool operator< (const FaceHandle& rhs) const { return m_idx < rhs.m_idx; }
108 |
109 | bool isValid() const { return m_idx >= 0; }
110 |
111 | static FaceHandle invalid() { return FaceHandle(-1); }
112 | };
113 |
114 | /** Handle for referring to a tet */
115 | class TetHandle
116 | {
117 |
118 | private:
119 | int m_idx;
120 | explicit TetHandle(int idx) : m_idx(idx) {}
121 | int idx() const { return m_idx; }
122 |
123 | public:
124 |
125 | explicit TetHandle() : m_idx(-1) {}
126 |
127 | friend class TetIterator;
128 | friend class SimplicialComplex;
129 |
130 | friend class TetIterator;
131 | friend class FaceTetIterator; friend class TetFaceIterator;
132 |
133 | template friend class TetProperty;
134 |
135 | bool operator== (const TetHandle& rhs) const { return m_idx == rhs.m_idx; }
136 | bool operator!= (const TetHandle& rhs) const { return m_idx != rhs.m_idx; }
137 | bool operator< (const TetHandle& rhs) const { return m_idx < rhs.m_idx; }
138 |
139 | bool isValid() const { return m_idx >= 0; }
140 |
141 | static TetHandle invalid() { return TetHandle(-1); }
142 | };
143 |
144 |
145 |
146 | } // namespace SimplexMesh
147 |
148 | #endif // SIMPLEXHANDLES_H
149 |
--------------------------------------------------------------------------------
/headers/SimplexIterators.h:
--------------------------------------------------------------------------------
1 | #ifndef SIMPLEXITERATORS_H
2 | #define SIMPLEXITERATORS_H
3 |
4 | #include "SimplicialComplex.h"
5 | #include "SimplexHandles.h"
6 |
7 | #include
8 |
9 | namespace SimplexMesh
10 | {
11 |
12 | //////////////////////////////////////////////////////////////////////////
13 | //Basic iterators
14 |
15 | class VertexIterator {
16 | public:
17 | VertexIterator(const SimplicialComplex& obj);
18 | void advance();
19 | bool done() const;
20 | VertexHandle current() const;
21 |
22 | private:
23 | int m_idx;
24 | const SimplicialComplex& m_obj;
25 |
26 | };
27 |
28 | class EdgeIterator {
29 | public:
30 | EdgeIterator(const SimplicialComplex& obj);
31 | void advance();
32 | bool done() const;
33 | EdgeHandle current() const;
34 |
35 | private:
36 | int m_idx;
37 | const SimplicialComplex& m_obj;
38 |
39 | };
40 |
41 |
42 | class FaceIterator {
43 | public:
44 | FaceIterator(const SimplicialComplex& obj);
45 | void advance();
46 | bool done() const;
47 | FaceHandle current() const;
48 |
49 | private:
50 | int m_idx;
51 | const SimplicialComplex& m_obj;
52 |
53 | };
54 |
55 | class TetIterator {
56 | public:
57 | TetIterator(const SimplicialComplex& obj);
58 | void advance();
59 | bool done() const;
60 | TetHandle current() const;
61 |
62 | private:
63 | int m_idx;
64 | const SimplicialComplex& m_obj;
65 |
66 | };
67 |
68 |
69 |
70 | //////////////////////////////////////////////////////////////////////////
71 | //Adjacency iterators
72 |
73 | class VertexEdgeIterator {
74 | public:
75 | VertexEdgeIterator(const SimplicialComplex& obj, const VertexHandle& vh);
76 | void advance();
77 | bool done() const;
78 | EdgeHandle current() const;
79 |
80 | private:
81 | int m_idx;
82 | VertexHandle m_vh;
83 | const SimplicialComplex& m_obj;
84 |
85 | };
86 |
87 | class EdgeVertexIterator {
88 | public:
89 | EdgeVertexIterator(const SimplicialComplex& obj, const EdgeHandle& eh, bool ordered = false);
90 | void advance();
91 | bool done() const;
92 | VertexHandle current() const;
93 |
94 | private:
95 | bool m_ordered;
96 | int m_idx;
97 | EdgeHandle m_eh;
98 | const SimplicialComplex& m_obj;
99 |
100 | };
101 |
102 | class VertexVertexIterator {
103 | public:
104 | VertexVertexIterator(const SimplicialComplex& obj, const VertexHandle& vh);
105 | void advance();
106 | bool done() const;
107 | VertexHandle current() const;
108 |
109 | private:
110 | int m_idx;
111 | VertexHandle m_vh;
112 | const SimplicialComplex& m_obj;
113 |
114 | };
115 |
116 | class EdgeFaceIterator {
117 | public:
118 | EdgeFaceIterator(const SimplicialComplex& obj, const EdgeHandle& eh);
119 | void advance();
120 | bool done() const;
121 | FaceHandle current() const;
122 |
123 | private:
124 | int m_idx;
125 | EdgeHandle m_eh;
126 | const SimplicialComplex& m_obj;
127 |
128 | };
129 |
130 | class FaceEdgeIterator {
131 | public:
132 | FaceEdgeIterator(const SimplicialComplex& obj, const FaceHandle& eh, bool ordered = false);
133 | void advance();
134 | bool done() const;
135 | EdgeHandle current() const;
136 |
137 | private:
138 | bool m_ordered;
139 | int m_idx;
140 | EdgeHandle m_cur;
141 | FaceHandle m_fh;
142 | const SimplicialComplex& m_obj;
143 |
144 | };
145 |
146 |
147 | class FaceTetIterator {
148 | public:
149 | FaceTetIterator(const SimplicialComplex& obj, const FaceHandle& eh);
150 | void advance();
151 | bool done() const;
152 | TetHandle current() const;
153 |
154 | private:
155 | int m_idx;
156 | FaceHandle m_fh;
157 | const SimplicialComplex& m_obj;
158 |
159 | };
160 |
161 | class TetFaceIterator {
162 | public:
163 | TetFaceIterator(const SimplicialComplex& obj, const TetHandle& eh);
164 | void advance();
165 | bool done() const;
166 | FaceHandle current() const;
167 |
168 | private:
169 | int m_idx;
170 | TetHandle m_th;
171 | const SimplicialComplex& m_obj;
172 |
173 | };
174 |
175 | //////////////////////////////////////////////////////////////////////////
176 | //Trickier adjacency iterators
177 |
178 | class VertexFaceIterator {
179 | public:
180 | VertexFaceIterator(const SimplicialComplex& obj, const VertexHandle& vh);
181 | void advance();
182 | bool done() const;
183 | FaceHandle current() const;
184 |
185 | private:
186 |
187 | const SimplicialComplex& m_obj;
188 | std::set m_faces;
189 | std::set::iterator m_fiter;
190 |
191 | };
192 |
193 | class FaceVertexIterator {
194 | public:
195 | FaceVertexIterator(const SimplicialComplex& obj, const FaceHandle& fh, bool ordered = false);
196 | void advance();
197 | bool done() const;
198 | VertexHandle current() const;
199 |
200 | private:
201 | FaceHandle m_fh;
202 | FaceEdgeIterator m_feit;
203 | const SimplicialComplex& m_obj;
204 |
205 | };
206 |
207 | class VertexTetIterator {
208 | public:
209 | VertexTetIterator(const SimplicialComplex& obj, const VertexHandle& vh);
210 | void advance();
211 | bool done() const;
212 | TetHandle current() const;
213 |
214 | private:
215 |
216 | const SimplicialComplex& m_obj;
217 | std::set m_tets;
218 | std::set::iterator m_titer;
219 |
220 | };
221 |
222 | class TetVertexIterator {
223 | public:
224 | TetVertexIterator(const SimplicialComplex& obj, const TetHandle& th);
225 | void advance();
226 | bool done() const;
227 | VertexHandle current() const;
228 |
229 | private:
230 | const SimplicialComplex& m_obj;
231 | std::set m_verts;
232 | std::set::iterator m_viter;
233 |
234 | };
235 |
236 |
237 | class EdgeTetIterator {
238 | public:
239 | EdgeTetIterator (const SimplicialComplex& obj, const EdgeHandle& eh);
240 | void advance();
241 | bool done() const;
242 | TetHandle current() const;
243 |
244 | private:
245 |
246 | const SimplicialComplex& m_obj;
247 | std::set m_tets;
248 | std::set::iterator m_titer;
249 |
250 | };
251 |
252 | class TetEdgeIterator {
253 | public:
254 | TetEdgeIterator(const SimplicialComplex& obj, const TetHandle& th);
255 | void advance();
256 | bool done() const;
257 | EdgeHandle current() const;
258 |
259 | private:
260 | const SimplicialComplex& m_obj;
261 | std::set m_edges;
262 | std::set::iterator m_eiter;
263 |
264 | };
265 |
266 |
267 | }
268 |
269 | #endif
--------------------------------------------------------------------------------
/headers/SimplexProperty.h:
--------------------------------------------------------------------------------
1 | #ifndef SIMPLEXPROPERTY_H
2 | #define SIMPLEXPROPERTY_H
3 |
4 | #include "SimplicialComplex.h"
5 |
6 | namespace SimplexMesh {
7 |
8 | //Base class, so TopologicalObject can store pointers to TopObjProperties of different types in a single list.
9 | class SimplexPropertyBase {
10 |
11 | public:
12 |
13 | SimplexPropertyBase(SimplicialComplex& obj) : m_obj(obj) {}
14 | virtual ~SimplexPropertyBase() {}
15 |
16 | protected:
17 |
18 | //Only the TopologicalObject that owns this object is allowed to manipulate its size,
19 | //in order to match the number of the given simplex type. (eg. #of edge properties should equal #of edges)
20 | virtual size_t size() const = 0;
21 | virtual void resize(size_t n) = 0;
22 |
23 | //The simplex mesh this property is associated with.
24 | SimplicialComplex& m_obj;
25 |
26 | friend class SimplicialComplex;
27 | };
28 |
29 |
30 | //The templated object property that stores the data. This is a base class that should not be used, since it doesn't get registered with
31 | //a particular simplex type (edge, face, etc.), and cannot be resized.
32 | template
33 | class SimplexProperty : public SimplexPropertyBase {
34 |
35 | public:
36 | SimplexProperty(SimplicialComplex& obj, size_t n) : SimplexPropertyBase(obj), m_data(n) {}
37 |
38 | virtual ~SimplexProperty() {}
39 |
40 | void assign(const T& data_value) { for(unsigned int i = 0; i < m_data.size(); ++i) m_data[i] = data_value; }
41 |
42 | protected:
43 |
44 | size_t size() const { return m_data.size(); }
45 | void resize(size_t n) { m_data.resize(n); }
46 |
47 | std::vector m_data;
48 |
49 | };
50 |
51 | //The properties associated to simplices of different dimensions. They are instantiated with a pointer to the the TopologicalObject that
52 | //"owns" them, and registered with that object, so they can be automatically resized to match the mesh when necessary.
53 | template
54 | class VertexProperty : public SimplexProperty {
55 |
56 | public:
57 |
58 | VertexProperty(SimplicialComplex& obj) : SimplexProperty(obj,obj.numVertexSlots()) {
59 | m_obj.registerVertexProperty(this);
60 | }
61 |
62 | explicit VertexProperty(const VertexProperty& prop) : SimplexProperty(prop.m_obj,prop.m_obj->numVertexSlots()) {
63 | this->m_obj.registerVertexProperty(this);
64 | this->m_data = prop.m_data;
65 | }
66 |
67 | ~VertexProperty() {
68 | this->m_obj.removeVertexProperty(this);
69 | }
70 |
71 | VertexProperty& operator=(const VertexProperty& other) {
72 |
73 | if(this != &other) {
74 | this->m_obj.removeVertexProperty(this);
75 |
76 | this->m_obj = other.m_obj;
77 | this->m_data = other.m_data;
78 |
79 | this->m_obj.registerVertexProperty(this);
80 | }
81 |
82 | return *this;
83 | }
84 |
85 | T& operator[] (const VertexHandle& h) {
86 | assert(h.idx() >= 0 && h.idx() < (int)m_data.size());
87 | return m_data[h.idx()];
88 | }
89 |
90 | T const& operator[] (const VertexHandle& h) const {
91 | assert(h.idx() >= 0 && h.idx() < (int)m_data.size());
92 | return m_data[h.idx()];
93 | }
94 |
95 | };
96 |
97 |
98 | template
99 | class EdgeProperty : public SimplexProperty {
100 | public:
101 |
102 | EdgeProperty(SimplicialComplex& obj) : SimplexProperty(obj,obj.numEdgeSlots()) {
103 | m_obj.registerEdgeProperty(this);
104 | }
105 |
106 | explicit EdgeProperty(const EdgeProperty& prop) : SimplexProperty(prop.m_obj,prop.m_obj.numEdgeSlots()) {
107 | m_obj.registerEdgeProperty(this);
108 | m_data = prop.m_data;
109 | }
110 |
111 | ~EdgeProperty() {
112 | this->m_obj.removeEdgeProperty(this);
113 | }
114 |
115 | EdgeProperty& operator=(const EdgeProperty& other) {
116 |
117 | if(this != &other) {
118 | m_obj.removeEdgeProperty(this);
119 |
120 | this->m_obj = other.m_obj;
121 | this->m_data = other.m_data;
122 |
123 | m_obj.registerEdgeProperty(this);
124 | }
125 |
126 | return *this;
127 | }
128 |
129 |
130 | T& operator[] (const EdgeHandle& h) {
131 | assert(h.idx() >= 0 && h.idx() < (int)m_data.size());
132 | return m_data[h.idx()];
133 | }
134 |
135 | T const& operator[] (const EdgeHandle& h) const {
136 | assert(h.idx() >= 0 && h.idx() < (int)m_data.size());
137 | return m_data[h.idx()];
138 | }
139 | };
140 |
141 | template
142 | class FaceProperty : public SimplexProperty {
143 | public:
144 | FaceProperty(SimplicialComplex& obj) : SimplexProperty(obj,obj.numFaceSlots()) {
145 | m_obj.registerFaceProperty(this);
146 | }
147 |
148 | explicit FaceProperty(const FaceProperty& prop) : SimplexProperty(prop.m_obj,prop.m_obj.numFaceSlots()) {
149 | m_obj.registerFaceProperty(this);
150 | m_data = prop.m_data;
151 | }
152 |
153 | ~FaceProperty() {
154 | m_obj.removeFaceProperty(this);
155 | }
156 |
157 | FaceProperty& operator=(const FaceProperty& other) {
158 |
159 | if(this != &other) {
160 | m_obj.removeFaceProperty(this);
161 |
162 | this->m_obj = other.m_obj;
163 | this->m_data = other.m_data;
164 |
165 | m_obj.registerFaceProperty(this);
166 | }
167 |
168 | return *this;
169 | }
170 |
171 | T& operator[] (const FaceHandle& h) {
172 | assert(h.idx() >= 0 && h.idx() < (int)m_data.size());
173 | return m_data[h.idx()];
174 | }
175 |
176 | T const& operator[] (const FaceHandle& h) const {
177 | assert(h.idx() >= 0 && h.idx() < (int)m_data.size());
178 | return m_data[h.idx()];
179 | }
180 |
181 | };
182 |
183 |
184 | template
185 | class TetProperty : public SimplexProperty {
186 | public:
187 | TetProperty(SimplicialComplex& obj) : SimplexProperty(obj, obj.numTetSlots()) {
188 | m_obj.registerTetProperty(this);
189 | }
190 |
191 | explicit TetProperty(const TetProperty& prop) : SimplexProperty(prop.m_obj,prop.m_obj.numTetSlots()) {
192 | m_obj->registerTetProperty(this);
193 | m_data = prop.m_data;
194 | }
195 |
196 | ~TetProperty() {
197 | m_obj.removeTetProperty(this);
198 | }
199 |
200 | TetProperty& operator=(const TetProperty& other) {
201 |
202 | if(this != &other) {
203 | m_obj.removeTetProperty(this);
204 |
205 | this->m_obj = other.m_obj;
206 | this->m_data = other.m_data;
207 |
208 | m_obj.registerTetProperty(this);
209 | }
210 |
211 | return *this;
212 | }
213 |
214 | T& operator[] (const TetHandle& h) {
215 | assert(h.idx() >= 0 && h.idx() < (int)m_data.size());
216 | return m_data[h.idx()];
217 | }
218 |
219 | T const& operator[] (const TetHandle& h) const {
220 | assert(h.idx() >= 0 && h.idx() < (int)m_data.size());
221 | return m_data[h.idx()];
222 | }
223 |
224 | };
225 |
226 | }
227 |
228 | #endif
--------------------------------------------------------------------------------
/headers/SimplicialComplex.h:
--------------------------------------------------------------------------------
1 | #ifndef SIMPLICIALCOMPLEX_H
2 | #define SIMPLICIALCOMPLEX_H
3 |
4 | #include
5 |
6 | #include "SimplexHandles.h"
7 | #include "IncidenceMatrix.h"
8 |
9 | namespace SimplexMesh {
10 |
11 | class SimplexPropertyBase;
12 |
13 | // An object that represents a collection of vertices, edges, faces and tets
14 | // with associated connectivity information.
15 | class SimplicialComplex
16 | {
17 | public:
18 |
19 | SimplicialComplex();
20 |
21 | //Whether to perform potentially expensive safety checks (duplicates, validity) when constructing the mesh.
22 | void setSafeMode(bool safe) { m_safetyChecks = safe; }
23 |
24 | int numVerts() const;
25 | int numEdges() const;
26 | int numFaces() const;
27 | int numTets() const;
28 |
29 | //Addition: note that the resulting orientation is (in most cases) dependent on the order of parameters
30 | VertexHandle addVertex();
31 | EdgeHandle addEdge(const VertexHandle& v0, const VertexHandle& v1); //ordered from v0 to v1
32 | FaceHandle addFace(const EdgeHandle& e0, const EdgeHandle& e1, const EdgeHandle& e2); //in order of given edges
33 | TetHandle addTet(const FaceHandle& f0, const FaceHandle& f1, //choose in/out orientation based on face0, possibly flipped
34 | const FaceHandle& f2, const FaceHandle& f3,
35 | bool flip_face0 = false);
36 |
37 | //auxiliary addition functions for convenience. These will necessarily be slower.
38 | FaceHandle addFace(const VertexHandle& v0, const VertexHandle& v1, const VertexHandle& v2);
39 | TetHandle addTet(const VertexHandle& v0, const VertexHandle& v1, const VertexHandle& v2, const VertexHandle& v3);
40 |
41 | //deletion: recurse=true will recursively delete its composing sub-simplices if they are not used in any other simplices
42 | bool deleteVertex(const VertexHandle& vertex);
43 | bool deleteEdge(const EdgeHandle& edge, bool recurse);
44 | bool deleteFace(const FaceHandle& face, bool recurse);
45 | bool deleteTet(const TetHandle& tet, bool recurse);
46 |
47 | //Existence: check if simplices still exist
48 | bool vertexExists(const VertexHandle& vertex) const;
49 | bool edgeExists(const EdgeHandle& edge) const;
50 | bool faceExists(const FaceHandle& face) const;
51 | bool tetExists(const TetHandle& tet) const;
52 |
53 | //Exploit fixed ordering to provide fast/easy access to sub-elements of a simplex
54 | VertexHandle getVertex(const EdgeHandle& eh, int index) const;
55 | EdgeHandle getEdge(const FaceHandle& fh, int index) const;
56 | FaceHandle getFace(const TetHandle& th, int index) const; //Is there an important/inherent ordering here? should we unique-ify by sorting?
57 |
58 | //Get functions - grab a simplex by its constitutive simplices - slower!
59 | EdgeHandle getEdge(const VertexHandle& v0, const VertexHandle& v1) const;
60 | FaceHandle getFace(const EdgeHandle& e0, const EdgeHandle& e1, const EdgeHandle& e2) const;
61 | TetHandle getTet(const FaceHandle& f0, const FaceHandle& f1, const FaceHandle& f2, const FaceHandle& f3) const;
62 |
63 | //determine relative orientation of simplices (+1 or -1)
64 | int getRelativeOrientation(const TetHandle& th, const FaceHandle& fh) const;
65 | int getRelativeOrientation(const FaceHandle& fh, const EdgeHandle& eh) const;
66 | int getRelativeOrientation(const EdgeHandle& eh, const VertexHandle& vh) const;
67 |
68 | //incidence counts for simplices of neighbouring dimensions
69 | int vertexIncidentEdgeCount(const VertexHandle& v) const { return m_VE.getNumEntriesInRow(v.idx()); }
70 | int edgeIncidentFaceCount(const EdgeHandle& e) const { return m_EF.getNumEntriesInRow(e.idx()); }
71 | int faceIncidentTetCount(const FaceHandle& f) const { return m_FT.getNumEntriesInRow(f.idx()); }
72 |
73 | //manifoldness tests - complicated...
74 | bool isManifold(const VertexHandle& v) const;
75 | bool isManifold(const EdgeHandle& e) const;
76 | bool isManifold(const FaceHandle& f) const;
77 |
78 | //boundary tests
79 | bool isOnBoundary(const VertexHandle& v) const;
80 | bool isOnBoundary(const EdgeHandle& e) const;
81 | bool isOnBoundary(const FaceHandle& f) const;
82 |
83 | //incidence tests
84 | bool isIncident(const VertexHandle& vh, const EdgeHandle& eh) const;
85 | bool isIncident(const EdgeHandle& eh, const FaceHandle& fh) const;
86 | bool isIncident(const FaceHandle& fh, const TetHandle& th) const;
87 |
88 | //Pairwise relationships / traversal
89 | //----------------------------------
90 | //Edge/Vert
91 | VertexHandle fromVertex(const EdgeHandle& eh) const;
92 | VertexHandle toVertex(const EdgeHandle& eh) const;
93 |
94 | //Face/Edge - assumes consistent orientation and 2D
95 | FaceHandle frontFace(const EdgeHandle& fh) const;
96 | FaceHandle backFace(const EdgeHandle& fh) const;
97 |
98 | //Tet/Face - assumes consistent orientation
99 | TetHandle frontTet(const FaceHandle& fh) const;
100 | TetHandle backTet(const FaceHandle& fh) const;
101 |
102 | //Simple global traversal functions (terser than iterators, safer/slower when editing meshes)
103 | //------------------------------------
104 | //Vertices
105 | VertexHandle nextVertex(const VertexHandle& curVertex) const;
106 | VertexHandle prevVertex(const VertexHandle& curVertex) const;
107 |
108 | //Edges
109 | EdgeHandle nextEdge(const EdgeHandle& curEdge) const;
110 | EdgeHandle prevEdge(const EdgeHandle& curEdge) const;
111 |
112 | //Faces
113 | FaceHandle nextFace(const FaceHandle& curFace) const;
114 | FaceHandle prevFace(const FaceHandle& curFace) const;
115 |
116 | //Tets
117 | TetHandle nextTet(const TetHandle& curTet) const;
118 | TetHandle prevTet(const TetHandle& curTet) const;
119 |
120 | //Simple local traversal functions (stateless, terser than iterators, safer & slower. Useful e.g. when editing meshes)
121 | //---------------------------------
122 | //Vertex traversal
123 | VertexHandle nextVertex(const EdgeHandle&edge, const VertexHandle& curVertex) const;
124 | VertexHandle prevVertex(const EdgeHandle&edge, const VertexHandle& curVertex) const;
125 | VertexHandle nextVertex(const FaceHandle&face, const VertexHandle& curVertex) const;
126 | VertexHandle prevVertex(const FaceHandle&face, const VertexHandle& curVertex) const;
127 |
128 | //Edge traversal
129 | EdgeHandle nextEdge(const VertexHandle& vert, const EdgeHandle& curEdge) const;
130 | EdgeHandle prevEdge(const VertexHandle& vert, const EdgeHandle& curEdge) const;
131 | EdgeHandle nextEdge(const FaceHandle& face, const EdgeHandle& curEdge) const;
132 | EdgeHandle prevEdge(const FaceHandle& face, const EdgeHandle& curEdge) const;
133 |
134 | //Face traversal
135 | FaceHandle nextFace(const TetHandle& tet, const FaceHandle& curFace) const;
136 | FaceHandle prevFace(const TetHandle& tet, const FaceHandle& curFace) const;
137 | FaceHandle nextFace(const EdgeHandle& edge, const FaceHandle& curFace) const;
138 | FaceHandle prevFace(const EdgeHandle& edge, const FaceHandle& curFace) const;
139 |
140 | //Tet traversal
141 | TetHandle nextTet(const FaceHandle& face, const TetHandle& curTet) const;
142 | TetHandle prevTet(const FaceHandle& face, const TetHandle& curTet) const;
143 |
144 | //Common connectivity editing operations
145 | //---------------------------------
146 |
147 | VertexHandle collapseEdge(const EdgeHandle& eh, const VertexHandle& vertToRemove);
148 |
149 | //Split an edge and insert a new vertex in between, subdividing all the faces sharing the edge.
150 | //Should be non-manifold friendly. Orientation is maintained.
151 | VertexHandle splitEdge(const EdgeHandle& h, std::vector& newFaces);
152 |
153 | //Takes an edge with two adjacent faces comprising a quad, and replaces the edge with the other diagonal of the quad.
154 | //Not defined in the non-manifold edge case. Orientation maintained if original face orientations matched.
155 | EdgeHandle flipEdge(const EdgeHandle& h);
156 |
157 | //--------------------------------
158 | private:
159 |
160 |
161 |
162 | //Friendship relations
163 | //////////////////////////////////////////////////////////////////////////
164 |
165 | //Basic iterators
166 | friend class VertexIterator; friend class EdgeIterator;
167 | friend class FaceIterator; friend class TetIterator;
168 |
169 | //Neighbour iterators
170 | friend class VertexEdgeIterator; friend class EdgeVertexIterator; friend class VertexVertexIterator;
171 | friend class EdgeFaceIterator; friend class FaceEdgeIterator;
172 | friend class FaceTetIterator; friend class TetFaceIterator;
173 |
174 | //allow properties to access object internals (for registering/unregistering themselves)
175 | template friend class VertexProperty;
176 | template friend class EdgeProperty;
177 | template friend class FaceProperty;
178 | template friend class TetProperty;
179 |
180 | //Internal functions
181 | //////////////////////////////////////////////////////////////////////////
182 |
183 | EdgeHandle getSharedEdge(const FaceHandle& f0, const FaceHandle& f1) const;
184 | FaceHandle getSharedFace(const TetHandle &t0, const TetHandle& t1) const;
185 |
186 | //Functions for registering/unregistering properties associated to simplex elements
187 | void registerVertexProperty(SimplexPropertyBase* prop);
188 | void removeVertexProperty(SimplexPropertyBase* prop);
189 |
190 | void registerEdgeProperty(SimplexPropertyBase* prop);
191 | void removeEdgeProperty(SimplexPropertyBase* prop);
192 |
193 | void registerFaceProperty(SimplexPropertyBase* prop);
194 | void removeFaceProperty(SimplexPropertyBase* prop);
195 |
196 | void registerTetProperty(SimplexPropertyBase* prop);
197 | void removeTetProperty(SimplexPropertyBase* prop);
198 |
199 | //The number of spaces currently allocated for each simplex type. (Note this is different
200 | //from the number of active simplices of each type.)
201 | unsigned int numVertexSlots() const {return m_V.size();}
202 | unsigned int numEdgeSlots() const {return m_EV.getNumRows();}
203 | unsigned int numFaceSlots() const {return m_FE.getNumRows();}
204 | unsigned int numTetSlots() const {return m_TF.getNumRows();}
205 |
206 | //Core Data
207 | //////////////////////////////////////////////////////////////////////////
208 |
209 | //Simplex counts
210 | int m_nVerts, m_nEdges, m_nFaces, m_nTets;
211 |
212 | //Fundamental mesh data (incidence matrix format)
213 | IncidenceMatrix m_TF; ///< tet-to-face relations
214 | IncidenceMatrix m_FE; ///< face-to-edge relations
215 | IncidenceMatrix m_EV; ///< edge-to-vert relations
216 | std::vector m_V; ///< vertex existence, to support isolated vertices
217 |
218 | //Transposes, needed for efficient deletion/traversal/etc
219 | IncidenceMatrix m_FT; ///< face-to-tet relations
220 | IncidenceMatrix m_EF; ///< edge-to-face relations
221 | IncidenceMatrix m_VE; ///< vert-to-edge relations
222 |
223 | //Pools of empty rows/columns in the above matrices, to efficiently add
224 | //data in previously deleted slots.
225 | std::vector m_deadVerts, m_deadEdges, m_deadFaces, m_deadTets;
226 |
227 | //Lists of simplex properties. These are just pointers so that memory can be managed by the SimplexMesh for adding/deleting.
228 | //But the data "lives" wherever it has been created.
229 | std::vector m_vertProperties;
230 | std::vector m_edgeProperties;
231 | std::vector m_faceProperties;
232 | std::vector m_tetProperties;
233 |
234 | //Option flags
235 | bool m_safetyChecks;
236 |
237 | };
238 |
239 | } // namespace SimplexMesh
240 |
241 | #include "SimplexProperty.h"
242 | #include "SimplexIterators.h"
243 |
244 | #endif // SIMPLICIALCOMPLEX_H
245 |
--------------------------------------------------------------------------------
/src/IncidenceMatrix.cpp:
--------------------------------------------------------------------------------
1 | #include "IncidenceMatrix.h"
2 |
3 | namespace SimplexMesh {
4 |
5 | int signum(int val) {
6 | return (val >= 0 ? 1 : -1);
7 |
8 | }
9 |
10 | IncidenceMatrix::IncidenceMatrix() :
11 | n_rows(0), n_cols(0), m_indices(0)
12 | {
13 | }
14 |
15 | IncidenceMatrix::IncidenceMatrix(unsigned int rows, unsigned int cols) :
16 | n_rows(rows), n_cols(cols),
17 | m_indices(rows, std::vector())
18 | {
19 | }
20 |
21 | unsigned int IncidenceMatrix::getNumEntriesInRow(unsigned int row) const {
22 | assert(row < n_rows);
23 | return m_indices[row].size();
24 | }
25 |
26 | int IncidenceMatrix::getValueByIndex(unsigned int i, unsigned int index_in_row) const {
27 | assert(i < n_rows);
28 | assert(index_in_row < m_indices[i].size());
29 |
30 | return signum(m_indices[i][index_in_row]);
31 | }
32 |
33 | unsigned int IncidenceMatrix::getColByIndex(unsigned int i, unsigned int index_in_row) const {
34 | assert(i < n_rows);
35 | assert(index_in_row < m_indices[i].size());
36 |
37 | return abs(m_indices[i][index_in_row]) - 1;
38 | }
39 |
40 | void IncidenceMatrix::cycleRow(unsigned int i) {
41 | int t = m_indices[i][0];
42 | int row_len = m_indices[i].size();
43 | for(int j = 0; j < row_len-1; ++j)
44 | m_indices[i][j] = m_indices[i][j+1];
45 | m_indices[i][row_len-1] = t;
46 | }
47 |
48 | void IncidenceMatrix::setByIndex(unsigned int i, unsigned int index_in_row, unsigned int col, int value) {
49 | assert(value == 1 || value == -1);
50 | if(index_in_row >= m_indices[i].size()) m_indices[i].resize(index_in_row+1);
51 |
52 | m_indices[i][index_in_row] = (col+1)*value;
53 | }
54 |
55 | void IncidenceMatrix::set(unsigned int i, unsigned int j, int new_val) {
56 | assert(i < n_rows && j < n_cols);
57 | if(new_val == 0) {
58 | remove(i,j);
59 | return;
60 | }
61 |
62 | assert(new_val == 1 || new_val == -1);
63 |
64 | int colShift = j+1;
65 | bool found = false;
66 | for(unsigned int cur = 0; cur < m_indices[i].size(); ++cur) {
67 | if(abs(m_indices[i][cur]) == (int)colShift ) {
68 | m_indices[i][cur] = signum(new_val)*colShift;
69 | found = true;
70 | break;
71 | }
72 | }
73 | if(!found)
74 | m_indices[i].push_back(signum(new_val)*colShift);
75 |
76 | }
77 |
78 | int IncidenceMatrix::get(unsigned int i, unsigned int j) const {
79 | assert(i < n_rows && j < n_cols);
80 |
81 | int colShift = j+1;
82 | for(unsigned int k=0; k 0?'+':'-', abs(m_indices[row][i])-1);
135 | printf("\n");
136 | }
137 | }
138 |
139 | void IncidenceMatrix::zeroAll()
140 | {
141 | for(unsigned int i = 0; i < getNumRows(); ++i)
142 | zeroRow(i);
143 | }
144 |
145 | }
--------------------------------------------------------------------------------
/src/SimplexIterators.cpp:
--------------------------------------------------------------------------------
1 | #include "SimplexIterators.h"
2 |
3 | namespace SimplexMesh {
4 |
5 | //VertexIterator
6 |
7 | VertexIterator::VertexIterator(const SimplicialComplex& obj): m_obj(obj), m_idx(-1) {
8 | advance();
9 | }
10 |
11 | void VertexIterator::advance() {
12 | do {
13 | m_idx++;
14 | } while(m_idx < (int)m_obj.numVertexSlots() && !m_obj.m_V[m_idx]);
15 | }
16 |
17 | bool VertexIterator::done() const {
18 | return m_idx >= (int)m_obj.numVertexSlots();
19 | }
20 |
21 | VertexHandle VertexIterator::current() const {
22 | return VertexHandle(m_idx);
23 | }
24 |
25 | //EdgeIterator
26 |
27 | EdgeIterator::EdgeIterator(const SimplicialComplex& obj): m_obj(obj), m_idx(-1) {
28 | advance();
29 | }
30 |
31 | void EdgeIterator::advance() {
32 | do {
33 | m_idx++;
34 | } while(m_idx < (int)m_obj.numEdgeSlots() && m_obj.m_EV.getNumEntriesInRow(m_idx) == 0);
35 | }
36 |
37 | bool EdgeIterator::done() const {
38 | return m_idx >= (int)m_obj.numEdgeSlots();
39 | }
40 |
41 | EdgeHandle EdgeIterator::current() const {
42 | return EdgeHandle(m_idx);
43 | }
44 |
45 | //FaceIterator
46 |
47 | FaceIterator::FaceIterator(const SimplicialComplex& obj): m_obj(obj), m_idx(-1) {
48 | advance();
49 | }
50 |
51 | void FaceIterator::advance() {
52 | do {
53 | m_idx++;
54 | } while(m_idx < (int)m_obj.numFaceSlots() && m_obj.m_FE.getNumEntriesInRow(m_idx) == 0);
55 | }
56 |
57 | bool FaceIterator::done() const {
58 | return m_idx >= (int)m_obj.numFaceSlots();
59 | }
60 |
61 | FaceHandle FaceIterator::current() const {
62 | return FaceHandle(m_idx);
63 | }
64 |
65 |
66 | //TetIterator
67 |
68 | TetIterator::TetIterator(const SimplicialComplex& obj): m_obj(obj), m_idx(-1) {
69 | advance();
70 | }
71 |
72 | void TetIterator::advance() {
73 | do {
74 | m_idx++;
75 | } while(m_idx < (int)m_obj.numTetSlots() && m_obj.m_TF.getNumEntriesInRow(m_idx) == 0);
76 | }
77 |
78 | bool TetIterator::done() const {
79 | return m_idx >= (int)m_obj.numTetSlots();
80 | }
81 |
82 | TetHandle TetIterator::current() const {
83 | return TetHandle(m_idx);
84 | }
85 |
86 |
87 | //////////////////////////////////////////////////////////////////////////
88 | //Adjacency iterators
89 |
90 |
91 | //VertexEdgeIterator
92 | VertexEdgeIterator::VertexEdgeIterator(const SimplicialComplex& obj, const VertexHandle& vh): m_obj(obj), m_idx(0), m_vh(vh) {
93 | }
94 |
95 | void VertexEdgeIterator::advance() {
96 | m_idx++;
97 | }
98 |
99 | bool VertexEdgeIterator::done() const {
100 | return m_idx >= (int)m_obj.vertexIncidentEdgeCount(m_vh);
101 | }
102 |
103 | EdgeHandle VertexEdgeIterator::current() const {
104 | return m_idx >= (int)m_obj.vertexIncidentEdgeCount(m_vh) ?
105 | EdgeHandle::invalid() : EdgeHandle(m_obj.m_VE.getColByIndex(m_vh.idx(), m_idx));
106 | }
107 |
108 | //EdgeVertexIterator
109 | EdgeVertexIterator::EdgeVertexIterator(const SimplicialComplex& obj, const EdgeHandle& eh, bool ordered): m_obj(obj), m_idx(0), m_eh(eh), m_ordered(ordered) {
110 | }
111 |
112 | void EdgeVertexIterator::advance() {
113 | m_idx++;
114 | }
115 |
116 | bool EdgeVertexIterator::done() const {
117 | return m_idx >= 2;
118 | }
119 |
120 | VertexHandle EdgeVertexIterator::current() const {
121 | if(m_ordered) {
122 | if(m_idx == 0)
123 | return m_obj.fromVertex(m_eh);
124 | else if(m_idx == 1)
125 | return m_obj.toVertex(m_eh);
126 | else return VertexHandle::invalid();
127 | }
128 | else {
129 | return m_idx >= 2 ?
130 | VertexHandle::invalid() : VertexHandle(m_obj.m_EV.getColByIndex(m_eh.idx(), m_idx));
131 | }
132 | }
133 |
134 |
135 | //VertexVertexIterator
136 | VertexVertexIterator::VertexVertexIterator(const SimplicialComplex& obj, const VertexHandle& vh): m_obj(obj), m_idx(0), m_vh(vh) {
137 | }
138 |
139 | void VertexVertexIterator::advance() {
140 | m_idx++;
141 | }
142 |
143 | bool VertexVertexIterator::done() const {
144 | return m_idx >= (int)m_obj.vertexIncidentEdgeCount(m_vh);
145 | }
146 |
147 | VertexHandle VertexVertexIterator::current() const {
148 | if(m_idx >= (int)m_obj.vertexIncidentEdgeCount(m_vh))
149 | return VertexHandle::invalid();
150 |
151 | unsigned int edgeID = m_obj.m_VE.getColByIndex(m_vh.idx(), m_idx);
152 | unsigned int vertID = m_obj.m_EV.getColByIndex(edgeID, 0);
153 | if(vertID == m_vh.idx())
154 | vertID = m_obj.m_EV.getColByIndex(edgeID, 1);
155 | return VertexHandle(vertID);
156 | }
157 |
158 | //EdgeFaceIterator
159 | EdgeFaceIterator::EdgeFaceIterator(const SimplicialComplex& obj, const EdgeHandle& eh): m_obj(obj), m_idx(0), m_eh(eh) {
160 | }
161 |
162 | void EdgeFaceIterator::advance() {
163 | m_idx++;
164 | }
165 |
166 | bool EdgeFaceIterator::done() const {
167 | return m_idx >= (int)m_obj.edgeIncidentFaceCount(m_eh);
168 | }
169 |
170 | FaceHandle EdgeFaceIterator::current() const {
171 | return m_idx >= (int)m_obj.edgeIncidentFaceCount(m_eh) ?
172 | FaceHandle::invalid() : FaceHandle(m_obj.m_EF.getColByIndex(m_eh.idx(), m_idx));
173 | }
174 |
175 | //FaceEdgeIterator
176 | FaceEdgeIterator::FaceEdgeIterator(const SimplicialComplex& obj, const FaceHandle& fh, bool ordered): m_obj(obj), m_idx(0), m_fh(fh), m_ordered(ordered) {
177 |
178 | if(m_ordered) { //start at an arbitrary edge
179 | m_cur = EdgeHandle(m_obj.m_FE.getColByIndex(m_fh.idx(), m_idx));
180 | }
181 |
182 | }
183 |
184 | void FaceEdgeIterator::advance() {
185 | m_idx++;
186 | if(m_ordered)
187 | m_cur = m_obj.nextEdge(m_fh, m_cur);
188 | }
189 |
190 | bool FaceEdgeIterator::done() const {
191 | return m_idx >= 3;
192 | }
193 |
194 | EdgeHandle FaceEdgeIterator::current() const {
195 | if(m_ordered) {
196 | return m_idx >= 3? EdgeHandle::invalid() : m_cur;
197 | }
198 | else {
199 | return m_idx >= 3 ? EdgeHandle::invalid() : EdgeHandle(m_obj.m_FE.getColByIndex(m_fh.idx(), m_idx));
200 | }
201 | }
202 |
203 |
204 | //FaceTetIterator
205 | FaceTetIterator::FaceTetIterator(const SimplicialComplex& obj, const FaceHandle& fh): m_obj(obj), m_idx(0), m_fh(fh) {
206 | }
207 |
208 | void FaceTetIterator::advance() {
209 | m_idx++;
210 | }
211 |
212 | bool FaceTetIterator::done() const {
213 | return m_idx >= (int)m_obj.m_FT.getNumEntriesInRow(m_fh.idx());
214 | }
215 |
216 | TetHandle FaceTetIterator::current() const {
217 | return m_idx >= (int)m_obj.m_FT.getNumEntriesInRow(m_fh.idx()) ?
218 | TetHandle::invalid():
219 | TetHandle(m_obj.m_FT.getColByIndex(m_fh.idx(), m_idx));
220 | }
221 |
222 | //TetFaceIterator
223 | TetFaceIterator::TetFaceIterator(const SimplicialComplex& obj, const TetHandle& th): m_obj(obj), m_idx(0), m_th(th) {
224 | }
225 |
226 | void TetFaceIterator::advance() {
227 | m_idx++;
228 | }
229 |
230 | bool TetFaceIterator::done() const {
231 | return m_idx >= 4;
232 | }
233 |
234 | FaceHandle TetFaceIterator::current() const {
235 | return m_idx >= 4 ?
236 | FaceHandle::invalid():
237 | FaceHandle(m_obj.m_TF.getColByIndex(m_th.idx(), m_idx));
238 | }
239 |
240 | //VertexFaceIterator
241 | VertexFaceIterator::VertexFaceIterator(const SimplicialComplex& obj, const VertexHandle& vh) : m_obj(obj) {
242 |
243 | //build the set of (unique) faces
244 | for(VertexEdgeIterator veit(m_obj, vh); !veit.done(); veit.advance())
245 | for(EdgeFaceIterator efit(m_obj, veit.current()); !efit.done(); efit.advance())
246 | m_faces.insert(efit.current());
247 |
248 | //...and set up an iterator
249 | m_fiter = m_faces.begin();
250 | }
251 |
252 |
253 | void VertexFaceIterator::advance() {
254 | if(!done())
255 | ++m_fiter;
256 | }
257 |
258 | bool VertexFaceIterator::done() const {
259 | return m_fiter == m_faces.end();
260 | }
261 |
262 | FaceHandle VertexFaceIterator::current() const {
263 | if(!done())
264 | return *m_fiter;
265 | else
266 | return FaceHandle::invalid();
267 | }
268 |
269 |
270 | //FaceVertexIterator
271 | FaceVertexIterator::FaceVertexIterator(const SimplicialComplex& obj, const FaceHandle& fh, bool ordered) :
272 | m_obj(obj), m_feit(obj, fh, ordered), m_fh(fh)
273 | {
274 |
275 | }
276 |
277 | void FaceVertexIterator::advance() {
278 | m_feit.advance();
279 | }
280 |
281 | bool FaceVertexIterator::done() const {
282 | return m_feit.done();
283 | }
284 |
285 | VertexHandle FaceVertexIterator::current() const {
286 | EdgeHandle curEdge = m_feit.current();
287 | int direction = m_obj.getRelativeOrientation(m_fh, curEdge);
288 | return direction > 0? m_obj.fromVertex(curEdge) : m_obj.toVertex(curEdge);
289 | }
290 |
291 | //VertexTetIterator
292 | VertexTetIterator::VertexTetIterator(const SimplicialComplex& obj, const VertexHandle& vh) : m_obj(obj) {
293 |
294 | //build the set of (unique) tets
295 | for(VertexEdgeIterator veit(m_obj, vh); !veit.done(); veit.advance())
296 | for(EdgeFaceIterator efit(m_obj, veit.current()); !efit.done(); efit.advance())
297 | for(FaceTetIterator ftit(m_obj, efit.current()); !ftit.done(); ftit.advance())
298 | m_tets.insert(ftit.current());
299 |
300 | //...and set up an iterator
301 | m_titer = m_tets.begin();
302 | }
303 |
304 |
305 | void VertexTetIterator::advance() {
306 | if(!done())
307 | ++m_titer;
308 | }
309 |
310 | bool VertexTetIterator::done() const {
311 | return m_titer == m_tets.end();
312 | }
313 |
314 | TetHandle VertexTetIterator::current() const {
315 | if(!done())
316 | return *m_titer;
317 | else
318 | return TetHandle::invalid();
319 | }
320 |
321 |
322 | //TetVertexIterator
323 | TetVertexIterator::TetVertexIterator(const SimplicialComplex& obj, const TetHandle& th) :
324 | m_obj(obj)
325 | {
326 | //build the set of (unique) vertices
327 | for(TetFaceIterator tfit(m_obj, th); !tfit.done(); tfit.advance())
328 | for(FaceEdgeIterator feit(m_obj, tfit.current(), false); !feit.done(); feit.advance())
329 | for(EdgeVertexIterator evit(m_obj, feit.current(), false); !evit.done(); evit.advance())
330 | m_verts.insert(evit.current());
331 |
332 | //...and set up an iterator
333 | m_viter = m_verts.begin();
334 |
335 | }
336 |
337 | void TetVertexIterator::advance() {
338 | if(!done())
339 | ++m_viter;
340 | }
341 |
342 | bool TetVertexIterator::done() const {
343 | return m_viter == m_verts.end();
344 | }
345 |
346 | VertexHandle TetVertexIterator::current() const {
347 | if(!done())
348 | return *m_viter;
349 | else
350 | return VertexHandle::invalid();
351 | }
352 |
353 |
354 | //EdgeTetIterator
355 | EdgeTetIterator::EdgeTetIterator(const SimplicialComplex& obj, const EdgeHandle& eh) : m_obj(obj) {
356 |
357 | //build the set of (unique) tets
358 | for(EdgeFaceIterator efit(m_obj, eh); !efit.done(); efit.advance())
359 | for(FaceTetIterator ftit(m_obj, efit.current()); !ftit.done(); ftit.advance())
360 | m_tets.insert(ftit.current());
361 |
362 | //...and set up an iterator
363 | m_titer = m_tets.begin();
364 | }
365 |
366 |
367 | void EdgeTetIterator::advance() {
368 | if(!done())
369 | ++m_titer;
370 | }
371 |
372 | bool EdgeTetIterator::done() const {
373 | return m_titer == m_tets.end();
374 | }
375 |
376 | TetHandle EdgeTetIterator::current() const {
377 | if(!done())
378 | return *m_titer;
379 | else
380 | return TetHandle::invalid();
381 | }
382 |
383 |
384 | //TetEdgeIterator
385 | TetEdgeIterator::TetEdgeIterator(const SimplicialComplex& obj, const TetHandle& th) :
386 | m_obj(obj)
387 | {
388 | //build the set of (unique) vertices
389 | for(TetFaceIterator tfit(m_obj, th); !tfit.done(); tfit.advance())
390 | for(FaceEdgeIterator feit(m_obj, tfit.current(), false); !feit.done(); feit.advance())
391 | m_edges.insert(feit.current());
392 |
393 | //...and set up an iterator
394 | m_eiter = m_edges.begin();
395 |
396 | }
397 |
398 | void TetEdgeIterator::advance() {
399 | if(!done())
400 | ++m_eiter;
401 | }
402 |
403 | bool TetEdgeIterator::done() const {
404 | return m_eiter == m_edges.end();
405 | }
406 |
407 | EdgeHandle TetEdgeIterator::current() const {
408 | if(!done())
409 | return *m_eiter;
410 | else
411 | return EdgeHandle::invalid();
412 | }
413 |
414 | }
--------------------------------------------------------------------------------
/src/SimplicialComplex.cpp:
--------------------------------------------------------------------------------
1 | #include "SimplicialComplex.h"
2 | #include "SimplexProperty.h"
3 | #include "SimplexIterators.h"
4 |
5 | #include
6 | #include
7 | #include
8 | #include