Skip to content

Commit c141ab2

Browse files
committed
Update: add feature preservation in remeshing.
1 parent 46d944f commit c141ab2

File tree

16 files changed

+153
-76
lines changed

16 files changed

+153
-76
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
v.0.1.1
22
---
33

4+
* Add feature preservation in remeshing.
45
* Include Eigen to repo as a submodule.
56
* Update Python setup to use Poetry.
67
* Add mesh denoising via bilateral filter [Zheng et al. 2011] and L0 smoothing [He and Schaefer 2013].

examples/example_remesh.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,17 @@ namespace mesh = tinymesh;
77

88
int main(int argc, char **argv) {
99
if (argc <= 1) {
10-
printf("usage: %s [input mesh]\n", argv[0]);
10+
printf("usage: %s [input mesh] [keep angle]\n", argv[0]);
1111
return 1;
1212
}
1313

1414
// Load
1515
mesh::Mesh mesh(argv[1]);
1616

1717
// Fill holes & remesh
18+
const double keepAngle = argc > 2 ? std::atof(argv[2]) * Pi / 180.0 : 0.0;
1819
mesh::holeFill(mesh, Pi / 6.0);
19-
mesh::remeshTriangular(mesh);
20+
mesh::remeshTriangular(mesh, 0.8, 1.333, keepAngle);
2021

2122
// Save
2223
const fs::path filepath = fs::canonical(fs::path(argv[1]));

examples/python/fill_and_fair.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ def main(filename):
1010
mesh = Mesh(filename)
1111

1212
# Freeze faces
13-
for i in range(mesh.num_faces()):
14-
f = mesh.face(i)
15-
f.set_is_static(True)
13+
for i in range(mesh.num_vertices()):
14+
v = mesh.vertex(i)
15+
v.set_is_static(True)
1616

1717
# Fill holes
1818
hole_fill(mesh, np.pi / 6.0)

src/pybind11.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,13 @@ PYBIND11_MODULE(tinymesh, m) {
7070
.def("pos", &Vertex::pos)
7171
.def("set_pos", &Vertex::setPos)
7272
.def("is_boundary", &Vertex::isBoundary)
73-
.def("is_static", &Vertex::isStatic);
73+
.def("is_static", &Vertex::isStatic)
74+
.def("set_is_static", &Vertex::setIsStatic);
7475

7576
py::class_<Face, std::shared_ptr<Face>>(m, "Face")
7677
.def(py::init<>())
7778
.def("is_boundary", &Face::isBoundary)
78-
.def("is_static", &Face::isStatic)
79-
.def("set_is_static", &Face::setIsStatic);
80-
79+
.def("is_static", &Face::isStatic);
8180

8281
/*** Smoothing ***/
8382

@@ -129,7 +128,7 @@ PYBIND11_MODULE(tinymesh, m) {
129128
py::arg("mesh"),
130129
py::arg("short_length") = 0.8,
131130
py::arg("long_length") = 1.333,
132-
py::arg("angle_thresh") = 0.2,
131+
py::arg("angle_keep_less_than") = 0.0,
133132
py::arg("iterations") = 5);
134133

135134
/*** Simplification ***/

src/tinymesh/core/face.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#define TINYMESH_API_EXPORT
22
#include "face.h"
33

4+
#include "vertex.h"
45
#include "halfedge.h"
56

67
namespace tinymesh {
@@ -12,10 +13,27 @@ bool Face::operator==(const Face &other) const {
1213
bool ret = true;
1314
ret &= (halfedge_ == other.halfedge_);
1415
ret &= (index_ == other.index_);
15-
ret &= (isBoundary_ == other.isBoundary_);
1616
return ret;
1717
}
1818

19+
bool Face::isBoundary() {
20+
for (auto vit = this->v_begin(); vit != this->v_end(); ++vit) {
21+
if (vit->isBoundary()) {
22+
return true;
23+
}
24+
}
25+
return false;
26+
}
27+
28+
bool Face::isStatic() {
29+
for (auto vit = this->v_begin(); vit != this->v_end(); ++vit) {
30+
if (vit->isStatic()) {
31+
return true;
32+
}
33+
}
34+
return false;
35+
}
36+
1937
Face::VertexIterator Face::v_begin() {
2038
return Face::VertexIterator(halfedge_);
2139
}

src/tinymesh/core/face.h

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,13 @@ class TINYMESH_API Face {
3636
int index() const {
3737
return index_;
3838
}
39-
bool isBoundary() const {
40-
return isBoundary_;
41-
}
42-
bool isStatic() const {
43-
return isStatic_;
44-
}
45-
void setIsStatic(bool flag) {
46-
isStatic_ = flag;
47-
}
39+
40+
bool isBoundary();
41+
bool isStatic();
4842

4943
private:
5044
Halfedge *halfedge_ = nullptr;
5145
int index_ = -1;
52-
bool isBoundary_ = false;
53-
bool isStatic_ = false;
5446

5547
friend class Mesh;
5648
};

src/tinymesh/core/halfedge.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@ double Halfedge::length() const {
2323
return ::length(src()->pos() - dst()->pos());
2424
}
2525

26+
bool Halfedge::isStatic() const {
27+
return this->src()->isStatic() && this->dst()->isStatic();
28+
}
29+
2630
bool Halfedge::isBoundary() const {
27-
return face_->isBoundary();
31+
return this->src()->isBoundary() && this->dst()->isBoundary();
2832
}
2933

3034
} // namespace tinymesh

src/tinymesh/core/halfedge.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class TINYMESH_API Halfedge {
4040
Edge *edge() const { return edge_; }
4141
Face *face() const { return face_; }
4242
int index() const { return index_; }
43+
bool isStatic() const;
4344
bool isBoundary() const;
4445

4546
private:

src/tinymesh/core/mesh.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,6 @@ void Mesh::construct() {
239239
if (he->rev_ == nullptr) {
240240
auto face = new Face();
241241
addFace(face);
242-
face->isBoundary_ = true;
243242

244243
std::vector<Halfedge *> boundaryHalfedges;
245244
Halfedge *it = he.get();
@@ -273,6 +272,7 @@ void Mesh::construct() {
273272
const auto degree = static_cast<int>(boundaryHalfedges.size());
274273
for (int j = 0; j < degree; j++) {
275274
const int k = (j - 1 + degree) % degree;
275+
boundaryHalfedges[j]->src_->isBoundary_ = true;
276276
boundaryHalfedges[j]->next_ = boundaryHalfedges[k];
277277
}
278278
}
@@ -289,13 +289,10 @@ void Mesh::construct() {
289289
FatalError("Some vertices are not referenced by any polygon!");
290290
}
291291

292-
uint32_t count = 0;
292+
uint32_t count = v->isBoundary() ? -1 : 0;
293293
Halfedge *he = v->halfedge_;
294294
do {
295-
if (!he->face()->isBoundary()) {
296-
count += 1;
297-
}
298-
295+
count += 1;
299296
he = he->rev()->next();
300297
} while (he != v->halfedge_);
301298

@@ -897,7 +894,6 @@ bool Mesh::triangulate(Face *face, double dihedralBound) {
897894
* Different from them, the triangularion is performed when the dihedral
898895
* angle in resulting triangularion is less than "dihedralBound".
899896
*/
900-
901897
using E = IndexPair;
902898
using T = std::tuple<uint32_t, uint32_t, uint32_t>;
903899

@@ -1097,6 +1093,7 @@ bool Mesh::triangulate(Face *face, double dihedralBound) {
10971093
}
10981094
}
10991095

1096+
he->src_->isBoundary_ = false;
11001097
he = he->next_;
11011098
} while (he != f->halfedge_);
11021099
}

src/tinymesh/core/vec.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,11 +255,17 @@ Float dihedral(const Vec<Float, Dims> &v1, const Vec<Float, Dims> &v2, const Vec
255255
using V = Vec<Float, Dims>;
256256
const V e12 = v2 - v1;
257257
const V e13 = v3 - v1;
258-
const V n1 = normalize(cross(e12, e13));
258+
const V n1 = cross(e12, e13);
259+
const Float l1 = length(n1);
259260
const V e42 = v2 - v1rev;
260261
const V e43 = v3 - v1rev;
261-
const V n4 = normalize(cross(e42, e43));
262-
return std::acos(dot(n1, n4));
262+
const V n4 = cross(e42, e43);
263+
const Float l4 = length(n4);
264+
if (l1 == 0.0 || l4 == 0.0) {
265+
return 0.0;
266+
}
267+
268+
return std::acos(dot(n1, n4) / (l1 * l4));
263269
}
264270

265271
// Hash

0 commit comments

Comments
 (0)