admesh 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }