TTK
Loading...
Searching...
No Matches
BarycentricSubdivision.h
Go to the documentation of this file.
1
19
20#pragma once
21
22#include <array>
23#include <type_traits>
24
25// base code includes
26#include <Geometry.h>
27#include <Triangulation.h>
28
29namespace ttk {
30
31 class BarycentricSubdivision : virtual public Debug {
32
33 public:
35 this->setDebugMsgPrefix("BarycentricSubdivision");
36 }
37
38 inline void
40 if(triangulation == nullptr) {
41 return;
42 }
43 triangulation->preconditionVertexNeighbors();
44 triangulation->preconditionEdges();
45 triangulation->preconditionTriangles();
46 triangulation->preconditionTriangleEdges();
47 nVertices_ = triangulation->getNumberOfVertices();
48 nEdges_ = triangulation->getNumberOfEdges();
49 nTriangles_ = triangulation->getNumberOfTriangles();
50 }
51
55 return nVertices_ + nEdges_ + nTriangles_;
56 }
57
61 return nTriangles_ * 6;
62 }
63
64 template <typename triangulationType>
65 int execute(const triangulationType &inputTriangl,
66 ExplicitTriangulation &outputTriangl);
67
79 template <typename T, typename triangulationType>
81 const T *data, T *output, const triangulationType &inputTriangl) const {
82 static_assert(
83 std::is_floating_point<T>::value, "Floating point type required.");
84 const auto nOutVerts = this->getNumberOfVertices();
85 if(nOutVerts < 0 || nOutVerts != nVertices_ + nEdges_ + nTriangles_) {
86 return 1;
87 }
88
89 // copy data on parent vertices
90 std::copy(data, data + nVertices_, output);
91
92 // interpolate on edges
93 for(SimplexId i = 0; i < nEdges_; ++i) {
94 SimplexId a{}, b{};
95 inputTriangl.getEdgeVertex(i, 0, a);
96 inputTriangl.getEdgeVertex(i, 0, b);
97 output[nVertices_ + i] = (data[a] + data[b]) / T{2.0};
98 }
99
100 // interpolate on triangle barycenters
101 for(SimplexId i = 0; i < nTriangles_; ++i) {
102 SimplexId a{}, b{}, c{};
103 inputTriangl.getTriangleVertex(i, 0, a);
104 inputTriangl.getTriangleVertex(i, 1, b);
105 inputTriangl.getTriangleVertex(i, 2, c);
106 output[nVertices_ + nEdges_ + i]
107 = (data[a] + data[b] + data[c]) / T{3.0};
108 }
109 return 0;
110 }
111
122 template <typename T>
123 int interpolateDiscreteScalarField(const T *data, T *output) const {
124
125 static_assert(std::is_integral<T>::value, "Integral type required.");
126 const auto nOutVerts = this->getNumberOfVertices();
127 if(nOutVerts < 0 || nOutVerts < nVertices_) {
128 return 1;
129 }
130 std::fill(output, output + nOutVerts, T{0});
131 std::copy(data, data + nVertices_, output);
132 return 0;
133 }
134
145 template <typename T>
146 int interpolateCellDataField(const T *data, T *output) const {
147
148 const size_t newTrianglesPerParent{6};
149 const size_t nOutTriangles = this->getNumberOfTriangles();
150 if(nOutTriangles != newTrianglesPerParent * nTriangles_) {
151 return 1;
152 }
153 for(SimplexId i = 0; i < nTriangles_; ++i) {
154 output[i * newTrianglesPerParent + 0] = data[i];
155 output[i * newTrianglesPerParent + 1] = data[i];
156 output[i * newTrianglesPerParent + 2] = data[i];
157 output[i * newTrianglesPerParent + 3] = data[i];
158 output[i * newTrianglesPerParent + 4] = data[i];
159 output[i * newTrianglesPerParent + 5] = data[i];
160 }
161 return 0;
162 }
163
164 private:
165 template <typename triangulationType>
166 int subdiviseTriangulation(const triangulationType &inputTriangl);
167
168 int buildOutputTriangulation(ExplicitTriangulation &outputTriangl);
169
170 // input triangulation properties
171 SimplexId nVertices_{};
172 SimplexId nEdges_{};
173 SimplexId nTriangles_{};
174
175 protected:
176 // output 3D coordinates of generated points: old points first, then edge
177 // middles, then triangle barycenters
178 std::vector<float> points_;
179 // output triangles
180 std::vector<LongSimplexId> cells_connectivity_;
181 std::vector<LongSimplexId> cells_offsets_;
182 // generated point cell id
183 std::vector<SimplexId> pointId_;
184 // generated points dimension: 0 vertex of parent triangulation, 1 edge
185 // middle, 2 triangle barycenter
186 std::vector<SimplexId> pointDim_;
187 };
188} // namespace ttk
189
190template <typename triangulationType>
191int ttk::BarycentricSubdivision::subdiviseTriangulation(
192 const triangulationType &inputTriangl) {
193
194 const SimplexId newPoints{nVertices_ + nEdges_ + nTriangles_};
195 const size_t dataPerPoint{3};
196 points_.clear();
197 points_.resize(newPoints * dataPerPoint);
198
199 const size_t dataPerCell{3};
200 const size_t newTrianglesPerParent{6};
201 cells_connectivity_.clear();
202 cells_offsets_.clear();
203 cells_connectivity_.resize(nTriangles_ * newTrianglesPerParent * dataPerCell);
204 cells_offsets_.resize(nTriangles_ * newTrianglesPerParent + 1);
205
206 pointId_.clear();
207 pointId_.resize(newPoints);
208
209 pointDim_.clear();
210 pointDim_.resize(newPoints);
211
212 // set input point coordinates and ids
213 for(SimplexId i = 0; i < nVertices_; ++i) {
214 inputTriangl.getVertexPoint(
215 i, points_[3 * i + 0], points_[3 * i + 1], points_[3 * i + 2]);
216 pointId_[i] = i;
217 }
218
219 // reserve memory for new points
220 points_.reserve(newPoints * dataPerPoint);
221
222 // generate edge middles
223 for(SimplexId i = 0; i < nEdges_; ++i) {
224 // edge vertices
225 SimplexId a{}, b{};
226 inputTriangl.getEdgeVertex(i, 0, a);
227 inputTriangl.getEdgeVertex(i, 1, b);
228
229 std::array<float, 3> pa{}, pb{}, mid{};
230 inputTriangl.getVertexPoint(a, pa[0], pa[1], pa[2]);
231 inputTriangl.getVertexPoint(b, pb[0], pb[1], pb[2]);
232
233 mid[0] = (pa[0] + pb[0]) / 2.0F;
234 mid[1] = (pa[1] + pb[1]) / 2.0F;
235 mid[2] = (pa[2] + pb[2]) / 2.0F;
236
237 const size_t offset = dataPerPoint * (nVertices_ + i);
238 points_[offset + 0] = mid[0];
239 points_[offset + 1] = mid[1];
240 points_[offset + 2] = mid[2];
241 pointId_[nVertices_ + i] = i;
242 pointDim_[nVertices_ + i] = 1;
243 }
244
245 // generate triangle barycenters
246 for(SimplexId i = 0; i < nTriangles_; ++i) {
247 // triangle vertices
248 SimplexId a{}, b{}, c{};
249 inputTriangl.getTriangleVertex(i, 0, a);
250 inputTriangl.getTriangleVertex(i, 1, b);
251 inputTriangl.getTriangleVertex(i, 2, c);
252
253 std::array<float, 3> pa{}, pb{}, pc{}, bary{};
254 inputTriangl.getVertexPoint(a, pa[0], pa[1], pa[2]);
255 inputTriangl.getVertexPoint(b, pb[0], pb[1], pb[2]);
256 inputTriangl.getVertexPoint(c, pc[0], pc[1], pc[2]);
257
258 bary[0] = (pa[0] + pb[0] + pc[0]) / 3.0F;
259 bary[1] = (pa[1] + pb[1] + pc[1]) / 3.0F;
260 bary[2] = (pa[2] + pb[2] + pc[2]) / 3.0F;
261
262 const size_t offset = dataPerPoint * (nVertices_ + nEdges_ + i);
263 points_[offset + 0] = bary[0];
264 points_[offset + 1] = bary[1];
265 points_[offset + 2] = bary[2];
266 pointId_[nVertices_ + nEdges_ + i] = i;
267 pointDim_[nVertices_ + nEdges_ + i] = 2;
268 }
269
270 LongSimplexId off_id = 0, co_id = 0;
271 // subdivise every triangle
272 for(SimplexId i = 0; i < nTriangles_; ++i) {
273 // id of triangle barycenter
274 SimplexId bary = nVertices_ + nEdges_ + i;
275
276 for(SimplexId j = 0; j < inputTriangl.getTriangleEdgeNumber(i); ++j) {
277 // edge id
278 SimplexId e{};
279 inputTriangl.getTriangleEdge(i, j, e);
280
281 // id of middle of edge e
282 SimplexId em = nVertices_ + e;
283
284 // edge vertices
285 SimplexId a{}, b{};
286 inputTriangl.getEdgeVertex(e, 0, a);
287 inputTriangl.getEdgeVertex(e, 1, b);
288
289 // Ad triangle a - em - bary
290 cells_offsets_[off_id] = co_id;
291 off_id++;
292 cells_connectivity_[co_id + 0] = a;
293 cells_connectivity_[co_id + 1] = em;
294 cells_connectivity_[co_id + 2] = bary;
295 co_id += 3;
296
297 // Ad triangle b - em - bary
298 cells_offsets_[off_id] = co_id;
299 off_id++;
300 cells_connectivity_[co_id + 0] = b;
301 cells_connectivity_[co_id + 1] = em;
302 cells_connectivity_[co_id + 2] = bary;
303 co_id += 3;
304 }
305 }
306 // Last offset
307 cells_offsets_[off_id] = co_id;
308
309 return 0;
310}
311
312template <typename triangulationType>
314 const triangulationType &inputTriangl,
315 ttk::ExplicitTriangulation &outputTriangl) {
316
317 // not implemented for dimension >= 3
318 if(inputTriangl.getDimensionality() >= 3) {
319 this->printErr("Not yet implemented for dimension 3 and above");
320 return 1;
321 }
322
323 Timer tm;
324
325 const SimplexId vertexNumber = inputTriangl.getNumberOfVertices();
326 subdiviseTriangulation(inputTriangl);
327 buildOutputTriangulation(outputTriangl);
328
329 this->printMsg(
330 "Data-set (" + std::to_string(vertexNumber) + " points) processed", 1.0,
331 tm.getElapsedTime(), this->threadNumber_);
332
333 return 0;
334}
AbstractTriangulation is an interface class that defines an interface for efficient traversal methods...
virtual SimplexId getNumberOfVertices() const
virtual SimplexId getNumberOfTriangles() const
virtual SimplexId getNumberOfEdges() const
Subdivise a triangulation according to triangle barycenter.
int interpolateContinuousScalarField(const T *data, T *output, const triangulationType &inputTriangl) const
Interpolate floating-point point data on subdivised triangulation.
SimplexId getNumberOfVertices() const
Return the number of vertices in the output triangulation.
std::vector< LongSimplexId > cells_connectivity_
void preconditionTriangulation(AbstractTriangulation *const triangulation)
int execute(const triangulationType &inputTriangl, ExplicitTriangulation &outputTriangl)
int interpolateCellDataField(const T *data, T *output) const
Interpolate cell data on subdivised triangulation.
std::vector< SimplexId > pointId_
SimplexId getNumberOfTriangles() const
Return the number of triangles in the output triangulation.
std::vector< LongSimplexId > cells_offsets_
int interpolateDiscreteScalarField(const T *data, T *output) const
Interpolate integer point data on subdivised triangulation.
std::vector< SimplexId > pointDim_
Minimalist debugging class.
Definition: Debug.h:88
void setDebugMsgPrefix(const std::string &prefix)
Definition: Debug.h:364
ExplicitTriangulation is a class that provides time efficient traversal methods on triangulations of ...
double getElapsedTime()
Definition: Timer.h:15
The Topology ToolKit.
long long int LongSimplexId
Identifier type for simplices of any dimension.
Definition: DataTypes.h:15
int SimplexId
Identifier type for simplices of any dimension.
Definition: DataTypes.h:22
printMsg(debug::output::GREEN+"                           "+debug::output::ENDCOLOR+debug::output::GREEN+"▒"+debug::output::ENDCOLOR+debug::output::GREEN+"▒▒▒▒▒▒▒▒▒▒▒▒▒░"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)