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