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,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
+ }