/
fixmesh.py
116 lines (99 loc) · 3.99 KB
/
fixmesh.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/env python
"""
Remesh the input mesh to remove degeneracies and improve triangle quality.
"""
import argparse
import numpy as np
from numpy.linalg import norm
import pymesh
def fix_mesh(mesh, detail="normal"):
bbox_min, bbox_max = mesh.bbox;
diag_len = norm(bbox_max - bbox_min);
if detail == "normal":
target_len = diag_len * 1e-2;
#target_len = diag_len * 5e-3;
elif detail == "enormal":
target_len = diag_len * 5e-3
elif detail == "high":
target_len = diag_len * 3e-3
#target_len = diag_len * 2.5e-3;
elif detail == "low":
target_len = diag_len * 1e-2;
elif detail == "ehigh":
target_len = diag_len * 1e-3;
print("Target resolution: {} mm".format(target_len));
count = 0;
mesh, __ = pymesh.remove_degenerated_triangles(mesh, 100);
mesh, __ = pymesh.split_long_edges(mesh, target_len);
num_vertices = mesh.num_vertices;
while True:
#mesh, __ = pymesh.collapse_short_edges(mesh, 1e-6);
if detail == "low":
mesh, __ = pymesh.collapse_short_edges(mesh, target_len, preserve_feature=False);
else:
mesh, __ = pymesh.collapse_short_edges(mesh, target_len, preserve_feature=True);
mesh, __ = pymesh.remove_obtuse_triangles(mesh, 150.0, 100);
if mesh.num_vertices == num_vertices:
break;
num_vertices = mesh.num_vertices;
print("#v: {}".format(num_vertices));
count += 1;
if count > 10: break;
mesh = pymesh.resolve_self_intersection(mesh);
mesh, __ = pymesh.remove_duplicated_faces(mesh);
mesh = pymesh.compute_outer_hull(mesh);
mesh, __ = pymesh.remove_duplicated_faces(mesh);
mesh, __ = pymesh.remove_obtuse_triangles(mesh, 179.0, 5);
mesh, __ = pymesh.remove_isolated_vertices(mesh);
return mesh;
def old_fix_mesh(vertices, faces, detail="normal"):
bbox_min = np.amin(vertices, axis=0);
bbox_max = np.amax(vertices, axis=0);
diag_len = norm(bbox_max - bbox_min);
if detail == "normal":
target_len = diag_len * 5e-3;
elif detail == "high":
target_len = diag_len * 2.5e-3;
elif detail == "low":
target_len = diag_len * 1e-2;
print("Target resolution: {} mm".format(target_len));
count = 0;
vertices, faces = split_long_edges(vertices, faces, target_len);
num_vertices = len(vertices);
while True:
vertices, faces = collapse_short_edges(vertices, faces, 1e-6);
vertices, faces = collapse_short_edges(vertices, faces,
target_len, preserve_feature=True);
vertices, faces = remove_obtuse_triangles(vertices, faces, 150.0, 100);
if (num_vertices == len(vertices)):
break;
num_vertices = len(vertices);
print("#v: {}".format(num_vertices));
count += 1;
if count > 10: break;
vertices, faces = resolve_self_intersection(vertices, faces);
vertices, faces = remove_duplicated_faces(vertices, faces);
vertices, faces, _ = compute_outer_hull(vertices, faces, False);
vertices, faces = remove_duplicated_faces(vertices, faces);
vertices, faces = remove_obtuse_triangles(vertices, faces, 179.0, 5);
vertices, faces, voxels = remove_isolated_vertices(vertices, faces);
return vertices, faces;
def parse_args():
parser = argparse.ArgumentParser(
description=__doc__);
parser.add_argument("--timing", help="print timing info",
action="store_true");
parser.add_argument("--detail", help="level of detail to preserve",
choices=["low", "normal", "high"], default="normal");
parser.add_argument("in_mesh", help="input mesh");
parser.add_argument("out_mesh", help="output mesh");
return parser.parse_args();
def main():
args = parse_args();
mesh = pymesh.meshio.load_mesh(args.in_mesh);
mesh = fix_mesh(mesh, detail = args.detail);
pymesh.meshio.save_mesh(args.out_mesh, mesh);
if args.timing:
pymesh.timethis.summarize();
if __name__ == "__main__":
main();