SDDSlib
Loading...
Searching...
No Matches
stl2sdds.c
1#include "mdb.h"
2#include "SDDS.h"
3#include "scan.h"
4
5float float_reverse_bytes(float x);
6int leqi(char *string1, char *string2);
7
8#define SET_ASCII 0
9#define SET_BINARY 1
10#define SET_PIPE 2
11#define N_OPTIONS 3
12
13char *option[N_OPTIONS] = {
14 "ascii", "binary", "pipe"};
15
16char *USAGE = "stl2sdds [<inputFile>] [<outputFile>] [-pipe[=in][,out]]\n\
17[-ascii | -binary]\n\n\
18pipe SDDS toolkit pipe option.\n\
19ascii Requests SDDS ASCII output. Default is binary.\n\
20binary Requests SDDS BINARY output.\n\
21Converts STL files to SDDS.\n\
22Program by Robert Soliday. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
23
24#define LINE_MAX_LEN 256
25#define FALSE 0
26#define TRUE 1
27
28int main(int argc, char **argv) {
29 char *inputFile = NULL, *outputFile = NULL;
30 SDDS_DATASET SDDSout;
31 SCANNED_ARG *scanned;
32 long iArg;
33 long ascii = 0, stlascii = 0;
34 unsigned long pipeFlags = 0;
35
36 int i, n = 0, solid = 0;
37 char init[7];
38 short attribute = 0;
39 int32_t face_num = 0, iface;
40 int32_t bigEndianMachine = 0;
41 int64_t bytes_num = 0, text_num = 0;
42 float *normalVector[3];
43 float *vertex1[3];
44 float *vertex2[3];
45 float *vertex3[3];
46 FILE *fd;
47 char input[LINE_MAX_LEN];
48 char *next;
49 char token[LINE_MAX_LEN];
50 int width;
51
53 argc = scanargs(&scanned, argc, argv);
54 if (argc < 2) {
55 fprintf(stderr, "%s", USAGE);
56 return (1);
57 }
58
59 for (iArg = 1; iArg < argc; iArg++) {
60 if (scanned[iArg].arg_type == OPTION) {
61 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
62 case SET_ASCII:
63 ascii = 1;
64 break;
65 case SET_BINARY:
66 ascii = 0;
67 break;
68 case SET_PIPE:
69 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags)) {
70 fprintf(stderr, "invalid -pipe syntax\n");
71 return (1);
72 }
73 break;
74 default:
75 fprintf(stderr, "stl2sdds: invalid option seen\n%s", USAGE);
76 return (1);
77 }
78 } else {
79 if (!inputFile)
80 SDDS_CopyString(&inputFile, scanned[iArg].list[0]);
81 else if (!outputFile)
82 SDDS_CopyString(&outputFile, scanned[iArg].list[0]);
83 else {
84 fprintf(stderr, "stl2sdds: too many filenames\n%s", USAGE);
85 return (1);
86 }
87 }
88 }
89
90 processFilenames("stl2sdds", &inputFile, &outputFile, pipeFlags, 0, NULL);
91
92 if (inputFile) {
93 if (!fexists(inputFile)) {
94 fprintf(stderr, "input file not found\n");
95 return (1);
96 }
97 if (!(fd = fopen(inputFile, "rb"))) {
98 fprintf(stderr, "problem opening input file\n");
99 return (1);
100 }
101 } else {
102#if defined(_WIN32)
103 if (_setmode(_fileno(stdin), _O_BINARY) == -1) {
104 fprintf(stderr, "error: unable to set stdin to binary mode\n");
105 return (1);
106 }
107#endif
108 fd = stdin;
109 }
110
111 bigEndianMachine = SDDS_IsBigEndianMachine();
112
113 /*
114 Check for ASCII or BINARY STL type
115 */
116 bytes_num += fread(&init, 1, 6, fd);
117 init[6] = 0;
118 if (strcasecmp("solid ", init) == 0) {
119 stlascii = 1;
120 }
121 if (stlascii == 0) {
122 /*
123 80 byte Header. (74 bytes remaining)
124 */
125 for (i = 0; i < 74; i++) {
126 fgetc(fd);
127 bytes_num++;
128 }
129
130 /*
131 Number of faces.
132 */
133 bytes_num += fread(&face_num, 1, sizeof(int32_t), fd);
134 if (bigEndianMachine) {
135 SDDS_SwapLong((int32_t *)&face_num);
136 }
137
138 for (i = 0; i < 3; i++) {
139 normalVector[i] = malloc(sizeof(*(normalVector[i])) * face_num);
140 vertex1[i] = malloc(sizeof(*(vertex1[i])) * face_num);
141 vertex2[i] = malloc(sizeof(*(vertex2[i])) * face_num);
142 vertex3[i] = malloc(sizeof(*(vertex3[i])) * face_num);
143 }
144
145 /*
146 For each (triangular) face,
147 components of normal vector,
148 coordinates of three vertices,
149 2 byte "attribute".
150 */
151 for (iface = 0; iface < face_num; iface++) {
152 for (i = 0; i < 3; i++) {
153 bytes_num += fread(&(normalVector[i][iface]), 1, sizeof(float), fd);
154 if (bigEndianMachine) {
155 normalVector[i][iface] = float_reverse_bytes(normalVector[i][iface]);
156 }
157 }
158 for (i = 0; i < 3; i++) {
159 bytes_num += fread(&(vertex1[i][iface]), 1, sizeof(float), fd);
160 if (bigEndianMachine) {
161 vertex1[i][iface] = float_reverse_bytes(vertex1[i][iface]);
162 }
163 }
164 for (i = 0; i < 3; i++) {
165 bytes_num += fread(&(vertex2[i][iface]), 1, sizeof(float), fd);
166 if (bigEndianMachine) {
167 vertex2[i][iface] = float_reverse_bytes(vertex2[i][iface]);
168 }
169 }
170 for (i = 0; i < 3; i++) {
171 bytes_num += fread(&(vertex3[i][iface]), 1, sizeof(float), fd);
172 if (bigEndianMachine) {
173 vertex3[i][iface] = float_reverse_bytes(vertex3[i][iface]);
174 }
175 }
176 bytes_num += fread(&(attribute), 1, sizeof(short int), fd);
177 }
178 } else {
179 for (i = 0; i < 3; i++) {
180 normalVector[i] = NULL;
181 vertex1[i] = NULL;
182 vertex2[i] = NULL;
183 vertex3[i] = NULL;
184 }
185 fseek(fd, 0, SEEK_SET);
186 while (fgets(input, LINE_MAX_LEN, fd) != NULL) {
187 text_num = text_num + 1;
188 for (next = input; *next != '\0' && isspace(*next); next++) {
189 }
190 if (*next == '\0' || *next == '#' || *next == '!' || *next == '$') {
191 continue;
192 }
193 sscanf(next, "%s%n", token, &width);
194 next = next + width;
195
196 if (leqi(token, "facet") == TRUE) {
197
198 if (n == 0) {
199 n++;
200 for (i = 0; i < 3; i++) {
201 normalVector[i] = malloc(sizeof(*(normalVector[i])) * n);
202 vertex1[i] = malloc(sizeof(*(vertex1[i])) * n);
203 vertex2[i] = malloc(sizeof(*(vertex2[i])) * n);
204 vertex3[i] = malloc(sizeof(*(vertex3[i])) * n);
205 }
206 } else {
207 n++;
208 for (i = 0; i < 3; i++) {
209 normalVector[i] = realloc(normalVector[i], sizeof(*(normalVector[i])) * n);
210 vertex1[i] = realloc(vertex1[i], sizeof(*(vertex1[i])) * n);
211 vertex2[i] = realloc(vertex2[i], sizeof(*(vertex2[i])) * n);
212 vertex3[i] = realloc(vertex3[i], sizeof(*(vertex3[i])) * n);
213 }
214 }
215
216 sscanf(next, "%*s %e %e %e", &(normalVector[0][n - 1]), &(normalVector[1][n - 1]), &(normalVector[2][n - 1]));
217
218 fgets(input, LINE_MAX_LEN, fd);
219 fgets(input, LINE_MAX_LEN, fd);
220 text_num = text_num + 2;
221
222 sscanf(next, "%*s %e %e %e", &(vertex1[0][n - 1]), &(vertex1[1][n - 1]), &(vertex1[2][n - 1]));
223
224 fgets(input, LINE_MAX_LEN, fd);
225 text_num = text_num + 1;
226
227 sscanf(next, "%*s %e %e %e", &(vertex2[0][n - 1]), &(vertex2[1][n - 1]), &(vertex2[2][n - 1]));
228
229 fgets(input, LINE_MAX_LEN, fd);
230 text_num = text_num + 1;
231
232 sscanf(next, "%*s %e %e %e", &(vertex3[0][n - 1]), &(vertex3[1][n - 1]), &(vertex3[2][n - 1]));
233
234 fgets(input, LINE_MAX_LEN, fd);
235 fgets(input, LINE_MAX_LEN, fd);
236 text_num = text_num + 2;
237 } else if (leqi(token, "color") == TRUE) {
238 fprintf(stderr, "stl2sdds: color field seen in STL file ignored.\n");
239 } else if (leqi(token, "solid") == TRUE) {
240 solid++;
241 if (solid > 1) {
242 fprintf(stderr, "stl2sdds: More than solid field seen in STL file.\n");
243 return (1);
244 }
245 } else if (leqi(token, "endsolid") == TRUE) {
246 } else {
247 fprintf(stderr, "stl2sdds: Unrecognized first word on line. %s\n", token);
248 return (1);
249 }
250 }
251 face_num = n;
252 }
253
254 if (!SDDS_InitializeOutput(&SDDSout, ascii ? SDDS_ASCII : SDDS_BINARY, 1, NULL, NULL, outputFile)) {
255 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
256 return (1);
257 }
258 if (!ascii) {
259 SDDSout.layout.data_mode.column_major = 1;
260 }
261 if (!SDDS_DefineSimpleColumn(&SDDSout, "NormalVectorX", NULL, SDDS_FLOAT)) {
262 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
263 return (1);
264 }
265 if (!SDDS_DefineSimpleColumn(&SDDSout, "NormalVectorY", NULL, SDDS_FLOAT)) {
266 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
267 return (1);
268 }
269 if (!SDDS_DefineSimpleColumn(&SDDSout, "NormalVectorZ", NULL, SDDS_FLOAT)) {
270 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
271 return (1);
272 }
273 if (!SDDS_DefineSimpleColumn(&SDDSout, "Vertex1X", NULL, SDDS_FLOAT)) {
274 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
275 return (1);
276 }
277 if (!SDDS_DefineSimpleColumn(&SDDSout, "Vertex1Y", NULL, SDDS_FLOAT)) {
278 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
279 return (1);
280 }
281 if (!SDDS_DefineSimpleColumn(&SDDSout, "Vertex1Z", NULL, SDDS_FLOAT)) {
282 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
283 return (1);
284 }
285 if (!SDDS_DefineSimpleColumn(&SDDSout, "Vertex2X", NULL, SDDS_FLOAT)) {
286 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
287 return (1);
288 }
289 if (!SDDS_DefineSimpleColumn(&SDDSout, "Vertex2Y", NULL, SDDS_FLOAT)) {
290 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
291 return (1);
292 }
293 if (!SDDS_DefineSimpleColumn(&SDDSout, "Vertex2Z", NULL, SDDS_FLOAT)) {
294 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
295 return (1);
296 }
297 if (!SDDS_DefineSimpleColumn(&SDDSout, "Vertex3X", NULL, SDDS_FLOAT)) {
298 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
299 return (1);
300 }
301 if (!SDDS_DefineSimpleColumn(&SDDSout, "Vertex3Y", NULL, SDDS_FLOAT)) {
302 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
303 return (1);
304 }
305 if (!SDDS_DefineSimpleColumn(&SDDSout, "Vertex3Z", NULL, SDDS_FLOAT)) {
306 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
307 return (1);
308 }
309 if (!SDDS_WriteLayout(&SDDSout)) {
310 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
311 return (1);
312 }
313 if (!SDDS_StartTable(&SDDSout, face_num)) {
314 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
315 return (1);
316 }
317 if (!SDDS_SetColumnFromFloats(&SDDSout, SDDS_SET_BY_NAME, normalVector[0], face_num, "NormalVectorX")) {
318 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
319 return (1);
320 }
321 if (!SDDS_SetColumnFromFloats(&SDDSout, SDDS_SET_BY_NAME, normalVector[1], face_num, "NormalVectorY")) {
322 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
323 return (1);
324 }
325 if (!SDDS_SetColumnFromFloats(&SDDSout, SDDS_SET_BY_NAME, normalVector[2], face_num, "NormalVectorZ")) {
326 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
327 return (1);
328 }
329 if (!SDDS_SetColumnFromFloats(&SDDSout, SDDS_SET_BY_NAME, vertex1[0], face_num, "Vertex1X")) {
330 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
331 return (1);
332 }
333 if (!SDDS_SetColumnFromFloats(&SDDSout, SDDS_SET_BY_NAME, vertex1[1], face_num, "Vertex1Y")) {
334 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
335 return (1);
336 }
337 if (!SDDS_SetColumnFromFloats(&SDDSout, SDDS_SET_BY_NAME, vertex1[2], face_num, "Vertex1Z")) {
338 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
339 return (1);
340 }
341 if (!SDDS_SetColumnFromFloats(&SDDSout, SDDS_SET_BY_NAME, vertex2[0], face_num, "Vertex2X")) {
342 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
343 return (1);
344 }
345 if (!SDDS_SetColumnFromFloats(&SDDSout, SDDS_SET_BY_NAME, vertex2[1], face_num, "Vertex2Y")) {
346 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
347 return (1);
348 }
349 if (!SDDS_SetColumnFromFloats(&SDDSout, SDDS_SET_BY_NAME, vertex2[2], face_num, "Vertex2Z")) {
350 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
351 return (1);
352 }
353 if (!SDDS_SetColumnFromFloats(&SDDSout, SDDS_SET_BY_NAME, vertex3[0], face_num, "Vertex3X")) {
354 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
355 return (1);
356 }
357 if (!SDDS_SetColumnFromFloats(&SDDSout, SDDS_SET_BY_NAME, vertex3[1], face_num, "Vertex3Y")) {
358 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
359 return (1);
360 }
361 if (!SDDS_SetColumnFromFloats(&SDDSout, SDDS_SET_BY_NAME, vertex3[2], face_num, "Vertex3Z")) {
362 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
363 return (1);
364 }
365
366 if (!SDDS_WriteTable(&SDDSout)) {
367 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
368 return (1);
369 }
370 if (!SDDS_Terminate(&SDDSout)) {
371 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
372 return (1);
373 }
374
375 free_scanargs(&scanned, argc);
376
377 for (i = 0; i < 3; i++) {
378 free(normalVector[i]);
379 free(vertex1[i]);
380 free(vertex2[i]);
381 free(vertex3[i]);
382 }
383
384 return (0);
385}
386
387float float_reverse_bytes(float x) {
388 char c;
389 union {
390 float yfloat;
391 char ychar[4];
392 } y;
393
394 y.yfloat = x;
395
396 c = y.ychar[0];
397 y.ychar[0] = y.ychar[3];
398 y.ychar[3] = c;
399
400 c = y.ychar[1];
401 y.ychar[1] = y.ychar[2];
402 y.ychar[2] = c;
403
404 return (y.yfloat);
405}
406
407int leqi(char *string1, char *string2) {
408 int i;
409 int nchar;
410 int nchar1;
411 int nchar2;
412
413 nchar1 = strlen(string1);
414 nchar2 = strlen(string2);
415
416 if (nchar1 < nchar2) {
417 nchar = nchar1;
418 } else {
419 nchar = nchar2;
420 }
421 /*
422 The strings are not equal if they differ over their common length.
423 */
424 for (i = 0; i < nchar; i++) {
425
426 if (toupper(string1[i]) != toupper(string2[i])) {
427 return FALSE;
428 }
429 }
430 /*
431 The strings are not equal if the longer one includes nonblanks
432 in the tail.
433 */
434 if (nchar1 > nchar) {
435 for (i = nchar; i < nchar1; i++) {
436 if (string1[i] != ' ') {
437 return FALSE;
438 }
439 }
440 } else if (nchar2 > nchar) {
441 for (i = nchar; i < nchar2; i++) {
442 if (string2[i] != ' ') {
443 return FALSE;
444 }
445 }
446 }
447 return TRUE;
448}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
void SDDS_SwapLong(int32_t *data)
Swaps the endianness of a 32-bit integer.
int32_t SDDS_SetColumnFromFloats(SDDS_DATASET *SDDS_dataset, int32_t mode, float *data, int64_t rows,...)
Sets the values for a single data column using single-precision floating-point numbers.
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
int32_t SDDS_DefineSimpleColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data column within the SDDS dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:856
int32_t SDDS_IsBigEndianMachine()
Determines whether the current machine uses big-endian byte ordering.
#define SDDS_FLOAT
Identifier for the float data type.
Definition SDDStypes.h:43
long fexists(const char *filename)
Checks if a file exists.
Definition fexists.c:27
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584