TTK
Loading...
Searching...
No Matches
SurfaceGeometrySmoother.h
Go to the documentation of this file.
1
24
25#pragma once
26
27// base code includes
28#include <Triangulation.h>
29
30#include <numeric>
31#include <stack>
32#include <string>
33
34namespace ttk {
35
36 class SurfaceGeometrySmoother : virtual public Debug {
37
38 public:
40 ~SurfaceGeometrySmoother() override = default;
41
43 AbstractTriangulation *const triangulation) {
44 if(triangulation != nullptr) {
45 triangulation->preconditionVertexNeighbors();
46 if(triangulation->getDimensionality() == 2) {
47 triangulation->preconditionVertexStars();
48 }
49 }
50 }
52 AbstractTriangulation *const triangulation) {
53 if(triangulation != nullptr) {
54 triangulation->preconditionEdges();
55 triangulation->preconditionVertexNeighbors();
56 triangulation->preconditionVertexEdges();
57 triangulation->preconditionTriangles();
58 triangulation->preconditionVertexTriangles();
59 triangulation->preconditionEdgeTriangles();
60 }
61 }
62
63 template <typename triangulationType0, typename triangulationType1>
64 int execute(float *const outputCoords,
65 const float *const inputCoords,
66 const char *const mask,
67 const SimplexId *const vertsId,
68 const int nIter,
69 const triangulationType0 &triangulationToSmooth,
70 const triangulationType1 &triangulationSurface) const;
71
72 struct Point : public std::array<float, 3> {
73 Point operator+(const Point other) const {
74 Point res{};
75 res[0] = (*this)[0] + other[0];
76 res[1] = (*this)[1] + other[1];
77 res[2] = (*this)[2] + other[2];
78 return res;
79 }
80 Point operator*(const float scalar) const {
81 Point res{};
82 res[0] = (*this)[0] * scalar;
83 res[1] = (*this)[1] * scalar;
84 res[2] = (*this)[2] * scalar;
85 return res;
86 }
87 Point operator-(Point other) const {
88 return *this + other * (-1);
89 }
90 Point operator/(const float scalar) const {
91 return (*this * (1.0F / scalar));
92 }
93 friend std::ostream &operator<<(std::ostream &os, const Point &pt) {
94 return os << '(' << pt[0] << " " << pt[1] << " " << pt[2] << ')';
95 }
96 };
97
98 protected:
99 template <typename triangulationType0, typename triangulationType1>
100 int relaxProject(std::vector<Point> &outputPoints,
101 std::vector<Point> &tmpStorage,
102 std::vector<SimplexId> &nearestVertexId,
103 std::vector<bool> &trianglesTested,
104 std::vector<SimplexId> &visitedTriangles,
105 std::vector<float> &dists,
106 const char *const mask,
107 const triangulationType0 &triangulationToSmooth,
108 const triangulationType1 &triangulationSurface) const;
109
118 template <typename triangulationType>
119 inline Point
121 std::vector<ttk::SurfaceGeometrySmoother::Point> &outputPoints,
122 const triangulationType &triangulationToSmooth) const {
123 Point relaxed{outputPoints[a]};
124 const auto nneigh{triangulationToSmooth.getVertexNeighborNumber(a)};
125 for(SimplexId i = 0; i < nneigh; ++i) {
126 SimplexId neigh{};
127 triangulationToSmooth.getVertexNeighbor(a, i, neigh);
128 relaxed = relaxed + outputPoints[neigh];
129 }
130 return relaxed * (1.0F / static_cast<float>(nneigh + 1));
131 }
132 };
133
134} // namespace ttk
135
136template <typename triangulationType0, typename triangulationType1>
138 std::vector<ttk::SurfaceGeometrySmoother::Point> &outputPoints,
139 std::vector<ttk::SurfaceGeometrySmoother::Point> &tmpStorage,
140 std::vector<SimplexId> &nearestVertexId,
141 std::vector<bool> &trianglesTested,
142 std::vector<SimplexId> &visitedTriangles,
143 std::vector<float> &dists,
144 const char *const mask,
145 const triangulationType0 &triangulationToSmooth,
146 const triangulationType1 &triangulationSurface) const {
147
148 Timer tm;
149 std::stack<SimplexId> trianglesToTest{};
150
151 // main loop
152#ifdef TTK_ENABLE_OPENMP4
153#pragma omp parallel for num_threads(threadNumber_) \
154 firstprivate(trianglesTested, visitedTriangles, dists, trianglesToTest)
155#endif // TTK_ENABLE_OPENMP
156 for(size_t i = 0; i < outputPoints.size(); i++) {
157
158 // skip computation if i in filtered
159 if(mask != nullptr && mask[i] == 0) {
160 tmpStorage[i] = outputPoints[i];
161 continue;
162 }
163 tmpStorage[i] = this->relax(i, outputPoints, triangulationToSmooth);
164
165 VisitedMask vm{trianglesTested, visitedTriangles};
166
167 // replace curr in outputPoints_ by its projection
168 const auto res = Geometry::findProjection(
169 Geometry::ProjectionInput{i, tmpStorage[i], nearestVertexId[i]}, vm,
170 dists, trianglesToTest, false, triangulationToSmooth,
171 triangulationSurface);
172
173 tmpStorage[i] = Point{res.pt};
174 nearestVertexId[i] = res.nearestVertex;
175 }
176
177 std::swap(outputPoints, tmpStorage);
178
179 this->printMsg("Projected " + std::to_string(outputPoints.size()) + " points",
180 1.0, tm.getElapsedTime(), this->threadNumber_,
182
183 return 0;
184}
185
186template <typename triangulationType0, typename triangulationType1>
188 float *const outputCoords,
189 const float *const inputCoords,
190 const char *const mask,
191 const SimplexId *const vertsId,
192 const int nIter,
193 const triangulationType0 &triangulationToSmooth,
194 const triangulationType1 &triangulationSurface) const {
195
196 const auto nPoints{triangulationToSmooth.getNumberOfVertices()};
197 if(triangulationSurface.getDimensionality() != 2) {
198 this->printErr("Can only project onto a surface");
199 return -1;
200 }
201
202 if(triangulationToSmooth.getDimensionality() < 1
203 || triangulationToSmooth.getDimensionality() > 2) {
204 this->printErr("Can only project a 1D or a 2D triangulated object");
205 return -1;
206 }
207
208 Timer tm{};
209 this->printMsg("Smoothing " + std::to_string(nPoints) + " points in "
210 + std::to_string(nIter) + " iterations...");
211
212 // list of triangle IDs already tested
213 // (takes more memory to reduce computation time)
214 std::vector<bool> trianglesTested(
215 triangulationSurface.getNumberOfTriangles(), false);
216 std::vector<SimplexId> visitedTriangles{};
217 // distance between every mesh point and current point
218 std::vector<float> dists(triangulationSurface.getNumberOfVertices());
219
220 // temporary storage
221 std::vector<ttk::SurfaceGeometrySmoother::Point> outputPoints(nPoints),
222 tmpStorage(nPoints);
223 std::vector<SimplexId> nearestVertexId(nPoints);
224
225 // copy input
226#ifdef TTK_ENABLE_OPENMP
227#pragma omp parallel for num_threads(threadNumber_)
228#endif // TTK_ENABLE_OPENMP
229 for(SimplexId i = 0; i < nPoints; ++i) {
230 outputPoints[i][0] = inputCoords[3 * i + 0];
231 outputPoints[i][1] = inputCoords[3 * i + 1];
232 outputPoints[i][2] = inputCoords[3 * i + 2];
233 }
234
235 // ttkVertexScalarField is optional (helps for instance with
236 // MorseSmaleComplex 1-separatrices)
237 if(vertsId != nullptr) {
238#ifdef TTK_ENABLE_OPENMP
239#pragma omp parallel for num_threads(threadNumber_)
240#endif // TTK_ENABLE_OPENMP
241 for(SimplexId i = 0; i < nPoints; ++i) {
242 nearestVertexId[i] = vertsId[i];
243 }
244 } else {
245 // generate a ttkVertexScalarField-like point data array using raw
246 // euclidean distance between the points to smooth and every
247 // vertex of the surface
248 Timer tm_nv{};
249 this->printMsg("Computing nearest vertices...", debug::Priority::INFO,
251#ifdef TTK_ENABLE_OPENMP
252#pragma omp parallel for num_threads(threadNumber_) firstprivate(dists)
253#endif // TTK_ENABLE_OPENMP
254 for(SimplexId i = 0; i < nPoints; ++i) {
255 nearestVertexId[i] = Geometry::getNearestSurfaceVertex(
256 outputPoints[i].data(), dists, triangulationSurface);
257 }
258 this->printMsg("Computed nearest vertices", 1.0, tm_nv.getElapsedTime(),
259 this->threadNumber_);
260 }
261
262 for(int i = 0; i < nIter; ++i) {
263 this->relaxProject(outputPoints, tmpStorage, nearestVertexId,
264 trianglesTested, visitedTriangles, dists, mask,
265 triangulationToSmooth, triangulationSurface);
266 }
267
268 // copy output
269#ifdef TTK_ENABLE_OPENMP
270#pragma omp parallel for num_threads(threadNumber_)
271#endif // TTK_ENABLE_OPENMP
272 for(SimplexId i = 0; i < nPoints; ++i) {
273 outputCoords[3 * i + 0] = outputPoints[i][0];
274 outputCoords[3 * i + 1] = outputPoints[i][1];
275 outputCoords[3 * i + 2] = outputPoints[i][2];
276 }
277
278 this->printMsg("Smoothed " + std::to_string(nPoints) + " points", 1.0,
279 tm.getElapsedTime(), this->threadNumber_);
280
281 return 0;
282}
boost::tuple< double, double > Point
Definition TopoMap.cpp:56
AbstractTriangulation is an interface class that defines an interface for efficient traversal methods...
virtual int getDimensionality() const
Minimalist debugging class.
Definition Debug.h:88
TTK VTK-filter for smoothing meshes on surfaces.
~SurfaceGeometrySmoother() override=default
int relaxProject(std::vector< Point > &outputPoints, std::vector< Point > &tmpStorage, std::vector< SimplexId > &nearestVertexId, std::vector< bool > &trianglesTested, std::vector< SimplexId > &visitedTriangles, std::vector< float > &dists, const char *const mask, const triangulationType0 &triangulationToSmooth, const triangulationType1 &triangulationSurface) const
int execute(float *const outputCoords, const float *const inputCoords, const char *const mask, const SimplexId *const vertsId, const int nIter, const triangulationType0 &triangulationToSmooth, const triangulationType1 &triangulationSurface) const
void preconditionTriangulationSurface(AbstractTriangulation *const triangulation)
void preconditionTriangulationToSmooth(AbstractTriangulation *const triangulation)
Point relax(const SimplexId a, std::vector< ttk::SurfaceGeometrySmoother::Point > &outputPoints, const triangulationType &triangulationToSmooth) const
Computes the barycenter of a given point's neighbors.
double getElapsedTime()
Definition Timer.h:15
SimplexId getNearestSurfaceVertex(const T *pa, std::vector< T > &dists, const triangulationType &triangulation)
Find nearest vertex on the surface.
Definition Geometry.h:517
ProjectionResult findProjection(const ProjectionInput &pi, VisitedMask &trianglesTested, std::vector< float > &dists, std::stack< SimplexId > &trianglesToTest, const bool reverseProjection, const triangulationType0 &triangulationToSmooth, const triangulationType1 &triangulation)
Definition Geometry.h:891
The Topology ToolKit.
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
Stores the findProjection() input.
Definition Geometry.h:880
friend std::ostream & operator<<(std::ostream &os, const Point &pt)
Point operator/(const float scalar) const
Point operator*(const float scalar) const
Point operator+(const Point other) const
Auto-cleaning re-usable graph propagations data structure.
Definition VisitedMask.h:27
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)