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,333 @@
|
|
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
|
+
static void stl_reverse_facet(stl_file *stl, int facet_num);
|
31
|
+
static void stl_reverse_vector(float v[]);
|
32
|
+
int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag);
|
33
|
+
|
34
|
+
static void
|
35
|
+
stl_reverse_facet(stl_file *stl, int facet_num) {
|
36
|
+
stl_vertex tmp_vertex;
|
37
|
+
/* int tmp_neighbor;*/
|
38
|
+
int neighbor[3];
|
39
|
+
int vnot[3];
|
40
|
+
|
41
|
+
stl->stats.facets_reversed += 1;
|
42
|
+
|
43
|
+
neighbor[0] = stl->neighbors_start[facet_num].neighbor[0];
|
44
|
+
neighbor[1] = stl->neighbors_start[facet_num].neighbor[1];
|
45
|
+
neighbor[2] = stl->neighbors_start[facet_num].neighbor[2];
|
46
|
+
vnot[0] = stl->neighbors_start[facet_num].which_vertex_not[0];
|
47
|
+
vnot[1] = stl->neighbors_start[facet_num].which_vertex_not[1];
|
48
|
+
vnot[2] = stl->neighbors_start[facet_num].which_vertex_not[2];
|
49
|
+
|
50
|
+
/* reverse the facet */
|
51
|
+
tmp_vertex = stl->facet_start[facet_num].vertex[0];
|
52
|
+
stl->facet_start[facet_num].vertex[0] =
|
53
|
+
stl->facet_start[facet_num].vertex[1];
|
54
|
+
stl->facet_start[facet_num].vertex[1] = tmp_vertex;
|
55
|
+
|
56
|
+
/* fix the vnots of the neighboring facets */
|
57
|
+
if(neighbor[0] != -1)
|
58
|
+
stl->neighbors_start[neighbor[0]].which_vertex_not[(vnot[0] + 1) % 3] =
|
59
|
+
(stl->neighbors_start[neighbor[0]].
|
60
|
+
which_vertex_not[(vnot[0] + 1) % 3] + 3) % 6;
|
61
|
+
if(neighbor[1] != -1)
|
62
|
+
stl->neighbors_start[neighbor[1]].which_vertex_not[(vnot[1] + 1) % 3] =
|
63
|
+
(stl->neighbors_start[neighbor[1]].
|
64
|
+
which_vertex_not[(vnot[1] + 1) % 3] + 4) % 6;
|
65
|
+
if(neighbor[2] != -1)
|
66
|
+
stl->neighbors_start[neighbor[2]].which_vertex_not[(vnot[2] + 1) % 3] =
|
67
|
+
(stl->neighbors_start[neighbor[2]].
|
68
|
+
which_vertex_not[(vnot[2] + 1) % 3] + 2) % 6;
|
69
|
+
|
70
|
+
/* swap the neighbors of the facet that is being reversed */
|
71
|
+
stl->neighbors_start[facet_num].neighbor[1] = neighbor[2];
|
72
|
+
stl->neighbors_start[facet_num].neighbor[2] = neighbor[1];
|
73
|
+
|
74
|
+
/* swap the vnots of the facet that is being reversed */
|
75
|
+
stl->neighbors_start[facet_num].which_vertex_not[1] = vnot[2];
|
76
|
+
stl->neighbors_start[facet_num].which_vertex_not[2] = vnot[1];
|
77
|
+
|
78
|
+
/* reverse the values of the vnots of the facet that is being reversed */
|
79
|
+
stl->neighbors_start[facet_num].which_vertex_not[0] =
|
80
|
+
(stl->neighbors_start[facet_num].which_vertex_not[0] + 3) % 6;
|
81
|
+
stl->neighbors_start[facet_num].which_vertex_not[1] =
|
82
|
+
(stl->neighbors_start[facet_num].which_vertex_not[1] + 3) % 6;
|
83
|
+
stl->neighbors_start[facet_num].which_vertex_not[2] =
|
84
|
+
(stl->neighbors_start[facet_num].which_vertex_not[2] + 3) % 6;
|
85
|
+
}
|
86
|
+
|
87
|
+
void
|
88
|
+
stl_fix_normal_directions(stl_file *stl) {
|
89
|
+
char *norm_sw;
|
90
|
+
/* int edge_num;*/
|
91
|
+
/* int vnot;*/
|
92
|
+
int checked = 0;
|
93
|
+
int facet_num;
|
94
|
+
/* int next_facet;*/
|
95
|
+
int i;
|
96
|
+
int j;
|
97
|
+
struct stl_normal {
|
98
|
+
int facet_num;
|
99
|
+
struct stl_normal *next;
|
100
|
+
};
|
101
|
+
struct stl_normal *head;
|
102
|
+
struct stl_normal *tail;
|
103
|
+
struct stl_normal *newn;
|
104
|
+
struct stl_normal *temp;
|
105
|
+
|
106
|
+
if (stl->error) return;
|
107
|
+
|
108
|
+
/* Initialize linked list. */
|
109
|
+
head = (struct stl_normal*)malloc(sizeof(struct stl_normal));
|
110
|
+
if(head == NULL) perror("stl_fix_normal_directions");
|
111
|
+
tail = (struct stl_normal*)malloc(sizeof(struct stl_normal));
|
112
|
+
if(tail == NULL) perror("stl_fix_normal_directions");
|
113
|
+
head->next = tail;
|
114
|
+
tail->next = tail;
|
115
|
+
|
116
|
+
/* Initialize list that keeps track of already fixed facets. */
|
117
|
+
norm_sw = (char*)calloc(stl->stats.number_of_facets, sizeof(char));
|
118
|
+
if(norm_sw == NULL) perror("stl_fix_normal_directions");
|
119
|
+
|
120
|
+
|
121
|
+
facet_num = 0;
|
122
|
+
/* If normal vector is not within tolerance and backwards:
|
123
|
+
Arbitrarily starts at face 0. If this one is wrong, we're screwed. Thankfully, the chances
|
124
|
+
of it being wrong randomly are low if most of the triangles are right: */
|
125
|
+
if(stl_check_normal_vector(stl, 0, 0) == 2)
|
126
|
+
stl_reverse_facet(stl, 0);
|
127
|
+
|
128
|
+
/* Say that we've fixed this facet: */
|
129
|
+
norm_sw[facet_num] = 1;
|
130
|
+
checked++;
|
131
|
+
|
132
|
+
for(;;) {
|
133
|
+
/* Add neighbors_to_list.
|
134
|
+
Add unconnected neighbors to the list:a */
|
135
|
+
for(j = 0; j < 3; j++) {
|
136
|
+
/* Reverse the neighboring facets if necessary. */
|
137
|
+
if(stl->neighbors_start[facet_num].which_vertex_not[j] > 2) {
|
138
|
+
/* If the facet has a neighbor that is -1, it means that edge isn't shared by another facet */
|
139
|
+
if(stl->neighbors_start[facet_num].neighbor[j] != -1) {
|
140
|
+
stl_reverse_facet
|
141
|
+
(stl, stl->neighbors_start[facet_num].neighbor[j]);
|
142
|
+
}
|
143
|
+
}
|
144
|
+
/* If this edge of the facet is connected: */
|
145
|
+
if(stl->neighbors_start[facet_num].neighbor[j] != -1) {
|
146
|
+
/* If we haven't fixed this facet yet, add it to the list: */
|
147
|
+
if(norm_sw[stl->neighbors_start[facet_num].neighbor[j]] != 1) {
|
148
|
+
/* Add node to beginning of list. */
|
149
|
+
newn = (struct stl_normal*)malloc(sizeof(struct stl_normal));
|
150
|
+
if(newn == NULL) perror("stl_fix_normal_directions");
|
151
|
+
newn->facet_num = stl->neighbors_start[facet_num].neighbor[j];
|
152
|
+
newn->next = head->next;
|
153
|
+
head->next = newn;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
}
|
157
|
+
/* Get next facet to fix from top of list. */
|
158
|
+
if(head->next != tail) {
|
159
|
+
facet_num = head->next->facet_num;
|
160
|
+
if(norm_sw[facet_num] != 1) { /* If facet is in list mutiple times */
|
161
|
+
norm_sw[facet_num] = 1; /* Record this one as being fixed. */
|
162
|
+
checked++;
|
163
|
+
}
|
164
|
+
temp = head->next; /* Delete this facet from the list. */
|
165
|
+
head->next = head->next->next;
|
166
|
+
free(temp);
|
167
|
+
} else { /* if we ran out of facets to fix: */
|
168
|
+
/* All of the facets in this part have been fixed. */
|
169
|
+
stl->stats.number_of_parts += 1;
|
170
|
+
if(checked >= stl->stats.number_of_facets) {
|
171
|
+
/* All of the facets have been checked. Bail out. */
|
172
|
+
break;
|
173
|
+
} else {
|
174
|
+
/* There is another part here. Find it and continue. */
|
175
|
+
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
176
|
+
if(norm_sw[i] == 0) {
|
177
|
+
/* This is the first facet of the next part. */
|
178
|
+
facet_num = i;
|
179
|
+
if(stl_check_normal_vector(stl, i, 0) == 2) {
|
180
|
+
stl_reverse_facet(stl, i);
|
181
|
+
}
|
182
|
+
|
183
|
+
norm_sw[facet_num] = 1;
|
184
|
+
checked++;
|
185
|
+
break;
|
186
|
+
}
|
187
|
+
}
|
188
|
+
}
|
189
|
+
}
|
190
|
+
}
|
191
|
+
free(head);
|
192
|
+
free(tail);
|
193
|
+
free(norm_sw);
|
194
|
+
}
|
195
|
+
|
196
|
+
int
|
197
|
+
stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag) {
|
198
|
+
/* Returns 0 if the normal is within tolerance */
|
199
|
+
/* Returns 1 if the normal is not within tolerance, but direction is OK */
|
200
|
+
/* Returns 2 if the normal is not within tolerance and backwards */
|
201
|
+
/* Returns 4 if the status is unknown. */
|
202
|
+
|
203
|
+
float normal[3];
|
204
|
+
float test_norm[3];
|
205
|
+
stl_facet *facet;
|
206
|
+
|
207
|
+
facet = &stl->facet_start[facet_num];
|
208
|
+
|
209
|
+
stl_calculate_normal(normal, facet);
|
210
|
+
stl_normalize_vector(normal);
|
211
|
+
|
212
|
+
if( (ABS(normal[0] - facet->normal.x) < 0.001)
|
213
|
+
&& (ABS(normal[1] - facet->normal.y) < 0.001)
|
214
|
+
&& (ABS(normal[2] - facet->normal.z) < 0.001)) {
|
215
|
+
/* It is not really necessary to change the values here */
|
216
|
+
/* but just for consistency, I will. */
|
217
|
+
facet->normal.x = normal[0];
|
218
|
+
facet->normal.y = normal[1];
|
219
|
+
facet->normal.z = normal[2];
|
220
|
+
return 0;
|
221
|
+
}
|
222
|
+
|
223
|
+
test_norm[0] = facet->normal.x;
|
224
|
+
test_norm[1] = facet->normal.y;
|
225
|
+
test_norm[2] = facet->normal.z;
|
226
|
+
|
227
|
+
stl_normalize_vector(test_norm);
|
228
|
+
if( (ABS(normal[0] - test_norm[0]) < 0.001)
|
229
|
+
&& (ABS(normal[1] - test_norm[1]) < 0.001)
|
230
|
+
&& (ABS(normal[2] - test_norm[2]) < 0.001)) {
|
231
|
+
if(normal_fix_flag) {
|
232
|
+
facet->normal.x = normal[0];
|
233
|
+
facet->normal.y = normal[1];
|
234
|
+
facet->normal.z = normal[2];
|
235
|
+
stl->stats.normals_fixed += 1;
|
236
|
+
}
|
237
|
+
return 1;
|
238
|
+
}
|
239
|
+
|
240
|
+
stl_reverse_vector(test_norm);
|
241
|
+
if( (ABS(normal[0] - test_norm[0]) < 0.001)
|
242
|
+
&& (ABS(normal[1] - test_norm[1]) < 0.001)
|
243
|
+
&& (ABS(normal[2] - test_norm[2]) < 0.001)) {
|
244
|
+
/* Facet is backwards. */
|
245
|
+
if(normal_fix_flag) {
|
246
|
+
facet->normal.x = normal[0];
|
247
|
+
facet->normal.y = normal[1];
|
248
|
+
facet->normal.z = normal[2];
|
249
|
+
stl->stats.normals_fixed += 1;
|
250
|
+
}
|
251
|
+
return 2;
|
252
|
+
}
|
253
|
+
if(normal_fix_flag) {
|
254
|
+
facet->normal.x = normal[0];
|
255
|
+
facet->normal.y = normal[1];
|
256
|
+
facet->normal.z = normal[2];
|
257
|
+
stl->stats.normals_fixed += 1;
|
258
|
+
}
|
259
|
+
return 4;
|
260
|
+
}
|
261
|
+
|
262
|
+
static void
|
263
|
+
stl_reverse_vector(float v[]) {
|
264
|
+
v[0] *= -1;
|
265
|
+
v[1] *= -1;
|
266
|
+
v[2] *= -1;
|
267
|
+
}
|
268
|
+
|
269
|
+
|
270
|
+
void
|
271
|
+
stl_calculate_normal(float normal[], stl_facet *facet) {
|
272
|
+
float v1[3];
|
273
|
+
float v2[3];
|
274
|
+
|
275
|
+
v1[0] = facet->vertex[1].x - facet->vertex[0].x;
|
276
|
+
v1[1] = facet->vertex[1].y - facet->vertex[0].y;
|
277
|
+
v1[2] = facet->vertex[1].z - facet->vertex[0].z;
|
278
|
+
v2[0] = facet->vertex[2].x - facet->vertex[0].x;
|
279
|
+
v2[1] = facet->vertex[2].y - facet->vertex[0].y;
|
280
|
+
v2[2] = facet->vertex[2].z - facet->vertex[0].z;
|
281
|
+
|
282
|
+
normal[0] = (float)((double)v1[1] * (double)v2[2]) - ((double)v1[2] * (double)v2[1]);
|
283
|
+
normal[1] = (float)((double)v1[2] * (double)v2[0]) - ((double)v1[0] * (double)v2[2]);
|
284
|
+
normal[2] = (float)((double)v1[0] * (double)v2[1]) - ((double)v1[1] * (double)v2[0]);
|
285
|
+
}
|
286
|
+
|
287
|
+
void stl_normalize_vector(float v[]) {
|
288
|
+
double length;
|
289
|
+
double factor;
|
290
|
+
float min_normal_length;
|
291
|
+
|
292
|
+
length = sqrt((double)v[0] * (double)v[0] + (double)v[1] * (double)v[1] + (double)v[2] * (double)v[2]);
|
293
|
+
min_normal_length = 0.000000000001;
|
294
|
+
if(length < min_normal_length) {
|
295
|
+
v[0] = 0.0;
|
296
|
+
v[1] = 0.0;
|
297
|
+
v[2] = 0.0;
|
298
|
+
return;
|
299
|
+
}
|
300
|
+
factor = 1.0 / length;
|
301
|
+
v[0] *= factor;
|
302
|
+
v[1] *= factor;
|
303
|
+
v[2] *= factor;
|
304
|
+
}
|
305
|
+
|
306
|
+
void
|
307
|
+
stl_fix_normal_values(stl_file *stl) {
|
308
|
+
int i;
|
309
|
+
|
310
|
+
if (stl->error) return;
|
311
|
+
|
312
|
+
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
313
|
+
stl_check_normal_vector(stl, i, 1);
|
314
|
+
}
|
315
|
+
}
|
316
|
+
|
317
|
+
void
|
318
|
+
stl_reverse_all_facets(stl_file *stl) {
|
319
|
+
int i;
|
320
|
+
float normal[3];
|
321
|
+
|
322
|
+
if (stl->error) return;
|
323
|
+
|
324
|
+
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
325
|
+
stl_reverse_facet(stl, i);
|
326
|
+
stl_calculate_normal(normal, &stl->facet_start[i]);
|
327
|
+
stl_normalize_vector(normal);
|
328
|
+
stl->facet_start[i].normal.x = normal[0];
|
329
|
+
stl->facet_start[i].normal.y = normal[1];
|
330
|
+
stl->facet_start[i].normal.z = normal[2];
|
331
|
+
}
|
332
|
+
}
|
333
|
+
|
@@ -0,0 +1,262 @@
|
|
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 <stdlib.h>
|
24
|
+
#include <string.h>
|
25
|
+
|
26
|
+
#include "stl.h"
|
27
|
+
|
28
|
+
void
|
29
|
+
stl_invalidate_shared_vertices(stl_file *stl) {
|
30
|
+
if (stl->error) return;
|
31
|
+
|
32
|
+
if (stl->v_indices != NULL) {
|
33
|
+
free(stl->v_indices);
|
34
|
+
stl->v_indices = NULL;
|
35
|
+
}
|
36
|
+
if (stl->v_shared != NULL) {
|
37
|
+
free(stl->v_shared);
|
38
|
+
stl->v_shared = NULL;
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
void
|
43
|
+
stl_generate_shared_vertices(stl_file *stl) {
|
44
|
+
int i;
|
45
|
+
int j;
|
46
|
+
int first_facet;
|
47
|
+
int direction;
|
48
|
+
int facet_num;
|
49
|
+
int vnot;
|
50
|
+
int next_edge;
|
51
|
+
int pivot_vertex;
|
52
|
+
int next_facet;
|
53
|
+
int reversed;
|
54
|
+
|
55
|
+
if (stl->error) return;
|
56
|
+
|
57
|
+
/* make sure this function is idempotent and does not leak memory */
|
58
|
+
stl_invalidate_shared_vertices(stl);
|
59
|
+
|
60
|
+
stl->v_indices = (v_indices_struct*)
|
61
|
+
calloc(stl->stats.number_of_facets, sizeof(v_indices_struct));
|
62
|
+
if(stl->v_indices == NULL) perror("stl_generate_shared_vertices");
|
63
|
+
stl->v_shared = (stl_vertex*)
|
64
|
+
calloc((stl->stats.number_of_facets / 2), sizeof(stl_vertex));
|
65
|
+
if(stl->v_shared == NULL) perror("stl_generate_shared_vertices");
|
66
|
+
stl->stats.shared_malloced = stl->stats.number_of_facets / 2;
|
67
|
+
stl->stats.shared_vertices = 0;
|
68
|
+
|
69
|
+
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
70
|
+
stl->v_indices[i].vertex[0] = -1;
|
71
|
+
stl->v_indices[i].vertex[1] = -1;
|
72
|
+
stl->v_indices[i].vertex[2] = -1;
|
73
|
+
}
|
74
|
+
|
75
|
+
|
76
|
+
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
77
|
+
first_facet = i;
|
78
|
+
for(j = 0; j < 3; j++) {
|
79
|
+
if(stl->v_indices[i].vertex[j] != -1) {
|
80
|
+
continue;
|
81
|
+
}
|
82
|
+
if(stl->stats.shared_vertices == stl->stats.shared_malloced) {
|
83
|
+
stl->stats.shared_malloced += 1024;
|
84
|
+
stl->v_shared = (stl_vertex*)realloc(stl->v_shared,
|
85
|
+
stl->stats.shared_malloced * sizeof(stl_vertex));
|
86
|
+
if(stl->v_shared == NULL) perror("stl_generate_shared_vertices");
|
87
|
+
}
|
88
|
+
|
89
|
+
stl->v_shared[stl->stats.shared_vertices] =
|
90
|
+
stl->facet_start[i].vertex[j];
|
91
|
+
|
92
|
+
direction = 0;
|
93
|
+
reversed = 0;
|
94
|
+
facet_num = i;
|
95
|
+
vnot = (j + 2) % 3;
|
96
|
+
|
97
|
+
for(;;) {
|
98
|
+
if(vnot > 2) {
|
99
|
+
if(direction == 0) {
|
100
|
+
pivot_vertex = (vnot + 2) % 3;
|
101
|
+
next_edge = pivot_vertex;
|
102
|
+
direction = 1;
|
103
|
+
} else {
|
104
|
+
pivot_vertex = (vnot + 1) % 3;
|
105
|
+
next_edge = vnot % 3;
|
106
|
+
direction = 0;
|
107
|
+
}
|
108
|
+
} else {
|
109
|
+
if(direction == 0) {
|
110
|
+
pivot_vertex = (vnot + 1) % 3;
|
111
|
+
next_edge = vnot;
|
112
|
+
} else {
|
113
|
+
pivot_vertex = (vnot + 2) % 3;
|
114
|
+
next_edge = pivot_vertex;
|
115
|
+
}
|
116
|
+
}
|
117
|
+
stl->v_indices[facet_num].vertex[pivot_vertex] =
|
118
|
+
stl->stats.shared_vertices;
|
119
|
+
|
120
|
+
next_facet = stl->neighbors_start[facet_num].neighbor[next_edge];
|
121
|
+
if(next_facet == -1) {
|
122
|
+
if(reversed) {
|
123
|
+
break;
|
124
|
+
} else {
|
125
|
+
direction = 1;
|
126
|
+
vnot = (j + 1) % 3;
|
127
|
+
reversed = 1;
|
128
|
+
facet_num = first_facet;
|
129
|
+
}
|
130
|
+
} else if(next_facet != first_facet) {
|
131
|
+
vnot = stl->neighbors_start[facet_num].
|
132
|
+
which_vertex_not[next_edge];
|
133
|
+
facet_num = next_facet;
|
134
|
+
} else {
|
135
|
+
break;
|
136
|
+
}
|
137
|
+
}
|
138
|
+
stl->stats.shared_vertices += 1;
|
139
|
+
}
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
void
|
144
|
+
stl_write_off(stl_file *stl, char *file) {
|
145
|
+
int i;
|
146
|
+
FILE *fp;
|
147
|
+
char *error_msg;
|
148
|
+
|
149
|
+
if (stl->error) return;
|
150
|
+
|
151
|
+
/* Open the file */
|
152
|
+
fp = fopen(file, "w");
|
153
|
+
if(fp == NULL) {
|
154
|
+
error_msg = (char*)
|
155
|
+
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
156
|
+
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing",
|
157
|
+
file);
|
158
|
+
perror(error_msg);
|
159
|
+
free(error_msg);
|
160
|
+
stl->error = 1;
|
161
|
+
return;
|
162
|
+
}
|
163
|
+
|
164
|
+
fprintf(fp, "OFF\n");
|
165
|
+
fprintf(fp, "%d %d 0\n",
|
166
|
+
stl->stats.shared_vertices, stl->stats.number_of_facets);
|
167
|
+
|
168
|
+
for(i = 0; i < stl->stats.shared_vertices; i++) {
|
169
|
+
fprintf(fp, "\t%f %f %f\n",
|
170
|
+
stl->v_shared[i].x, stl->v_shared[i].y, stl->v_shared[i].z);
|
171
|
+
}
|
172
|
+
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
173
|
+
fprintf(fp, "\t3 %d %d %d\n", stl->v_indices[i].vertex[0],
|
174
|
+
stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]);
|
175
|
+
}
|
176
|
+
fclose(fp);
|
177
|
+
}
|
178
|
+
|
179
|
+
void
|
180
|
+
stl_write_vrml(stl_file *stl, char *file) {
|
181
|
+
int i;
|
182
|
+
FILE *fp;
|
183
|
+
char *error_msg;
|
184
|
+
|
185
|
+
if (stl->error) return;
|
186
|
+
|
187
|
+
/* Open the file */
|
188
|
+
fp = fopen(file, "w");
|
189
|
+
if(fp == NULL) {
|
190
|
+
error_msg = (char*)
|
191
|
+
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
192
|
+
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing",
|
193
|
+
file);
|
194
|
+
perror(error_msg);
|
195
|
+
free(error_msg);
|
196
|
+
stl->error = 1;
|
197
|
+
return;
|
198
|
+
}
|
199
|
+
|
200
|
+
fprintf(fp, "#VRML V1.0 ascii\n\n");
|
201
|
+
fprintf(fp, "Separator {\n");
|
202
|
+
fprintf(fp, "\tDEF STLShape ShapeHints {\n");
|
203
|
+
fprintf(fp, "\t\tvertexOrdering COUNTERCLOCKWISE\n");
|
204
|
+
fprintf(fp, "\t\tfaceType CONVEX\n");
|
205
|
+
fprintf(fp, "\t\tshapeType SOLID\n");
|
206
|
+
fprintf(fp, "\t\tcreaseAngle 0.0\n");
|
207
|
+
fprintf(fp, "\t}\n");
|
208
|
+
fprintf(fp, "\tDEF STLModel Separator {\n");
|
209
|
+
fprintf(fp, "\t\tDEF STLColor Material {\n");
|
210
|
+
fprintf(fp, "\t\t\temissiveColor 0.700000 0.700000 0.000000\n");
|
211
|
+
fprintf(fp, "\t\t}\n");
|
212
|
+
fprintf(fp, "\t\tDEF STLVertices Coordinate3 {\n");
|
213
|
+
fprintf(fp, "\t\t\tpoint [\n");
|
214
|
+
|
215
|
+
for(i = 0; i < (stl->stats.shared_vertices - 1); i++) {
|
216
|
+
fprintf(fp, "\t\t\t\t%f %f %f,\n",
|
217
|
+
stl->v_shared[i].x, stl->v_shared[i].y, stl->v_shared[i].z);
|
218
|
+
}
|
219
|
+
fprintf(fp, "\t\t\t\t%f %f %f]\n",
|
220
|
+
stl->v_shared[i].x, stl->v_shared[i].y, stl->v_shared[i].z);
|
221
|
+
fprintf(fp, "\t\t}\n");
|
222
|
+
fprintf(fp, "\t\tDEF STLTriangles IndexedFaceSet {\n");
|
223
|
+
fprintf(fp, "\t\t\tcoordIndex [\n");
|
224
|
+
|
225
|
+
for(i = 0; i < (stl->stats.number_of_facets - 1); i++) {
|
226
|
+
fprintf(fp, "\t\t\t\t%d, %d, %d, -1,\n", stl->v_indices[i].vertex[0],
|
227
|
+
stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]);
|
228
|
+
}
|
229
|
+
fprintf(fp, "\t\t\t\t%d, %d, %d, -1]\n", stl->v_indices[i].vertex[0],
|
230
|
+
stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]);
|
231
|
+
fprintf(fp, "\t\t}\n");
|
232
|
+
fprintf(fp, "\t}\n");
|
233
|
+
fprintf(fp, "}\n");
|
234
|
+
fclose(fp);
|
235
|
+
}
|
236
|
+
|
237
|
+
void stl_write_obj (stl_file *stl, char *file) {
|
238
|
+
int i;
|
239
|
+
FILE* fp;
|
240
|
+
|
241
|
+
if (stl->error) return;
|
242
|
+
|
243
|
+
/* Open the file */
|
244
|
+
fp = fopen(file, "w");
|
245
|
+
if (fp == NULL) {
|
246
|
+
char* error_msg = (char*)malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
247
|
+
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file);
|
248
|
+
perror(error_msg);
|
249
|
+
free(error_msg);
|
250
|
+
stl->error = 1;
|
251
|
+
return;
|
252
|
+
}
|
253
|
+
|
254
|
+
for (i = 0; i < stl->stats.shared_vertices; i++) {
|
255
|
+
fprintf(fp, "v %f %f %f\n", stl->v_shared[i].x, stl->v_shared[i].y, stl->v_shared[i].z);
|
256
|
+
}
|
257
|
+
for (i = 0; i < stl->stats.number_of_facets; i++) {
|
258
|
+
fprintf(fp, "f %d %d %d\n", stl->v_indices[i].vertex[0]+1, stl->v_indices[i].vertex[1]+1, stl->v_indices[i].vertex[2]+1);
|
259
|
+
}
|
260
|
+
|
261
|
+
fclose(fp);
|
262
|
+
}
|