Easy3D 2.5.3
surface_mesh_simplification.h
1/********************************************************************
2 * Copyright (C) 2020-2021 by Liangliang Nan <liangliang.nan@gmail.com>
3 * Copyright (C) 2011-2020 the Polygon Mesh Processing Library developers.
4 *
5 * The code in this file is adapted from the PMP (Polygon Mesh Processing
6 * Library) with modifications.
7 * https://github.com/pmp-library/pmp-library
8 * The original code was distributed under a MIT-style license, see
9 * https://github.com/pmp-library/pmp-library/blob/master/LICENSE.txt
10 ********************************************************************/
11
12#ifndef EASY3D_ALGO_SURFACE_MESH_SIMPLIFICATION_H
13#define EASY3D_ALGO_SURFACE_MESH_SIMPLIFICATION_H
14
15#include <easy3d/core/surface_mesh.h>
16#include <easy3d/core/heap.h>
17
18#include <set>
19#include <vector>
20
21
22namespace easy3d {
23
25 class Quadric {
26 public:
28 Quadric(double a, double b, double c, double d,
29 double e, double f, double g,
30 double h, double i,
31 double j)
32 : a_(a), b_(b), c_(c), d_(d),
33 e_(e), f_(f), g_(g),
34 h_(h), i_(i),
35 j_(j) {}
36
38 explicit Quadric(double a = 0.0, double b = 0.0, double c = 0.0, double d = 0.0)
39 : a_(a * a), b_(a * b), c_(a * c), d_(a * d),
40 e_(b * b), f_(b * c), g_(b * d),
41 h_(c * c), i_(c * d),
42 j_(d * d) {}
43
45 Quadric(const vec3 &n, const vec3 &p) {
46 *this = Quadric(n[0], n[1], n[2], -dot(n, p));
47 }
48
50 void clear() { a_ = b_ = c_ = d_ = e_ = f_ = g_ = h_ = i_ = j_ = 0.0; }
51
54 a_ += q.a_;
55 b_ += q.b_;
56 c_ += q.c_;
57 d_ += q.d_;
58 e_ += q.e_;
59 f_ += q.f_;
60 g_ += q.g_;
61 h_ += q.h_;
62 i_ += q.i_;
63 j_ += q.j_;
64 return *this;
65 }
66
68 Quadric &operator*=(double s) {
69 a_ *= s;
70 b_ *= s;
71 c_ *= s;
72 d_ *= s;
73 e_ *= s;
74 f_ *= s;
75 g_ *= s;
76 h_ *= s;
77 i_ *= s;
78 j_ *= s;
79 return *this;
80 }
81
83 double operator()(const vec3 &p) const {
84 const double x(p[0]), y(p[1]), z(p[2]);
85 return a_ * x * x + 2.0 * b_ * x * y + 2.0 * c_ * x * z + 2.0 * d_ * x
86 + e_ * y * y + 2.0 * f_ * y * z + 2.0 * g_ * y
87 + h_ * z * z + 2.0 * i_ * z
88 + j_;
89 }
90
91 private:
92
93 double a_, b_, c_, d_,
94 e_, f_, g_,
95 h_, i_,
96 j_;
97 };
98
99 //=============================================================================
100
103 public:
105 NormalCone() = default;
106
108 explicit NormalCone(const vec3 &normal, float angle = 0.0)
109 : center_normal_(normal), angle_(angle) {
110 }
111
113 const vec3 &center_normal() const { return center_normal_; }
114
116 float angle() const { return angle_; }
117
119 NormalCone &merge(const vec3 &n) { return merge(NormalCone(n)); }
120
123 const float dp = dot(center_normal_, nc.center_normal_);
124
125 // axes point in same direction
126 if (dp > 0.99999) {
127 angle_ = std::max(angle_, nc.angle_);
128 }
129
130 // axes point in opposite directions
131 else if (dp < -0.99999) {
132 angle_ = static_cast<float>(2 * M_PI);
133 } else {
134 // new angle
135 float center_angle = std::acos(dp);
136 float min_angle = std::min(-angle_, center_angle - nc.angle_);
137 float max_angle = std::max(angle_, center_angle + nc.angle_);
138 angle_ = 0.5f * (max_angle - min_angle);
139
140 // axis by SLERP
141 float axis_angle = 0.5f * (min_angle + max_angle);
142 center_normal_ = ((center_normal_ * std::sin(center_angle - axis_angle) +
143 nc.center_normal_ * std::sin(axis_angle)) /
144 std::sin(center_angle));
145 }
146
147 return *this;
148 }
149
150 private:
151 vec3 center_normal_;
152 float angle_;
153 };
154
155
156 //=============================================================================
157
167 public:
170
171 // destructor
173
175 void initialize(float aspect_ratio = 0.0, float edge_length = 0.0,
176 unsigned int max_valence = 0, float normal_deviation = 0.0,
177 float hausdorff_error = 0.0);
178
180 void simplify(unsigned int n_vertices);
181
182 private:
184 /*
185 vl
186 *
187 / \
188 / \
189 / fl \
190 v0 *------>* v1
191 \ fr /
192 \ /
193 \ /
194 *
195 vr
196 */
197 struct CollapseData {
198 CollapseData(SurfaceMesh *sm, SurfaceMesh::Halfedge h);
199
200 SurfaceMesh *mesh;
201
202 SurfaceMesh::Halfedge v0v1; // Halfedge to be collapsed
203 SurfaceMesh::Halfedge v1v0; // Reverse halfedge
204 SurfaceMesh::Vertex v0; // Vertex to be removed
205 SurfaceMesh::Vertex v1; // Remaining vertex
206 SurfaceMesh::Face fl; // Left face
207 SurfaceMesh::Face fr; // Right face
208 SurfaceMesh::Vertex vl; // Left vertex
209 SurfaceMesh::Vertex vr; // Right vertex
210 SurfaceMesh::Halfedge v1vl, vlv0, v0vr, vrv1;
211 };
212
214 class HeapInterface {
215 public:
217 : prio_(prio), pos_(pos) {
218 }
219
220 bool less(SurfaceMesh::Vertex v0, SurfaceMesh::Vertex v1) { return prio_[v0] < prio_[v1]; }
221
222 bool greater(SurfaceMesh::Vertex v0, SurfaceMesh::Vertex v1) { return prio_[v0] > prio_[v1]; }
223
224 int get_heap_position(SurfaceMesh::Vertex v) { return pos_[v]; }
225
226 void set_heap_position(SurfaceMesh::Vertex v, int pos) { pos_[v] = pos; }
227
228 private:
231 };
232
234
235 typedef std::vector<vec3> Points;
236
237 private:
238 // put the vertex v in the priority queue
239 void enqueue_vertex(SurfaceMesh::Vertex v);
240
241 // is collapsing the halfedge h allowed?
242 bool is_collapse_legal(const CollapseData &cd);
243
244 // what is the priority of collapsing the halfedge h
245 float priority(const CollapseData &cd);
246
247 // postprocess halfedge collapse
248 void postprocess_collapse(const CollapseData &cd);
249
250 // compute aspect ratio for face f
251 float aspect_ratio(SurfaceMesh::Face f) const;
252
253 // compute distance from p to triangle f
254 float distance(SurfaceMesh::Face f, const vec3 &p) const;
255
256 private:
257 SurfaceMesh *mesh_;
258
259 bool initialized_;
260
267
273
274 PriorityQueue *queue_;
275
276 bool has_selection_;
277 bool has_features_;
278 float normal_deviation_;
279 float hausdorff_error_;
280 float aspect_ratio_;
281 float edge_length_;
282 unsigned int max_valence_;
283 };
284
285} // namespace easy3d
286
287#endif // EASY3D_ALGO_SURFACE_MESH_SIMPLIFICATION_H
A class implementing a heap.
Definition: heap.h:59
A class implementing a normal cone.
Definition: surface_mesh_simplification.h:102
NormalCone & merge(const NormalCone &nc)
merge *this with nc. *this will then enclose both cones.
Definition: surface_mesh_simplification.h:122
NormalCone & merge(const vec3 &n)
merge *this with n.
Definition: surface_mesh_simplification.h:119
NormalCone()=default
default constructor (not initialized)
NormalCone(const vec3 &normal, float angle=0.0)
Initialize cone with center (unit vector) and angle (radius in radians)
Definition: surface_mesh_simplification.h:108
float angle() const
returns size of cone (radius in radians)
Definition: surface_mesh_simplification.h:116
const vec3 & center_normal() const
returns center normal
Definition: surface_mesh_simplification.h:113
A quadric as a symmetric 4x4 matrix. Used by the error quadric mesh decimation algorithms.
Definition: surface_mesh_simplification.h:25
Quadric & operator*=(double s)
multiply quadric by a scalar
Definition: surface_mesh_simplification.h:68
double operator()(const vec3 &p) const
evaluate quadric Q at position p by computing (p^T * Q * p)
Definition: surface_mesh_simplification.h:83
Quadric & operator+=(const Quadric &q)
add given quadric to this quadric
Definition: surface_mesh_simplification.h:53
Quadric(double a=0.0, double b=0.0, double c=0.0, double d=0.0)
constructor quadric from given plane equation: ax+by+cz+d=0
Definition: surface_mesh_simplification.h:38
Quadric(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j)
construct quadric from upper triangle of symmetric 4x4 matrix
Definition: surface_mesh_simplification.h:28
void clear()
set all matrix entries to zero
Definition: surface_mesh_simplification.h:50
Quadric(const vec3 &n, const vec3 &p)
construct from point and normal specifying a plane
Definition: surface_mesh_simplification.h:45
Definition: surface_mesh.h:233
Definition: surface_mesh.h:257
A halfedge data structure for polygonal meshes of 2-manifold.
Definition: surface_mesh.h:52
Surface mesh simplification based on approximation error and fairness criteria.
Definition: surface_mesh_simplification.h:166
SurfaceMeshSimplification(SurfaceMesh *mesh)
Construct with mesh to be simplified.
Definition: surface_mesh_simplification.cpp:20
void simplify(unsigned int n_vertices)
Simplify mesh to n vertices.
Definition: surface_mesh_simplification.cpp:124
void initialize(float aspect_ratio=0.0, float edge_length=0.0, unsigned int max_valence=0, float normal_deviation=0.0, float hausdorff_error=0.0)
Initialize with given parameters.
Definition: surface_mesh_simplification.cpp:42
Definition: collider.cpp:182
FT dot(const std::vector< FT > &, const std::vector< FT > &)
Inner product for vectors.
Definition: matrix.h:1803
Definition: surface_mesh.h:134
Definition: surface_mesh.h:114
Definition: surface_mesh.h:104