admesh 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ext/admesh/admesh/AUTHORS +11 -0
- data/ext/admesh/admesh/COPYING +339 -0
- data/ext/admesh/admesh/ChangeLog +143 -0
- data/ext/admesh/admesh/ChangeLog.old +42 -0
- data/ext/admesh/admesh/INSTALL +14 -0
- data/ext/admesh/admesh/Makefile.am +62 -0
- data/ext/admesh/admesh/Makefile.in +1100 -0
- data/ext/admesh/admesh/README.md +115 -0
- data/ext/admesh/admesh/aclocal.m4 +1183 -0
- data/ext/admesh/admesh/admesh-doc.txt +475 -0
- data/ext/admesh/admesh/admesh.1 +173 -0
- data/ext/admesh/admesh/block.stl +86 -0
- data/ext/admesh/admesh/compile +347 -0
- data/ext/admesh/admesh/config.guess +1420 -0
- data/ext/admesh/admesh/config.h.in +65 -0
- data/ext/admesh/admesh/config.sub +1798 -0
- data/ext/admesh/admesh/configure +14671 -0
- data/ext/admesh/admesh/configure.ac +90 -0
- data/ext/admesh/admesh/depcomp +791 -0
- data/ext/admesh/admesh/install-sh +527 -0
- data/ext/admesh/admesh/libadmesh.pc.in +11 -0
- data/ext/admesh/admesh/ltmain.sh +9655 -0
- data/ext/admesh/admesh/m4/libtool.m4 +7992 -0
- data/ext/admesh/admesh/m4/ltoptions.m4 +384 -0
- data/ext/admesh/admesh/m4/ltsugar.m4 +123 -0
- data/ext/admesh/admesh/m4/ltversion.m4 +23 -0
- data/ext/admesh/admesh/m4/lt~obsolete.m4 +98 -0
- data/ext/admesh/admesh/missing +215 -0
- data/ext/admesh/admesh/src/admesh.c +425 -0
- data/ext/admesh/admesh/src/connect.c +971 -0
- data/ext/admesh/admesh/src/normals.c +333 -0
- data/ext/admesh/admesh/src/shared.c +262 -0
- data/ext/admesh/admesh/src/stl.h +201 -0
- data/ext/admesh/admesh/src/stl_io.c +479 -0
- data/ext/admesh/admesh/src/stlinit.c +377 -0
- data/ext/admesh/admesh/src/util.c +557 -0
- data/ext/admesh/extconf.rb +14 -0
- data/lib/admesh.rb +40 -0
- metadata +84 -0
@@ -0,0 +1,971 @@
|
|
1
|
+
/* ADMesh -- process triangulated solid meshes
|
2
|
+
* Copyright (C) 1995, 1996 Anthony D. Martin <amartin@engr.csulb.edu>
|
3
|
+
* Copyright (C) 2013, 2014 several contributors, see AUTHORS
|
4
|
+
*
|
5
|
+
* This program is free software; you can redistribute it and/or modify
|
6
|
+
* it under the terms of the GNU General Public License as published by
|
7
|
+
* the Free Software Foundation; either version 2 of the License, or
|
8
|
+
* (at your option) any later version.
|
9
|
+
|
10
|
+
* This program is distributed in the hope that it will be useful,
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
* GNU General Public License for more details.
|
14
|
+
|
15
|
+
* You should have received a copy of the GNU General Public License along
|
16
|
+
* with this program; if not, write to the Free Software Foundation, Inc.,
|
17
|
+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
18
|
+
*
|
19
|
+
* Questions, comments, suggestions, etc to
|
20
|
+
* https://github.com/admesh/admesh/issues
|
21
|
+
*/
|
22
|
+
|
23
|
+
#include <stdio.h>
|
24
|
+
#include <stdlib.h>
|
25
|
+
#include <string.h>
|
26
|
+
#include <math.h>
|
27
|
+
|
28
|
+
#include "stl.h"
|
29
|
+
|
30
|
+
|
31
|
+
static void stl_match_neighbors_exact(stl_file *stl,
|
32
|
+
stl_hash_edge *edge_a, stl_hash_edge *edge_b);
|
33
|
+
static void stl_match_neighbors_nearby(stl_file *stl,
|
34
|
+
stl_hash_edge *edge_a, stl_hash_edge *edge_b);
|
35
|
+
static void stl_record_neighbors(stl_file *stl,
|
36
|
+
stl_hash_edge *edge_a, stl_hash_edge *edge_b);
|
37
|
+
static void stl_initialize_facet_check_exact(stl_file *stl);
|
38
|
+
static void stl_initialize_facet_check_nearby(stl_file *stl);
|
39
|
+
static void stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge,
|
40
|
+
stl_vertex *a, stl_vertex *b);
|
41
|
+
static int stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge,
|
42
|
+
stl_vertex *a, stl_vertex *b, float tolerance);
|
43
|
+
static void insert_hash_edge(stl_file *stl, stl_hash_edge edge,
|
44
|
+
void (*match_neighbors)(stl_file *stl,
|
45
|
+
stl_hash_edge *edge_a, stl_hash_edge *edge_b));
|
46
|
+
static int stl_get_hash_for_edge(int M, stl_hash_edge *edge);
|
47
|
+
static int stl_compare_function(stl_hash_edge *edge_a, stl_hash_edge *edge_b);
|
48
|
+
static void stl_free_edges(stl_file *stl);
|
49
|
+
static void stl_remove_facet(stl_file *stl, int facet_number);
|
50
|
+
static void stl_change_vertices(stl_file *stl, int facet_num, int vnot,
|
51
|
+
stl_vertex new_vertex);
|
52
|
+
static void stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a,
|
53
|
+
stl_hash_edge *edge_b, int *facet1, int *vertex1,
|
54
|
+
int *facet2, int *vertex2,
|
55
|
+
stl_vertex *new_vertex1, stl_vertex *new_vertex2);
|
56
|
+
static void stl_remove_degenerate(stl_file *stl, int facet);
|
57
|
+
extern int stl_check_normal_vector(stl_file *stl,
|
58
|
+
int facet_num, int normal_fix_flag);
|
59
|
+
static void stl_update_connects_remove_1(stl_file *stl, int facet_num);
|
60
|
+
|
61
|
+
|
62
|
+
void
|
63
|
+
stl_check_facets_exact(stl_file *stl) {
|
64
|
+
/* This function builds the neighbors list. No modifications are made
|
65
|
+
* to any of the facets. The edges are said to match only if all six
|
66
|
+
* floats of the first edge matches all six floats of the second edge.
|
67
|
+
*/
|
68
|
+
|
69
|
+
stl_hash_edge edge;
|
70
|
+
stl_facet facet;
|
71
|
+
int i;
|
72
|
+
int j;
|
73
|
+
|
74
|
+
if (stl->error) return;
|
75
|
+
|
76
|
+
stl->stats.connected_edges = 0;
|
77
|
+
stl->stats.connected_facets_1_edge = 0;
|
78
|
+
stl->stats.connected_facets_2_edge = 0;
|
79
|
+
stl->stats.connected_facets_3_edge = 0;
|
80
|
+
|
81
|
+
stl_initialize_facet_check_exact(stl);
|
82
|
+
|
83
|
+
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
84
|
+
facet = stl->facet_start[i];
|
85
|
+
|
86
|
+
/* If any two of the three vertices are found to be exactally the same, call them degenerate and remove the facet. */
|
87
|
+
if( !memcmp(&facet.vertex[0], &facet.vertex[1],
|
88
|
+
sizeof(stl_vertex))
|
89
|
+
|| !memcmp(&facet.vertex[1], &facet.vertex[2],
|
90
|
+
sizeof(stl_vertex))
|
91
|
+
|| !memcmp(&facet.vertex[0], &facet.vertex[2],
|
92
|
+
sizeof(stl_vertex))) {
|
93
|
+
stl->stats.degenerate_facets += 1;
|
94
|
+
stl_remove_facet(stl, i);
|
95
|
+
i--;
|
96
|
+
continue;
|
97
|
+
|
98
|
+
}
|
99
|
+
for(j = 0; j < 3; j++) {
|
100
|
+
edge.facet_number = i;
|
101
|
+
edge.which_edge = j;
|
102
|
+
stl_load_edge_exact(stl, &edge, &facet.vertex[j],
|
103
|
+
&facet.vertex[(j + 1) % 3]);
|
104
|
+
|
105
|
+
insert_hash_edge(stl, edge, stl_match_neighbors_exact);
|
106
|
+
}
|
107
|
+
}
|
108
|
+
stl_free_edges(stl);
|
109
|
+
}
|
110
|
+
|
111
|
+
static void
|
112
|
+
stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge,
|
113
|
+
stl_vertex *a, stl_vertex *b) {
|
114
|
+
|
115
|
+
float diff_x;
|
116
|
+
float diff_y;
|
117
|
+
float diff_z;
|
118
|
+
float max_diff;
|
119
|
+
|
120
|
+
if (stl->error) return;
|
121
|
+
|
122
|
+
diff_x = ABS(a->x - b->x);
|
123
|
+
diff_y = ABS(a->y - b->y);
|
124
|
+
diff_z = ABS(a->z - b->z);
|
125
|
+
max_diff = STL_MAX(diff_x, diff_y);
|
126
|
+
max_diff = STL_MAX(diff_z, max_diff);
|
127
|
+
stl->stats.shortest_edge = STL_MIN(max_diff, stl->stats.shortest_edge);
|
128
|
+
|
129
|
+
if(diff_x == max_diff) {
|
130
|
+
if(a->x > b->x) {
|
131
|
+
memcpy(&edge->key[0], a, sizeof(stl_vertex));
|
132
|
+
memcpy(&edge->key[3], b, sizeof(stl_vertex));
|
133
|
+
} else {
|
134
|
+
memcpy(&edge->key[0], b, sizeof(stl_vertex));
|
135
|
+
memcpy(&edge->key[3], a, sizeof(stl_vertex));
|
136
|
+
edge->which_edge += 3; /* this edge is loaded backwards */
|
137
|
+
}
|
138
|
+
} else if(diff_y == max_diff) {
|
139
|
+
if(a->y > b->y) {
|
140
|
+
memcpy(&edge->key[0], a, sizeof(stl_vertex));
|
141
|
+
memcpy(&edge->key[3], b, sizeof(stl_vertex));
|
142
|
+
} else {
|
143
|
+
memcpy(&edge->key[0], b, sizeof(stl_vertex));
|
144
|
+
memcpy(&edge->key[3], a, sizeof(stl_vertex));
|
145
|
+
edge->which_edge += 3; /* this edge is loaded backwards */
|
146
|
+
}
|
147
|
+
} else {
|
148
|
+
if(a->z > b->z) {
|
149
|
+
memcpy(&edge->key[0], a, sizeof(stl_vertex));
|
150
|
+
memcpy(&edge->key[3], b, sizeof(stl_vertex));
|
151
|
+
} else {
|
152
|
+
memcpy(&edge->key[0], b, sizeof(stl_vertex));
|
153
|
+
memcpy(&edge->key[3], a, sizeof(stl_vertex));
|
154
|
+
edge->which_edge += 3; /* this edge is loaded backwards */
|
155
|
+
}
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
static void
|
160
|
+
stl_initialize_facet_check_exact(stl_file *stl) {
|
161
|
+
int i;
|
162
|
+
|
163
|
+
if (stl->error) return;
|
164
|
+
|
165
|
+
stl->stats.malloced = 0;
|
166
|
+
stl->stats.freed = 0;
|
167
|
+
stl->stats.collisions = 0;
|
168
|
+
|
169
|
+
|
170
|
+
stl->M = 81397;
|
171
|
+
|
172
|
+
for(i = 0; i < stl->stats.number_of_facets ; i++) {
|
173
|
+
/* initialize neighbors list to -1 to mark unconnected edges */
|
174
|
+
stl->neighbors_start[i].neighbor[0] = -1;
|
175
|
+
stl->neighbors_start[i].neighbor[1] = -1;
|
176
|
+
stl->neighbors_start[i].neighbor[2] = -1;
|
177
|
+
}
|
178
|
+
|
179
|
+
stl->heads = (stl_hash_edge**)calloc(stl->M, sizeof(*stl->heads));
|
180
|
+
if(stl->heads == NULL) perror("stl_initialize_facet_check_exact");
|
181
|
+
|
182
|
+
stl->tail = (stl_hash_edge*)malloc(sizeof(stl_hash_edge));
|
183
|
+
if(stl->tail == NULL) perror("stl_initialize_facet_check_exact");
|
184
|
+
|
185
|
+
stl->tail->next = stl->tail;
|
186
|
+
|
187
|
+
for(i = 0; i < stl->M; i++) {
|
188
|
+
stl->heads[i] = stl->tail;
|
189
|
+
}
|
190
|
+
}
|
191
|
+
|
192
|
+
static void
|
193
|
+
insert_hash_edge(stl_file *stl, stl_hash_edge edge,
|
194
|
+
void (*match_neighbors)(stl_file *stl,
|
195
|
+
stl_hash_edge *edge_a, stl_hash_edge *edge_b)) {
|
196
|
+
stl_hash_edge *link;
|
197
|
+
stl_hash_edge *new_edge;
|
198
|
+
stl_hash_edge *temp;
|
199
|
+
int chain_number;
|
200
|
+
|
201
|
+
if (stl->error) return;
|
202
|
+
|
203
|
+
chain_number = stl_get_hash_for_edge(stl->M, &edge);
|
204
|
+
|
205
|
+
link = stl->heads[chain_number];
|
206
|
+
|
207
|
+
if(link == stl->tail) {
|
208
|
+
/* This list doesn't have any edges currently in it. Add this one. */
|
209
|
+
new_edge = (stl_hash_edge*)malloc(sizeof(stl_hash_edge));
|
210
|
+
if(new_edge == NULL) perror("insert_hash_edge");
|
211
|
+
stl->stats.malloced++;
|
212
|
+
*new_edge = edge;
|
213
|
+
new_edge->next = stl->tail;
|
214
|
+
stl->heads[chain_number] = new_edge;
|
215
|
+
return;
|
216
|
+
} else if(!stl_compare_function(&edge, link)) {
|
217
|
+
/* This is a match. Record result in neighbors list. */
|
218
|
+
match_neighbors(stl, &edge, link);
|
219
|
+
/* Delete the matched edge from the list. */
|
220
|
+
stl->heads[chain_number] = link->next;
|
221
|
+
free(link);
|
222
|
+
stl->stats.freed++;
|
223
|
+
return;
|
224
|
+
} else {
|
225
|
+
/* Continue through the rest of the list */
|
226
|
+
for(;;) {
|
227
|
+
if(link->next == stl->tail) {
|
228
|
+
/* This is the last item in the list. Insert a new edge. */
|
229
|
+
new_edge = (stl_hash_edge*)malloc(sizeof(stl_hash_edge));
|
230
|
+
if(new_edge == NULL) perror("insert_hash_edge");
|
231
|
+
stl->stats.malloced++;
|
232
|
+
*new_edge = edge;
|
233
|
+
new_edge->next = stl->tail;
|
234
|
+
link->next = new_edge;
|
235
|
+
stl->stats.collisions++;
|
236
|
+
return;
|
237
|
+
} else if(!stl_compare_function(&edge, link->next)) {
|
238
|
+
/* This is a match. Record result in neighbors list. */
|
239
|
+
match_neighbors(stl, &edge, link->next);
|
240
|
+
|
241
|
+
/* Delete the matched edge from the list. */
|
242
|
+
temp = link->next;
|
243
|
+
link->next = link->next->next;
|
244
|
+
free(temp);
|
245
|
+
stl->stats.freed++;
|
246
|
+
return;
|
247
|
+
} else {
|
248
|
+
/* This is not a match. Go to the next link */
|
249
|
+
link = link->next;
|
250
|
+
stl->stats.collisions++;
|
251
|
+
}
|
252
|
+
}
|
253
|
+
}
|
254
|
+
}
|
255
|
+
|
256
|
+
|
257
|
+
static int
|
258
|
+
stl_get_hash_for_edge(int M, stl_hash_edge *edge) {
|
259
|
+
return ((edge->key[0] / 23 + edge->key[1] / 19 + edge->key[2] / 17
|
260
|
+
+ edge->key[3] /13 + edge->key[4] / 11 + edge->key[5] / 7 ) % M);
|
261
|
+
}
|
262
|
+
|
263
|
+
static int
|
264
|
+
stl_compare_function(stl_hash_edge *edge_a, stl_hash_edge *edge_b) {
|
265
|
+
if(edge_a->facet_number == edge_b->facet_number) {
|
266
|
+
return 1; /* Don't match edges of the same facet */
|
267
|
+
} else {
|
268
|
+
return memcmp(edge_a, edge_b, SIZEOF_EDGE_SORT);
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
void
|
273
|
+
stl_check_facets_nearby(stl_file *stl, float tolerance) {
|
274
|
+
stl_hash_edge edge[3];
|
275
|
+
stl_facet facet;
|
276
|
+
int i;
|
277
|
+
int j;
|
278
|
+
|
279
|
+
if (stl->error) return;
|
280
|
+
|
281
|
+
if( (stl->stats.connected_facets_1_edge == stl->stats.number_of_facets)
|
282
|
+
&& (stl->stats.connected_facets_2_edge == stl->stats.number_of_facets)
|
283
|
+
&& (stl->stats.connected_facets_3_edge == stl->stats.number_of_facets)) {
|
284
|
+
/* No need to check any further. All facets are connected */
|
285
|
+
return;
|
286
|
+
}
|
287
|
+
|
288
|
+
stl_initialize_facet_check_nearby(stl);
|
289
|
+
|
290
|
+
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
291
|
+
facet = stl->facet_start[i];
|
292
|
+
for(j = 0; j < 3; j++) {
|
293
|
+
if(stl->neighbors_start[i].neighbor[j] == -1) {
|
294
|
+
edge[j].facet_number = i;
|
295
|
+
edge[j].which_edge = j;
|
296
|
+
if(stl_load_edge_nearby(stl, &edge[j], &facet.vertex[j],
|
297
|
+
&facet.vertex[(j + 1) % 3],
|
298
|
+
tolerance)) {
|
299
|
+
/* only insert edges that have different keys */
|
300
|
+
insert_hash_edge(stl, edge[j], stl_match_neighbors_nearby);
|
301
|
+
}
|
302
|
+
}
|
303
|
+
}
|
304
|
+
}
|
305
|
+
|
306
|
+
stl_free_edges(stl);
|
307
|
+
}
|
308
|
+
|
309
|
+
static int
|
310
|
+
stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge,
|
311
|
+
stl_vertex *a, stl_vertex *b, float tolerance) {
|
312
|
+
float diff_x;
|
313
|
+
float diff_y;
|
314
|
+
float diff_z;
|
315
|
+
float max_diff;
|
316
|
+
unsigned vertex1[3];
|
317
|
+
unsigned vertex2[3];
|
318
|
+
|
319
|
+
|
320
|
+
diff_x = ABS(a->x - b->x);
|
321
|
+
diff_y = ABS(a->y - b->y);
|
322
|
+
diff_z = ABS(a->z - b->z);
|
323
|
+
max_diff = STL_MAX(diff_x, diff_y);
|
324
|
+
max_diff = STL_MAX(diff_z, max_diff);
|
325
|
+
|
326
|
+
vertex1[0] = (unsigned)((a->x - stl->stats.min.x) / tolerance);
|
327
|
+
vertex1[1] = (unsigned)((a->y - stl->stats.min.y) / tolerance);
|
328
|
+
vertex1[2] = (unsigned)((a->z - stl->stats.min.z) / tolerance);
|
329
|
+
vertex2[0] = (unsigned)((b->x - stl->stats.min.x) / tolerance);
|
330
|
+
vertex2[1] = (unsigned)((b->y - stl->stats.min.y) / tolerance);
|
331
|
+
vertex2[2] = (unsigned)((b->z - stl->stats.min.z) / tolerance);
|
332
|
+
|
333
|
+
if( (vertex1[0] == vertex2[0])
|
334
|
+
&& (vertex1[1] == vertex2[1])
|
335
|
+
&& (vertex1[2] == vertex2[2])) {
|
336
|
+
/* Both vertices hash to the same value */
|
337
|
+
return 0;
|
338
|
+
}
|
339
|
+
|
340
|
+
if(diff_x == max_diff) {
|
341
|
+
if(a->x > b->x) {
|
342
|
+
memcpy(&edge->key[0], vertex1, sizeof(stl_vertex));
|
343
|
+
memcpy(&edge->key[3], vertex2, sizeof(stl_vertex));
|
344
|
+
} else {
|
345
|
+
memcpy(&edge->key[0], vertex2, sizeof(stl_vertex));
|
346
|
+
memcpy(&edge->key[3], vertex1, sizeof(stl_vertex));
|
347
|
+
edge->which_edge += 3; /* this edge is loaded backwards */
|
348
|
+
}
|
349
|
+
} else if(diff_y == max_diff) {
|
350
|
+
if(a->y > b->y) {
|
351
|
+
memcpy(&edge->key[0], vertex1, sizeof(stl_vertex));
|
352
|
+
memcpy(&edge->key[3], vertex2, sizeof(stl_vertex));
|
353
|
+
} else {
|
354
|
+
memcpy(&edge->key[0], vertex2, sizeof(stl_vertex));
|
355
|
+
memcpy(&edge->key[3], vertex1, sizeof(stl_vertex));
|
356
|
+
edge->which_edge += 3; /* this edge is loaded backwards */
|
357
|
+
}
|
358
|
+
} else {
|
359
|
+
if(a->z > b->z) {
|
360
|
+
memcpy(&edge->key[0], vertex1, sizeof(stl_vertex));
|
361
|
+
memcpy(&edge->key[3], vertex2, sizeof(stl_vertex));
|
362
|
+
} else {
|
363
|
+
memcpy(&edge->key[0], vertex2, sizeof(stl_vertex));
|
364
|
+
memcpy(&edge->key[3], vertex1, sizeof(stl_vertex));
|
365
|
+
edge->which_edge += 3; /* this edge is loaded backwards */
|
366
|
+
}
|
367
|
+
}
|
368
|
+
return 1;
|
369
|
+
}
|
370
|
+
|
371
|
+
static void
|
372
|
+
stl_free_edges(stl_file *stl) {
|
373
|
+
int i;
|
374
|
+
stl_hash_edge *temp;
|
375
|
+
|
376
|
+
if (stl->error) return;
|
377
|
+
|
378
|
+
if(stl->stats.malloced != stl->stats.freed) {
|
379
|
+
for(i = 0; i < stl->M; i++) {
|
380
|
+
for(temp = stl->heads[i]; stl->heads[i] != stl->tail;
|
381
|
+
temp = stl->heads[i]) {
|
382
|
+
stl->heads[i] = stl->heads[i]->next;
|
383
|
+
free(temp);
|
384
|
+
stl->stats.freed++;
|
385
|
+
}
|
386
|
+
}
|
387
|
+
}
|
388
|
+
free(stl->heads);
|
389
|
+
free(stl->tail);
|
390
|
+
}
|
391
|
+
|
392
|
+
static void
|
393
|
+
stl_initialize_facet_check_nearby(stl_file *stl) {
|
394
|
+
int i;
|
395
|
+
|
396
|
+
if (stl->error) return;
|
397
|
+
|
398
|
+
stl->stats.malloced = 0;
|
399
|
+
stl->stats.freed = 0;
|
400
|
+
stl->stats.collisions = 0;
|
401
|
+
|
402
|
+
/* tolerance = STL_MAX(stl->stats.shortest_edge, tolerance);*/
|
403
|
+
/* tolerance = STL_MAX((stl->stats.bounding_diameter / 500000.0), tolerance);*/
|
404
|
+
/* tolerance *= 0.5;*/
|
405
|
+
|
406
|
+
stl->M = 81397;
|
407
|
+
|
408
|
+
stl->heads = (stl_hash_edge**)calloc(stl->M, sizeof(*stl->heads));
|
409
|
+
if(stl->heads == NULL) perror("stl_initialize_facet_check_nearby");
|
410
|
+
|
411
|
+
stl->tail = (stl_hash_edge*)malloc(sizeof(stl_hash_edge));
|
412
|
+
if(stl->tail == NULL) perror("stl_initialize_facet_check_nearby");
|
413
|
+
|
414
|
+
stl->tail->next = stl->tail;
|
415
|
+
|
416
|
+
for(i = 0; i < stl->M; i++) {
|
417
|
+
stl->heads[i] = stl->tail;
|
418
|
+
}
|
419
|
+
}
|
420
|
+
|
421
|
+
|
422
|
+
|
423
|
+
static void
|
424
|
+
stl_record_neighbors(stl_file *stl,
|
425
|
+
stl_hash_edge *edge_a, stl_hash_edge *edge_b) {
|
426
|
+
int i;
|
427
|
+
int j;
|
428
|
+
|
429
|
+
if (stl->error) return;
|
430
|
+
|
431
|
+
/* Facet a's neighbor is facet b */
|
432
|
+
stl->neighbors_start[edge_a->facet_number].neighbor[edge_a->which_edge % 3] =
|
433
|
+
edge_b->facet_number; /* sets the .neighbor part */
|
434
|
+
|
435
|
+
stl->neighbors_start[edge_a->facet_number].
|
436
|
+
which_vertex_not[edge_a->which_edge % 3] =
|
437
|
+
(edge_b->which_edge + 2) % 3; /* sets the .which_vertex_not part */
|
438
|
+
|
439
|
+
/* Facet b's neighbor is facet a */
|
440
|
+
stl->neighbors_start[edge_b->facet_number].neighbor[edge_b->which_edge % 3] =
|
441
|
+
edge_a->facet_number; /* sets the .neighbor part */
|
442
|
+
|
443
|
+
stl->neighbors_start[edge_b->facet_number].
|
444
|
+
which_vertex_not[edge_b->which_edge % 3] =
|
445
|
+
(edge_a->which_edge + 2) % 3; /* sets the .which_vertex_not part */
|
446
|
+
|
447
|
+
if( ((edge_a->which_edge < 3) && (edge_b->which_edge < 3))
|
448
|
+
|| ((edge_a->which_edge > 2) && (edge_b->which_edge > 2))) {
|
449
|
+
/* these facets are oriented in opposite directions. */
|
450
|
+
/* their normals are probably messed up. */
|
451
|
+
stl->neighbors_start[edge_a->facet_number].
|
452
|
+
which_vertex_not[edge_a->which_edge % 3] += 3;
|
453
|
+
stl->neighbors_start[edge_b->facet_number].
|
454
|
+
which_vertex_not[edge_b->which_edge % 3] += 3;
|
455
|
+
}
|
456
|
+
|
457
|
+
|
458
|
+
/* Count successful connects */
|
459
|
+
/* Total connects */
|
460
|
+
stl->stats.connected_edges += 2;
|
461
|
+
/* Count individual connects */
|
462
|
+
i = ((stl->neighbors_start[edge_a->facet_number].neighbor[0] == -1) +
|
463
|
+
(stl->neighbors_start[edge_a->facet_number].neighbor[1] == -1) +
|
464
|
+
(stl->neighbors_start[edge_a->facet_number].neighbor[2] == -1));
|
465
|
+
j = ((stl->neighbors_start[edge_b->facet_number].neighbor[0] == -1) +
|
466
|
+
(stl->neighbors_start[edge_b->facet_number].neighbor[1] == -1) +
|
467
|
+
(stl->neighbors_start[edge_b->facet_number].neighbor[2] == -1));
|
468
|
+
if(i == 2) {
|
469
|
+
stl->stats.connected_facets_1_edge +=1;
|
470
|
+
} else if(i == 1) {
|
471
|
+
stl->stats.connected_facets_2_edge +=1;
|
472
|
+
} else {
|
473
|
+
stl->stats.connected_facets_3_edge +=1;
|
474
|
+
}
|
475
|
+
if(j == 2) {
|
476
|
+
stl->stats.connected_facets_1_edge +=1;
|
477
|
+
} else if(j == 1) {
|
478
|
+
stl->stats.connected_facets_2_edge +=1;
|
479
|
+
} else {
|
480
|
+
stl->stats.connected_facets_3_edge +=1;
|
481
|
+
}
|
482
|
+
}
|
483
|
+
|
484
|
+
static void
|
485
|
+
stl_match_neighbors_exact(stl_file *stl,
|
486
|
+
stl_hash_edge *edge_a, stl_hash_edge *edge_b) {
|
487
|
+
if (stl->error) return;
|
488
|
+
stl_record_neighbors(stl, edge_a, edge_b);
|
489
|
+
}
|
490
|
+
|
491
|
+
static void
|
492
|
+
stl_match_neighbors_nearby(stl_file *stl,
|
493
|
+
stl_hash_edge *edge_a, stl_hash_edge *edge_b) {
|
494
|
+
int facet1;
|
495
|
+
int facet2;
|
496
|
+
int vertex1;
|
497
|
+
int vertex2;
|
498
|
+
int vnot1;
|
499
|
+
int vnot2;
|
500
|
+
stl_vertex new_vertex1;
|
501
|
+
stl_vertex new_vertex2;
|
502
|
+
|
503
|
+
if (stl->error) return;
|
504
|
+
|
505
|
+
stl_record_neighbors(stl, edge_a, edge_b);
|
506
|
+
stl_which_vertices_to_change(stl, edge_a, edge_b, &facet1, &vertex1,
|
507
|
+
&facet2, &vertex2, &new_vertex1, &new_vertex2);
|
508
|
+
if(facet1 != -1) {
|
509
|
+
if(facet1 == edge_a->facet_number) {
|
510
|
+
vnot1 = (edge_a->which_edge + 2) % 3;
|
511
|
+
} else {
|
512
|
+
vnot1 = (edge_b->which_edge + 2) % 3;
|
513
|
+
}
|
514
|
+
if(((vnot1 + 2) % 3) == vertex1) {
|
515
|
+
vnot1 += 3;
|
516
|
+
}
|
517
|
+
stl_change_vertices(stl, facet1, vnot1, new_vertex1);
|
518
|
+
}
|
519
|
+
if(facet2 != -1) {
|
520
|
+
if(facet2 == edge_a->facet_number) {
|
521
|
+
vnot2 = (edge_a->which_edge + 2) % 3;
|
522
|
+
} else {
|
523
|
+
vnot2 = (edge_b->which_edge + 2) % 3;
|
524
|
+
}
|
525
|
+
if(((vnot2 + 2) % 3) == vertex2) {
|
526
|
+
vnot2 += 3;
|
527
|
+
}
|
528
|
+
stl_change_vertices(stl, facet2, vnot2, new_vertex2);
|
529
|
+
}
|
530
|
+
stl->stats.edges_fixed += 2;
|
531
|
+
}
|
532
|
+
|
533
|
+
|
534
|
+
static void
|
535
|
+
stl_change_vertices(stl_file *stl, int facet_num, int vnot,
|
536
|
+
stl_vertex new_vertex) {
|
537
|
+
int first_facet;
|
538
|
+
int direction;
|
539
|
+
int next_edge;
|
540
|
+
int pivot_vertex;
|
541
|
+
|
542
|
+
if (stl->error) return;
|
543
|
+
|
544
|
+
first_facet = facet_num;
|
545
|
+
direction = 0;
|
546
|
+
|
547
|
+
for(;;) {
|
548
|
+
if(vnot > 2) {
|
549
|
+
if(direction == 0) {
|
550
|
+
pivot_vertex = (vnot + 2) % 3;
|
551
|
+
next_edge = pivot_vertex;
|
552
|
+
direction = 1;
|
553
|
+
} else {
|
554
|
+
pivot_vertex = (vnot + 1) % 3;
|
555
|
+
next_edge = vnot % 3;
|
556
|
+
direction = 0;
|
557
|
+
}
|
558
|
+
} else {
|
559
|
+
if(direction == 0) {
|
560
|
+
pivot_vertex = (vnot + 1) % 3;
|
561
|
+
next_edge = vnot;
|
562
|
+
} else {
|
563
|
+
pivot_vertex = (vnot + 2) % 3;
|
564
|
+
next_edge = pivot_vertex;
|
565
|
+
}
|
566
|
+
}
|
567
|
+
stl->facet_start[facet_num].vertex[pivot_vertex] = new_vertex;
|
568
|
+
vnot = stl->neighbors_start[facet_num].which_vertex_not[next_edge];
|
569
|
+
facet_num = stl->neighbors_start[facet_num].neighbor[next_edge];
|
570
|
+
|
571
|
+
if(facet_num == -1) {
|
572
|
+
break;
|
573
|
+
}
|
574
|
+
|
575
|
+
if(facet_num == first_facet) {
|
576
|
+
/* back to the beginning */
|
577
|
+
printf("\
|
578
|
+
Back to the first facet changing vertices: probably a mobius part.\n\
|
579
|
+
Try using a smaller tolerance or don't do a nearby check\n");
|
580
|
+
return;
|
581
|
+
}
|
582
|
+
}
|
583
|
+
}
|
584
|
+
|
585
|
+
|
586
|
+
static void
|
587
|
+
stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a,
|
588
|
+
stl_hash_edge *edge_b, int *facet1, int *vertex1,
|
589
|
+
int *facet2, int *vertex2,
|
590
|
+
stl_vertex *new_vertex1, stl_vertex *new_vertex2) {
|
591
|
+
int v1a; /* pair 1, facet a */
|
592
|
+
int v1b; /* pair 1, facet b */
|
593
|
+
int v2a; /* pair 2, facet a */
|
594
|
+
int v2b; /* pair 2, facet b */
|
595
|
+
|
596
|
+
/* Find first pair */
|
597
|
+
if(edge_a->which_edge < 3) {
|
598
|
+
v1a = edge_a->which_edge;
|
599
|
+
v2a = (edge_a->which_edge + 1) % 3;
|
600
|
+
} else {
|
601
|
+
v2a = edge_a->which_edge % 3;
|
602
|
+
v1a = (edge_a->which_edge + 1) % 3;
|
603
|
+
}
|
604
|
+
if(edge_b->which_edge < 3) {
|
605
|
+
v1b = edge_b->which_edge;
|
606
|
+
v2b = (edge_b->which_edge + 1) % 3;
|
607
|
+
} else {
|
608
|
+
v2b = edge_b->which_edge % 3;
|
609
|
+
v1b = (edge_b->which_edge + 1) % 3;
|
610
|
+
}
|
611
|
+
|
612
|
+
/* Of the first pair, which vertex, if any, should be changed */
|
613
|
+
if(!memcmp(&stl->facet_start[edge_a->facet_number].vertex[v1a],
|
614
|
+
&stl->facet_start[edge_b->facet_number].vertex[v1b],
|
615
|
+
sizeof(stl_vertex))) {
|
616
|
+
/* These facets are already equal. No need to change. */
|
617
|
+
*facet1 = -1;
|
618
|
+
} else {
|
619
|
+
if( (stl->neighbors_start[edge_a->facet_number].neighbor[v1a] == -1)
|
620
|
+
&& (stl->neighbors_start[edge_a->facet_number].
|
621
|
+
neighbor[(v1a + 2) % 3] == -1)) {
|
622
|
+
/* This vertex has no neighbors. This is a good one to change */
|
623
|
+
*facet1 = edge_a->facet_number;
|
624
|
+
*vertex1 = v1a;
|
625
|
+
*new_vertex1 = stl->facet_start[edge_b->facet_number].vertex[v1b];
|
626
|
+
} else {
|
627
|
+
*facet1 = edge_b->facet_number;
|
628
|
+
*vertex1 = v1b;
|
629
|
+
*new_vertex1 = stl->facet_start[edge_a->facet_number].vertex[v1a];
|
630
|
+
}
|
631
|
+
}
|
632
|
+
|
633
|
+
/* Of the second pair, which vertex, if any, should be changed */
|
634
|
+
if(!memcmp(&stl->facet_start[edge_a->facet_number].vertex[v2a],
|
635
|
+
&stl->facet_start[edge_b->facet_number].vertex[v2b],
|
636
|
+
sizeof(stl_vertex))) {
|
637
|
+
/* These facets are already equal. No need to change. */
|
638
|
+
*facet2 = -1;
|
639
|
+
} else {
|
640
|
+
if( (stl->neighbors_start[edge_a->facet_number].neighbor[v2a] == -1)
|
641
|
+
&& (stl->neighbors_start[edge_a->facet_number].
|
642
|
+
neighbor[(v2a + 2) % 3] == -1)) {
|
643
|
+
/* This vertex has no neighbors. This is a good one to change */
|
644
|
+
*facet2 = edge_a->facet_number;
|
645
|
+
*vertex2 = v2a;
|
646
|
+
*new_vertex2 = stl->facet_start[edge_b->facet_number].vertex[v2b];
|
647
|
+
} else {
|
648
|
+
*facet2 = edge_b->facet_number;
|
649
|
+
*vertex2 = v2b;
|
650
|
+
*new_vertex2 = stl->facet_start[edge_a->facet_number].vertex[v2a];
|
651
|
+
}
|
652
|
+
}
|
653
|
+
}
|
654
|
+
|
655
|
+
static void
|
656
|
+
stl_remove_facet(stl_file *stl, int facet_number) {
|
657
|
+
int neighbor[3];
|
658
|
+
int vnot[3];
|
659
|
+
int i;
|
660
|
+
int j;
|
661
|
+
|
662
|
+
if (stl->error) return;
|
663
|
+
|
664
|
+
stl->stats.facets_removed += 1;
|
665
|
+
/* Update list of connected edges */
|
666
|
+
j = ((stl->neighbors_start[facet_number].neighbor[0] == -1) +
|
667
|
+
(stl->neighbors_start[facet_number].neighbor[1] == -1) +
|
668
|
+
(stl->neighbors_start[facet_number].neighbor[2] == -1));
|
669
|
+
if(j == 2) {
|
670
|
+
stl->stats.connected_facets_1_edge -= 1;
|
671
|
+
} else if(j == 1) {
|
672
|
+
stl->stats.connected_facets_2_edge -= 1;
|
673
|
+
stl->stats.connected_facets_1_edge -= 1;
|
674
|
+
} else if(j == 0) {
|
675
|
+
stl->stats.connected_facets_3_edge -= 1;
|
676
|
+
stl->stats.connected_facets_2_edge -= 1;
|
677
|
+
stl->stats.connected_facets_1_edge -= 1;
|
678
|
+
}
|
679
|
+
|
680
|
+
stl->facet_start[facet_number] =
|
681
|
+
stl->facet_start[stl->stats.number_of_facets - 1];
|
682
|
+
/* I could reallocate at this point, but it is not really necessary. */
|
683
|
+
stl->neighbors_start[facet_number] =
|
684
|
+
stl->neighbors_start[stl->stats.number_of_facets - 1];
|
685
|
+
stl->stats.number_of_facets -= 1;
|
686
|
+
|
687
|
+
for(i = 0; i < 3; i++) {
|
688
|
+
neighbor[i] = stl->neighbors_start[facet_number].neighbor[i];
|
689
|
+
vnot[i] = stl->neighbors_start[facet_number].which_vertex_not[i];
|
690
|
+
}
|
691
|
+
|
692
|
+
for(i = 0; i < 3; i++) {
|
693
|
+
if(neighbor[i] != -1) {
|
694
|
+
if(stl->neighbors_start[neighbor[i]].neighbor[(vnot[i] + 1)% 3] !=
|
695
|
+
stl->stats.number_of_facets) {
|
696
|
+
printf("\
|
697
|
+
in stl_remove_facet: neighbor = %d numfacets = %d this is wrong\n",
|
698
|
+
stl->neighbors_start[neighbor[i]].neighbor[(vnot[i] + 1)% 3],
|
699
|
+
stl->stats.number_of_facets);
|
700
|
+
return;
|
701
|
+
}
|
702
|
+
stl->neighbors_start[neighbor[i]].neighbor[(vnot[i] + 1)% 3]
|
703
|
+
= facet_number;
|
704
|
+
}
|
705
|
+
}
|
706
|
+
}
|
707
|
+
|
708
|
+
void
|
709
|
+
stl_remove_unconnected_facets(stl_file *stl) {
|
710
|
+
/* A couple of things need to be done here. One is to remove any */
|
711
|
+
/* completely unconnected facets (0 edges connected) since these are */
|
712
|
+
/* useless and could be completely wrong. The second thing that needs to */
|
713
|
+
/* be done is to remove any degenerate facets that were created during */
|
714
|
+
/* stl_check_facets_nearby(). */
|
715
|
+
|
716
|
+
int i;
|
717
|
+
|
718
|
+
if (stl->error) return;
|
719
|
+
|
720
|
+
/* remove degenerate facets */
|
721
|
+
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
722
|
+
if( !memcmp(&stl->facet_start[i].vertex[0],
|
723
|
+
&stl->facet_start[i].vertex[1], sizeof(stl_vertex))
|
724
|
+
|| !memcmp(&stl->facet_start[i].vertex[1],
|
725
|
+
&stl->facet_start[i].vertex[2], sizeof(stl_vertex))
|
726
|
+
|| !memcmp(&stl->facet_start[i].vertex[0],
|
727
|
+
&stl->facet_start[i].vertex[2], sizeof(stl_vertex))) {
|
728
|
+
stl_remove_degenerate(stl, i);
|
729
|
+
i--;
|
730
|
+
}
|
731
|
+
}
|
732
|
+
|
733
|
+
if(stl->stats.connected_facets_1_edge < stl->stats.number_of_facets) {
|
734
|
+
/* remove completely unconnected facets */
|
735
|
+
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
736
|
+
if( (stl->neighbors_start[i].neighbor[0] == -1)
|
737
|
+
&& (stl->neighbors_start[i].neighbor[1] == -1)
|
738
|
+
&& (stl->neighbors_start[i].neighbor[2] == -1)) {
|
739
|
+
/* This facet is completely unconnected. Remove it. */
|
740
|
+
stl_remove_facet(stl, i);
|
741
|
+
i--;
|
742
|
+
}
|
743
|
+
}
|
744
|
+
}
|
745
|
+
}
|
746
|
+
|
747
|
+
static void
|
748
|
+
stl_remove_degenerate(stl_file *stl, int facet) {
|
749
|
+
int edge1;
|
750
|
+
int edge2;
|
751
|
+
int edge3;
|
752
|
+
int neighbor1;
|
753
|
+
int neighbor2;
|
754
|
+
int neighbor3;
|
755
|
+
int vnot1;
|
756
|
+
int vnot2;
|
757
|
+
int vnot3;
|
758
|
+
|
759
|
+
if (stl->error) return;
|
760
|
+
|
761
|
+
if( !memcmp(&stl->facet_start[facet].vertex[0],
|
762
|
+
&stl->facet_start[facet].vertex[1], sizeof(stl_vertex))
|
763
|
+
&& !memcmp(&stl->facet_start[facet].vertex[1],
|
764
|
+
&stl->facet_start[facet].vertex[2], sizeof(stl_vertex))) {
|
765
|
+
/* all 3 vertices are equal. Just remove the facet. I don't think*/
|
766
|
+
/* this is really possible, but just in case... */
|
767
|
+
printf("removing a facet in stl_remove_degenerate\n");
|
768
|
+
|
769
|
+
stl_remove_facet(stl, facet);
|
770
|
+
return;
|
771
|
+
}
|
772
|
+
|
773
|
+
if(!memcmp(&stl->facet_start[facet].vertex[0],
|
774
|
+
&stl->facet_start[facet].vertex[1], sizeof(stl_vertex))) {
|
775
|
+
edge1 = 1;
|
776
|
+
edge2 = 2;
|
777
|
+
edge3 = 0;
|
778
|
+
} else if(!memcmp(&stl->facet_start[facet].vertex[1],
|
779
|
+
&stl->facet_start[facet].vertex[2], sizeof(stl_vertex))) {
|
780
|
+
edge1 = 0;
|
781
|
+
edge2 = 2;
|
782
|
+
edge3 = 1;
|
783
|
+
} else if(!memcmp(&stl->facet_start[facet].vertex[2],
|
784
|
+
&stl->facet_start[facet].vertex[0], sizeof(stl_vertex))) {
|
785
|
+
edge1 = 0;
|
786
|
+
edge2 = 1;
|
787
|
+
edge3 = 2;
|
788
|
+
} else {
|
789
|
+
/* No degenerate. Function shouldn't have been called. */
|
790
|
+
return;
|
791
|
+
}
|
792
|
+
neighbor1 = stl->neighbors_start[facet].neighbor[edge1];
|
793
|
+
neighbor2 = stl->neighbors_start[facet].neighbor[edge2];
|
794
|
+
|
795
|
+
if(neighbor1 == -1) {
|
796
|
+
stl_update_connects_remove_1(stl, neighbor2);
|
797
|
+
}
|
798
|
+
if(neighbor2 == -1) {
|
799
|
+
stl_update_connects_remove_1(stl, neighbor1);
|
800
|
+
}
|
801
|
+
|
802
|
+
|
803
|
+
neighbor3 = stl->neighbors_start[facet].neighbor[edge3];
|
804
|
+
vnot1 = stl->neighbors_start[facet].which_vertex_not[edge1];
|
805
|
+
vnot2 = stl->neighbors_start[facet].which_vertex_not[edge2];
|
806
|
+
vnot3 = stl->neighbors_start[facet].which_vertex_not[edge3];
|
807
|
+
|
808
|
+
stl->neighbors_start[neighbor1].neighbor[(vnot1 + 1) % 3] = neighbor2;
|
809
|
+
stl->neighbors_start[neighbor2].neighbor[(vnot2 + 1) % 3] = neighbor1;
|
810
|
+
stl->neighbors_start[neighbor1].which_vertex_not[(vnot1 + 1) % 3] = vnot2;
|
811
|
+
stl->neighbors_start[neighbor2].which_vertex_not[(vnot2 + 1) % 3] = vnot1;
|
812
|
+
|
813
|
+
stl_remove_facet(stl, facet);
|
814
|
+
|
815
|
+
if(neighbor3 != -1) {
|
816
|
+
stl_update_connects_remove_1(stl, neighbor3);
|
817
|
+
stl->neighbors_start[neighbor3].neighbor[(vnot3 + 1) % 3] = -1;
|
818
|
+
}
|
819
|
+
}
|
820
|
+
|
821
|
+
void
|
822
|
+
stl_update_connects_remove_1(stl_file *stl, int facet_num) {
|
823
|
+
int j;
|
824
|
+
|
825
|
+
if (stl->error) return;
|
826
|
+
/* Update list of connected edges */
|
827
|
+
j = ((stl->neighbors_start[facet_num].neighbor[0] == -1) +
|
828
|
+
(stl->neighbors_start[facet_num].neighbor[1] == -1) +
|
829
|
+
(stl->neighbors_start[facet_num].neighbor[2] == -1));
|
830
|
+
if(j == 0) { /* Facet has 3 neighbors */
|
831
|
+
stl->stats.connected_facets_3_edge -= 1;
|
832
|
+
} else if(j == 1) { /* Facet has 2 neighbors */
|
833
|
+
stl->stats.connected_facets_2_edge -= 1;
|
834
|
+
} else if(j == 2) { /* Facet has 1 neighbor */
|
835
|
+
stl->stats.connected_facets_1_edge -= 1;
|
836
|
+
}
|
837
|
+
}
|
838
|
+
|
839
|
+
void
|
840
|
+
stl_fill_holes(stl_file *stl) {
|
841
|
+
stl_facet facet;
|
842
|
+
stl_facet new_facet;
|
843
|
+
int neighbors_initial[3];
|
844
|
+
stl_hash_edge edge;
|
845
|
+
int first_facet;
|
846
|
+
int direction;
|
847
|
+
int facet_num;
|
848
|
+
int vnot;
|
849
|
+
int next_edge;
|
850
|
+
int pivot_vertex;
|
851
|
+
int next_facet;
|
852
|
+
int i;
|
853
|
+
int j;
|
854
|
+
int k;
|
855
|
+
|
856
|
+
if (stl->error) return;
|
857
|
+
|
858
|
+
/* Insert all unconnected edges into hash list */
|
859
|
+
stl_initialize_facet_check_nearby(stl);
|
860
|
+
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
861
|
+
facet = stl->facet_start[i];
|
862
|
+
for(j = 0; j < 3; j++) {
|
863
|
+
if(stl->neighbors_start[i].neighbor[j] != -1) continue;
|
864
|
+
edge.facet_number = i;
|
865
|
+
edge.which_edge = j;
|
866
|
+
stl_load_edge_exact(stl, &edge, &facet.vertex[j],
|
867
|
+
&facet.vertex[(j + 1) % 3]);
|
868
|
+
|
869
|
+
insert_hash_edge(stl, edge, stl_match_neighbors_exact);
|
870
|
+
}
|
871
|
+
}
|
872
|
+
|
873
|
+
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
874
|
+
facet = stl->facet_start[i];
|
875
|
+
neighbors_initial[0] = stl->neighbors_start[i].neighbor[0];
|
876
|
+
neighbors_initial[1] = stl->neighbors_start[i].neighbor[1];
|
877
|
+
neighbors_initial[2] = stl->neighbors_start[i].neighbor[2];
|
878
|
+
first_facet = i;
|
879
|
+
for(j = 0; j < 3; j++) {
|
880
|
+
if(stl->neighbors_start[i].neighbor[j] != -1) continue;
|
881
|
+
|
882
|
+
new_facet.vertex[0] = facet.vertex[j];
|
883
|
+
new_facet.vertex[1] = facet.vertex[(j + 1) % 3];
|
884
|
+
if(neighbors_initial[(j + 2) % 3] == -1) {
|
885
|
+
direction = 1;
|
886
|
+
} else {
|
887
|
+
direction = 0;
|
888
|
+
}
|
889
|
+
|
890
|
+
facet_num = i;
|
891
|
+
vnot = (j + 2) % 3;
|
892
|
+
|
893
|
+
for(;;) {
|
894
|
+
if(vnot > 2) {
|
895
|
+
if(direction == 0) {
|
896
|
+
pivot_vertex = (vnot + 2) % 3;
|
897
|
+
next_edge = pivot_vertex;
|
898
|
+
direction = 1;
|
899
|
+
} else {
|
900
|
+
pivot_vertex = (vnot + 1) % 3;
|
901
|
+
next_edge = vnot % 3;
|
902
|
+
direction = 0;
|
903
|
+
}
|
904
|
+
} else {
|
905
|
+
if(direction == 0) {
|
906
|
+
pivot_vertex = (vnot + 1) % 3;
|
907
|
+
next_edge = vnot;
|
908
|
+
} else {
|
909
|
+
pivot_vertex = (vnot + 2) % 3;
|
910
|
+
next_edge = pivot_vertex;
|
911
|
+
}
|
912
|
+
}
|
913
|
+
next_facet = stl->neighbors_start[facet_num].neighbor[next_edge];
|
914
|
+
|
915
|
+
if(next_facet == -1) {
|
916
|
+
new_facet.vertex[2] = stl->facet_start[facet_num].
|
917
|
+
vertex[vnot % 3];
|
918
|
+
stl_add_facet(stl, &new_facet);
|
919
|
+
for(k = 0; k < 3; k++) {
|
920
|
+
edge.facet_number = stl->stats.number_of_facets - 1;
|
921
|
+
edge.which_edge = k;
|
922
|
+
stl_load_edge_exact(stl, &edge, &new_facet.vertex[k],
|
923
|
+
&new_facet.vertex[(k + 1) % 3]);
|
924
|
+
|
925
|
+
insert_hash_edge(stl, edge, stl_match_neighbors_exact);
|
926
|
+
}
|
927
|
+
break;
|
928
|
+
} else {
|
929
|
+
vnot = stl->neighbors_start[facet_num].
|
930
|
+
which_vertex_not[next_edge];
|
931
|
+
facet_num = next_facet;
|
932
|
+
}
|
933
|
+
|
934
|
+
if(facet_num == first_facet) {
|
935
|
+
/* back to the beginning */
|
936
|
+
printf("\
|
937
|
+
Back to the first facet filling holes: probably a mobius part.\n\
|
938
|
+
Try using a smaller tolerance or don't do a nearby check\n");
|
939
|
+
return;
|
940
|
+
}
|
941
|
+
}
|
942
|
+
}
|
943
|
+
}
|
944
|
+
}
|
945
|
+
|
946
|
+
void
|
947
|
+
stl_add_facet(stl_file *stl, stl_facet *new_facet) {
|
948
|
+
if (stl->error) return;
|
949
|
+
|
950
|
+
stl->stats.facets_added += 1;
|
951
|
+
if(stl->stats.facets_malloced < stl->stats.number_of_facets + 1) {
|
952
|
+
stl->facet_start = (stl_facet*)realloc(stl->facet_start,
|
953
|
+
(sizeof(stl_facet) * (stl->stats.facets_malloced + 256)));
|
954
|
+
if(stl->facet_start == NULL) perror("stl_add_facet");
|
955
|
+
stl->neighbors_start = (stl_neighbors*)realloc(stl->neighbors_start,
|
956
|
+
(sizeof(stl_neighbors) * (stl->stats.facets_malloced + 256)));
|
957
|
+
if(stl->neighbors_start == NULL) perror("stl_add_facet");
|
958
|
+
stl->stats.facets_malloced += 256;
|
959
|
+
}
|
960
|
+
stl->facet_start[stl->stats.number_of_facets] = *new_facet;
|
961
|
+
|
962
|
+
/* note that the normal vector is not set here, just initialized to 0 */
|
963
|
+
stl->facet_start[stl->stats.number_of_facets].normal.x = 0.0;
|
964
|
+
stl->facet_start[stl->stats.number_of_facets].normal.y = 0.0;
|
965
|
+
stl->facet_start[stl->stats.number_of_facets].normal.z = 0.0;
|
966
|
+
|
967
|
+
stl->neighbors_start[stl->stats.number_of_facets].neighbor[0] = -1;
|
968
|
+
stl->neighbors_start[stl->stats.number_of_facets].neighbor[1] = -1;
|
969
|
+
stl->neighbors_start[stl->stats.number_of_facets].neighbor[2] = -1;
|
970
|
+
stl->stats.number_of_facets += 1;
|
971
|
+
}
|