SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sdds2stl.c File Reference

Detailed Description

Converts SDDS files into binary STL (STereo-Lithography) files.

This program reads an SDDS (Self Describing Data Set) file, extracts normal vectors and vertex coordinates, and writes them into a binary STL file format suitable for 3D modeling and printing. It supports both big-endian and little-endian systems for portability and adheres to SDDS conventions for data processing.

Usage

sdds2stl [<inputFile>] [<outputFile>] [-pipe[=input]]

Options

Options Description
-pipe Use piped input/output for SDDS files.

Requirements

  • The input SDDS file must include the following columns:
    • NormalVectorX, NormalVectorY, NormalVectorZ
    • Vertex1X, Vertex1Y, Vertex1Z
    • Vertex2X, Vertex2Y, Vertex2Z
    • Vertex3X, Vertex3Y, Vertex3Z
  • The columns should be of a numeric type supported by SDDS.
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
R. Soliday

Definition in file sdds2stl.c.

#include "mdb.h"
#include "SDDS.h"
#include "scan.h"

Go to the source code of this file.

Functions

float float_reverse_bytes (float x)
 
int main (int argc, char **argv)
 

Function Documentation

◆ float_reverse_bytes()

float float_reverse_bytes ( float x)

Definition at line 273 of file sdds2stl.c.

273 {
274 char c;
275 union {
276 float yfloat;
277 char ychar[4];
278 } y;
279
280 y.yfloat = x;
281
282 c = y.ychar[0];
283 y.ychar[0] = y.ychar[3];
284 y.ychar[3] = c;
285
286 c = y.ychar[1];
287 y.ychar[1] = y.ychar[2];
288 y.ychar[2] = c;
289
290 return y.yfloat;
291}

◆ main()

int main ( int argc,
char ** argv )

Definition at line 65 of file sdds2stl.c.

65 {
66 char *input = NULL, *output = NULL;
67 SDDS_DATASET SDDS_dataset;
68 SCANNED_ARG *scanned;
69 long i_arg;
70 unsigned long pipe_flags = 0;
71
72 int i;
73 int64_t rows = 0;
74 int32_t row, bsrows;
75 float *normal_vector[3];
76 float *vertex1[3];
77 float *vertex2[3];
78 float *vertex3[3];
79 short attribute = 0;
80 FILE *fd;
81 int32_t big_endian_machine = 0;
82 float temp;
83
85 argc = scanargs(&scanned, argc, argv);
86 if (argc < 2) {
87 fprintf(stderr, "%s", usage);
88 return 1;
89 }
90
91 for (i_arg = 1; i_arg < argc; i_arg++) {
92 if (scanned[i_arg].arg_type == OPTION) {
93 switch (match_string(scanned[i_arg].list[0], option, N_OPTIONS, 0)) {
94 case SET_PIPE:
95 if (!processPipeOption(scanned[i_arg].list + 1, scanned[i_arg].n_items - 1, &pipe_flags)) {
96 fprintf(stderr, "sdds2stl: invalid -pipe syntax\n");
97 return 1;
98 }
99 break;
100 default:
101 fprintf(stderr, "sdds2stl: invalid option seen\n%s", usage);
102 return 1;
103 }
104 } else {
105 if (!input)
106 SDDS_CopyString(&input, scanned[i_arg].list[0]);
107 else if (!output)
108 SDDS_CopyString(&output, scanned[i_arg].list[0]);
109 else {
110 fprintf(stderr, "sdds2stl: too many filenames\n%s", usage);
111 return 1;
112 }
113 }
114 }
115
116 if (pipe_flags & USE_STDIN)
117 processFilenames("sdds2tiff", &input, &output, USE_STDIN, 1, NULL);
118
119 if (!SDDS_InitializeInput(&SDDS_dataset, input))
120 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
121
122 if ((SDDS_CheckColumn(&SDDS_dataset, "NormalVectorX", NULL, SDDS_ANY_NUMERIC_TYPE, NULL)) != SDDS_CHECK_OKAY) {
123 fprintf(stderr, "sdds2stl: NormalVectorX column not found.\n");
124 return 1;
125 }
126
127 if ((SDDS_CheckColumn(&SDDS_dataset, "NormalVectorY", NULL, SDDS_ANY_NUMERIC_TYPE, NULL)) != SDDS_CHECK_OKAY) {
128 fprintf(stderr, "sdds2stl: NormalVectorX column not found.\n");
129 return 1;
130 }
131
132 if ((SDDS_CheckColumn(&SDDS_dataset, "NormalVectorZ", NULL, SDDS_ANY_NUMERIC_TYPE, NULL)) != SDDS_CHECK_OKAY) {
133 fprintf(stderr, "sdds2stl: NormalVectorX column not found.\n");
134 return 1;
135 }
136
137 if ((SDDS_CheckColumn(&SDDS_dataset, "Vertex1X", NULL, SDDS_ANY_NUMERIC_TYPE, NULL)) != SDDS_CHECK_OKAY) {
138 fprintf(stderr, "sdds2stl: Vertex1X column not found.\n");
139 return 1;
140 }
141
142 if ((SDDS_CheckColumn(&SDDS_dataset, "Vertex1Y", NULL, SDDS_ANY_NUMERIC_TYPE, NULL)) != SDDS_CHECK_OKAY) {
143 fprintf(stderr, "sdds2stl: Vertex1Y column not found.\n");
144 return 1;
145 }
146
147 if ((SDDS_CheckColumn(&SDDS_dataset, "Vertex1Z", NULL, SDDS_ANY_NUMERIC_TYPE, NULL)) != SDDS_CHECK_OKAY) {
148 fprintf(stderr, "sdds2stl: Vertex1Z column not found.\n");
149 return 1;
150 }
151
152 if ((SDDS_CheckColumn(&SDDS_dataset, "Vertex2X", NULL, SDDS_ANY_NUMERIC_TYPE, NULL)) != SDDS_CHECK_OKAY) {
153 fprintf(stderr, "sdds2stl: Vertex2X column not found.\n");
154 return 1;
155 }
156
157 if ((SDDS_CheckColumn(&SDDS_dataset, "Vertex2Y", NULL, SDDS_ANY_NUMERIC_TYPE, NULL)) != SDDS_CHECK_OKAY) {
158 fprintf(stderr, "sdds2stl: Vertex2Y column not found.\n");
159 return 1;
160 }
161
162 if ((SDDS_CheckColumn(&SDDS_dataset, "Vertex2Z", NULL, SDDS_ANY_NUMERIC_TYPE, NULL)) != SDDS_CHECK_OKAY) {
163 fprintf(stderr, "sdds2stl: Vertex2Z column not found.\n");
164 return 1;
165 }
166
167 if ((SDDS_CheckColumn(&SDDS_dataset, "Vertex3X", NULL, SDDS_ANY_NUMERIC_TYPE, NULL)) != SDDS_CHECK_OKAY) {
168 fprintf(stderr, "sdds2stl: Vertex3X column not found.\n");
169 return 1;
170 }
171
172 if ((SDDS_CheckColumn(&SDDS_dataset, "Vertex3Y", NULL, SDDS_ANY_NUMERIC_TYPE, NULL)) != SDDS_CHECK_OKAY) {
173 fprintf(stderr, "sdds2stl: Vertex3Y column not found.\n");
174 return 1;
175 }
176
177 if ((SDDS_CheckColumn(&SDDS_dataset, "Vertex3Z", NULL, SDDS_ANY_NUMERIC_TYPE, NULL)) != SDDS_CHECK_OKAY) {
178 fprintf(stderr, "sdds2stl: Vertex3Z column not found.\n");
179 return 1;
180 }
181
182 if (SDDS_ReadTable(&SDDS_dataset) <= 0) {
183 fprintf(stderr, "sdds2stl: Unable to read SDDS page.\n");
184 return 1;
185 }
186
187 rows = SDDS_RowCount(&SDDS_dataset);
188 if (rows > INT32_MAX) {
189 fprintf(stderr, "sdds2stl: Too many rows input file for conversion to STL format\n");
190 return 1;
191 }
192
193 for (i = 0; i < 3; i++) {
194 normal_vector[i] = malloc(sizeof(*(normal_vector[i])) * rows);
195 vertex1[i] = malloc(sizeof(*(vertex1[i])) * rows);
196 vertex2[i] = malloc(sizeof(*(vertex2[i])) * rows);
197 vertex3[i] = malloc(sizeof(*(vertex3[i])) * rows);
198 }
199
200 normal_vector[0] = SDDS_GetColumnInFloats(&SDDS_dataset, "NormalVectorX");
201 normal_vector[1] = SDDS_GetColumnInFloats(&SDDS_dataset, "NormalVectorY");
202 normal_vector[2] = SDDS_GetColumnInFloats(&SDDS_dataset, "NormalVectorZ");
203 vertex1[0] = SDDS_GetColumnInFloats(&SDDS_dataset, "Vertex1X");
204 vertex1[1] = SDDS_GetColumnInFloats(&SDDS_dataset, "Vertex1Y");
205 vertex1[2] = SDDS_GetColumnInFloats(&SDDS_dataset, "Vertex1Z");
206 vertex2[0] = SDDS_GetColumnInFloats(&SDDS_dataset, "Vertex2X");
207 vertex2[1] = SDDS_GetColumnInFloats(&SDDS_dataset, "Vertex2Y");
208 vertex2[2] = SDDS_GetColumnInFloats(&SDDS_dataset, "Vertex2Z");
209 vertex3[0] = SDDS_GetColumnInFloats(&SDDS_dataset, "Vertex3X");
210 vertex3[1] = SDDS_GetColumnInFloats(&SDDS_dataset, "Vertex3Y");
211 vertex3[2] = SDDS_GetColumnInFloats(&SDDS_dataset, "Vertex3Z");
212
213 if (!SDDS_Terminate(&SDDS_dataset))
214 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
215
216 if (!output) {
217#if defined(_WIN32)
218 if (_setmode(_fileno(stdout), _O_BINARY) == -1) {
219 fprintf(stderr, "error: unable to set stdout to binary mode\n");
220 exit(1);
221 }
222#endif
223 fd = stdout;
224 } else
225 fd = fopen(output, "wb");
226
227 big_endian_machine = SDDS_IsBigEndianMachine();
228
229 fprintf(fd, "STL BINARY FILE CREATED BY SDDS2STL --------------------------------------------");
230 if (big_endian_machine) {
231 bsrows = rows;
232 SDDS_SwapLong((int32_t *)&bsrows);
233 fwrite(&bsrows, sizeof(int32_t), 1, fd);
234 for (row = 0; row < rows; row++) {
235 for (i = 0; i < 3; i++) {
236 temp = float_reverse_bytes(normal_vector[i][row]);
237 fwrite(&temp, sizeof(float), 1, fd);
238 }
239 for (i = 0; i < 3; i++) {
240 temp = float_reverse_bytes(vertex1[i][row]);
241 fwrite(&temp, sizeof(float), 1, fd);
242 }
243 for (i = 0; i < 3; i++) {
244 temp = float_reverse_bytes(vertex2[i][row]);
245 fwrite(&temp, sizeof(float), 1, fd);
246 }
247 for (i = 0; i < 3; i++) {
248 temp = float_reverse_bytes(vertex3[i][row]);
249 fwrite(&temp, sizeof(float), 1, fd);
250 }
251 fwrite(&attribute, sizeof(short), 1, fd);
252 }
253 } else {
254 fwrite(&rows, sizeof(int32_t), 1, fd);
255 for (row = 0; row < rows; row++) {
256 for (i = 0; i < 3; i++)
257 fwrite(&(normal_vector[i][row]), sizeof(float), 1, fd);
258 for (i = 0; i < 3; i++)
259 fwrite(&(vertex1[i][row]), sizeof(float), 1, fd);
260 for (i = 0; i < 3; i++)
261 fwrite(&(vertex2[i][row]), sizeof(float), 1, fd);
262 for (i = 0; i < 3; i++)
263 fwrite(&(vertex3[i][row]), sizeof(float), 1, fd);
264 fwrite(&attribute, sizeof(short), 1, fd);
265 }
266 }
267
268 fclose(fd);
269
270 return 1;
271}
void SDDS_SwapLong(int32_t *data)
Swaps the endianness of a 32-bit integer.
float * SDDS_GetColumnInFloats(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of floats, considering only rows marke...
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_CheckColumn(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a column exists in the SDDS dataset with the specified name, units, and type.
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_ANY_NUMERIC_TYPE
Special identifier used by SDDS_Check*() routines to accept any numeric type.
Definition SDDStypes.h:157
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