/
remesh.m
185 lines (168 loc) · 6.02 KB
/
remesh.m
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
% remesh Surface simplification
%
% Usage:
%
% [surface] = remesh (surface, opt)
% [surface] = remesh (TRI, X, Y, Z, opt)
% [TRI,X,Y,Z] = remesh (surface, opt)
% [TRI,X,Y,Z] = remesh (TRI, X, Y, Z, opt)
%
% Description:
%
% Reduces the vertex and face count of a surface using the QSlim
% algorithm.
%
% Input:
%
% TRIV - ntx3 triangulation matrix with 1-based indices (as the one
% returned by the MATLAB function delaunay).
% X,Y,Z - vectors with nv vertex coordinates.
% surface - alternative way to specify the mesh as a struct, having .TRIV,
% .X, .Y, and .Z as its fields.
% opt - (optional) settings
% .placement [-O] Optimal placement policy (default: 3)
% 0 - end points,
% 1 - end or mid points,
% 2 - line,
% 3 - optimal
% .boundary [-B] Use boundary preservation planes with given weight
% (default: 1000)
% .weight [-W] Quadric weighting policy (default: 1)
% 0 - uniform,
% 1 - area,
% 2 - angle
% .contract [-F] Contraction of faces ('faces') or edges ('edges')
% (default: 'edges')
% .penalty [-m] Penalty for bad meshes (default: 1)
% .compact [-c] Compactness ratio (default: 0)
% .join [-j] Join only without removing faces (default: 'false')
% .faces [-t] Target number of faces
% .vertices Target number of vertices (default: 2000)
% .verbose Verbosity level (default: 1)
% 0 - no display,
% 1 - display results
%
% Output:
%
% TRIV - ntx3 triangulation matrix of the simplified surface.
% X,Y,Z - list of vertices of the simplified surface.
% surface - alternative way to specify the simplified surface.
%
% References:
%
% [1] http://www.cs.cmu.edu/~garland/quadrics/
%
% TOSCA = Toolbox for Surface Comparison and Analysis
% Web: http://tosca.cs.technion.ac.il
% Version: 0.9
%
% (C) QSlim 2.0 copyright Michael Garland, 1998.
% (C) Mex iterface copyright Alex Bronstein, 2007.
function [TRIV_, X_, Y_, Z_] = remesh(surface, options)
if isstruct(surface),
TRI = surface.TRIV;
X = surface.X;
Y = surface.Y;
Z = surface.Z;
else
TRI = surface;
X = varargin{1};
Y = varargin{2};
Z = varargin{3};
varargin = varargin(4:end);
end
opt = [3 1000 1 0 1 0 0];
verts = min(length(X), 2000);
faces = 0;
verbose = 1;
if nargin > 1,
if isfield(options, 'placement'),
opt(1) = options.placement;
end
if isfield(options, 'boundary'),
opt(2) = options.boundary;
end
if isfield(options, 'weight'),
opt(3) = options.weight;
end
if isfield(options, 'contract'),
if strcmpi(value,'face') | strcmpi(value,'faces'),
opt(4) = 1;
elseif strcmpi(value,'edge') | strcmpi(value,'edges'),
opt(4) = 0;
else
error('Invalid value setting for .contract. Must be "faces" or "edges".');
end
end
if isfield(options, 'penalty'),
opt(5) = options.penalty;
end
if isfield(options, 'compact'),
opt(6) = options.compact;
end
if isfield(options, 'join'),
if strcmpi(options.join,'true') | value == 1,
opt(7) = 1;
elseif strcmpi(options.join,'false') | value == 0,
opt(7) = 0;
else
error('Invalid value setting for .join. Must be "true" or "false".');
end
end
if isfield(options, 'vertices'),
verts = options.vertices;
end
if isfield(options, 'faces'),
faces = options.faces;
end
if isfield(options, 'verbose'),
verbose = options.verbose;
end
end
if verts < 1 & faces < 1,
error('Either face or vertex positive count targets have to be specified.');
end
switch opt(1),
case 0, placement_policy = 'end point';
case 1, placement_policy = 'end or mid point';
case 2, placement_policy = 'line';
case 3, placement_policy = 'optimal';
otherwise, error('Invalid placement policy. Use .placement = 0-3.');
end
switch opt(3),
case 0, weighting_policy = 'uniform';
case 1, weighting_policy = 'area';
case 2, weighting_policy = 'angle';
otherwise, error('Invalid weighting policy. Use .weigh = 0-2.');
end
if opt(4), contract = 'face', else contract = 'edge'; end
if opt(7), join = 'on', else join = 'off'; end
if verbose > 0,
fprintf (1, 'Surface simplification\n');
fprintf (1, 'Placement policy: %s\n', placement_policy);
fprintf (1, 'Weighting policy: %s\n', weighting_policy);
fprintf (1, 'Boundary preserv. weight: %-8.6g\n', opt(2));
fprintf (1, 'Contraction: %s\n', contract);
fprintf (1, 'Bad mesh penalty: %-8.6g\n', opt(5));
fprintf (1, 'Compactness ratio: %-8.6g\n', opt(6));
fprintf (1, 'Join only: %s\n', join);
fprintf (1, 'Original faces: %-d\n', size(TRI,1));
fprintf (1, 'Original vertices: %-d\n', length(X));
fprintf (1, 'Target faces: %-d\n', faces);
fprintf (1, 'Target vertices: %-d\n', verts);
end
[TRIV_,X_,Y_,Z_] = qslim(TRI, X, Y, Z, faces, verts, opt);
if verbose > 0,
fprintf (1, 'Done. faces = %d vertices = %d\n\n', size(TRIV_,1), length(X_));
end
if nargout <= 1,
surface_ = [];
surface_.TRIV = TRIV_;
surface_.X = X_;
surface_.Y = Y_;
surface_.Z = Z_;
TRIV_ = surface_;
if isstruct(surface) & isfield(surface,'D'),
warning('The returned result is an uninitialized surface. Use init_surface to initialize.');
end
end