admesh 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/ext/admesh/admesh/AUTHORS +11 -0
  3. data/ext/admesh/admesh/COPYING +339 -0
  4. data/ext/admesh/admesh/ChangeLog +143 -0
  5. data/ext/admesh/admesh/ChangeLog.old +42 -0
  6. data/ext/admesh/admesh/INSTALL +14 -0
  7. data/ext/admesh/admesh/Makefile.am +62 -0
  8. data/ext/admesh/admesh/Makefile.in +1100 -0
  9. data/ext/admesh/admesh/README.md +115 -0
  10. data/ext/admesh/admesh/aclocal.m4 +1183 -0
  11. data/ext/admesh/admesh/admesh-doc.txt +475 -0
  12. data/ext/admesh/admesh/admesh.1 +173 -0
  13. data/ext/admesh/admesh/block.stl +86 -0
  14. data/ext/admesh/admesh/compile +347 -0
  15. data/ext/admesh/admesh/config.guess +1420 -0
  16. data/ext/admesh/admesh/config.h.in +65 -0
  17. data/ext/admesh/admesh/config.sub +1798 -0
  18. data/ext/admesh/admesh/configure +14671 -0
  19. data/ext/admesh/admesh/configure.ac +90 -0
  20. data/ext/admesh/admesh/depcomp +791 -0
  21. data/ext/admesh/admesh/install-sh +527 -0
  22. data/ext/admesh/admesh/libadmesh.pc.in +11 -0
  23. data/ext/admesh/admesh/ltmain.sh +9655 -0
  24. data/ext/admesh/admesh/m4/libtool.m4 +7992 -0
  25. data/ext/admesh/admesh/m4/ltoptions.m4 +384 -0
  26. data/ext/admesh/admesh/m4/ltsugar.m4 +123 -0
  27. data/ext/admesh/admesh/m4/ltversion.m4 +23 -0
  28. data/ext/admesh/admesh/m4/lt~obsolete.m4 +98 -0
  29. data/ext/admesh/admesh/missing +215 -0
  30. data/ext/admesh/admesh/src/admesh.c +425 -0
  31. data/ext/admesh/admesh/src/connect.c +971 -0
  32. data/ext/admesh/admesh/src/normals.c +333 -0
  33. data/ext/admesh/admesh/src/shared.c +262 -0
  34. data/ext/admesh/admesh/src/stl.h +201 -0
  35. data/ext/admesh/admesh/src/stl_io.c +479 -0
  36. data/ext/admesh/admesh/src/stlinit.c +377 -0
  37. data/ext/admesh/admesh/src/util.c +557 -0
  38. data/ext/admesh/extconf.rb +14 -0
  39. data/lib/admesh.rb +40 -0
  40. 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
+ }