#define PROG_NAME "salamic_slice" #define PROG_DESC "topological slicing of triangle meshes for 3D printing" #define PROG_VERS "1.0" #define salamic_slice_C_COPYRIGHT \ "Copyright © 2015 by Federal Technological Universioty of Parana (UTFPR) and State University of Campinas (UNICAMP)" /* Last edited on 2015-10-03 22:12:53 by stolfilocal */ #define PROG_HELP \ " " PROG_NAME " \\\n" \ " -blabber {AMOUNT} \\\n" \ " " argparser_help_info_HELP " \\\n" \ " < {INFILE} \\\n" \ " > {OUTFILE}" #define PROG_INFO \ "NAME\n" \ " " PROG_NAME " - " PROG_DESC "\n" \ "\n" \ "SYNOPSIS\n" \ PROG_HELP "\n" \ "\n" \ "DESCRIPTION\n" \ " The program bla bla bla" \ " bla bla bla bla {X+Y} bla bla" \ " bla {INFILE} bla \"foobar.ppm\" bla bla bla\n" \ "\n" \ " Beware that bla bla bla BLEBBLE BLOB bla" \ " bla bla bla bla.\n" \ "\n" \ "INPUT FILE\n" \ "\n" \ "OUTPUT FILE\n" \ " " salamic_closer_output_file_name_INFO "\n" \ "\n" \ " " salamic_section_format_INFO "\n" \ "\n" \ "OPTIONS\n" \ " -blabber {AMOUNT}\n" \ " Blabbers for that {AMOUNT}. May also bla" \ " bla bla bla bla bla bla bla bla bla bla bla bla" \ " bla bla bla bla bla bla bla.\n" \ "\n" \ "DOCUMENTATION OPTIONS\n" \ argparser_help_info_HELP_INFO "\n" \ "\n" \ "SEE ALSO\n" \ " baloney(1).\n" \ "\n" \ "AUTHOR\n" \ " Created 2015-09-25 by Jorge Stolfi, IC-UNICAMP from {SliceMain.cpp} by Minetto and Habib.\n" \ "\n" \ "MODIFICATION HISTORY\n" \ " 2015-09-26 Converted to C by J. Stolfi, IC-UNICAMP.\n" \ "\n" \ "WARRANTY\n" \ argparser_help_info_NO_WARRANTY "\n" \ "\n" \ "RIGHTS\n" \ " " salamic_slice_C_COPYRIGHT ".\n" \ "\n" \ argparser_help_info_STANDARD_RIGHTS #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // #include // #include typedef struct salamic_options_t { /* Quantization: */ float eps; /* Vertex and plane coords are multiple of {eps}. */ /* Parameters for slicing planes: */ float startZ; /* First {Z} coordinate (mm), or {NAN}. */ float deltaZ; /* Spacing for uniform slicing (mm), or {NAN}. */ char *planeZFile; /* Name of file with plane {Z}-coords. */ /* Input files: */ char *modelFile; /* Name of file with the input STL model. */ bool_t binary; /* FALSE if ASCII STL format, TRUE if binary STL format. */ bool_t preSorted; /* If true, assumes that the input triangles be sorted by increasing {Z}. */ int nfGuess; /* Hint about number of triangles in the mesh. */ /* Algorithms: */ char *slicer; /* Slicer algorithm ("TRIVIAL", "MINETTO", "SANG", etc.). */ char *closer; /* Loop closing algorithm ("TRIVIAL", "MINETTO", etc.). */ /* Output files: */ char *outPrefix; /* Prefix for output file names. */ } salamic_options_t; /* INTERNAL PROTOTYPES */ int main(int argc, char **argv); /* Main program. */ salamic_options_t *salamic_parse_options(int argc, char **argv); /* Parses the command line arguments and packs them as an {options_t}. */ /* IMPLEMENTATIONS */ int main(int argc, char **argv) { /* Parse the command line options: */ salamic_options_t *o = salamic_parse_options(argc, argv); /* Get the input triangle mesh {mesh} and its {Z}-range {minZ,maxZ}: */ salamic_mesh_t *mesh = salamic_mesh_read_STL(o->modelFile, o->binary, o->eps, o->nfGuess, o->preSorted); /* Get the Z-coordinates of the slicing planes, in increasing order: */ int32_t minZ = mesh->minP.c[2]; int32_t maxZ = mesh->maxP.c[2]; bool_t uniform = ((! isnan(o->deltaZ)) && (o->deltaZ != 0)); int_vec_t planeZ; /* The {Z}-coordinates of the slicing planes, quantized by {eps}. */ if (uniform) { planeZ = salamic_planes_get_uniform(o->startZ, o->deltaZ, o->eps, minZ, maxZ); } else { planeZ = salamic_planes_get_adaptive(o->planeZFile, o->eps, minZ, maxZ); } /* Process it: */ salamic_stats_t st; salamic_slicer_slice(mesh, o->preSorted, &planeZ, uniform, o->slicer, o->closer, o->outPrefix, &st); /* Show statistics: */ salamic_stats_print(stderr, &st); fprintf(stderr, "done.\n"); return 0; } /* ARGUMENT PARSING */ #define salamic_eps_MIN (0.000001f) /* Minimum value of fundamental unit {eps} (mm). */ #define salamic_eps_MAX (1.0f) /* Maximum value of fundamental unit {eps} (mm). */ #define salamic_deltaZ_MINQ 10 /* Minimum plane spacing for uniform slicing, as multiple of fundamental unit {eps}. */ #define salamic_deltaZ_MAX 1000.0 /* Maximum plane spacing for uniform slicing (mm). */ #define salamic_startZ_MAX (10000.0f) /* Max {Z} coordinate of reference plane (mm). */ #define salamic_startZ_DEFAULTQ 1 /* Default {Z} coordinate of start plane, an odd multiple of fundamental unit {eps}. */ #define salamic_nfGuess_MAX (500*1000*1000) /* Default guess for the number of faces in the mesh. */ #define salamic_nfGuess_DEFAULT 100000 /* Maximum guess for the number of faces in the mesh. */ salamic_options_t *salamic_parse_options(int argc, char** argv) { /* Initialize argument parser: */ argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); /* Allocate the command line argument record: */ salamic_options_t *o = notnull(malloc(sizeof(salamic_options_t)), "no mem"); /* Parse keyword parameters: */ /* Fundamental unit: */ argparser_get_keyword(pp, "-eps"); o->eps = (float)argparser_get_next_double(pp, salamic_eps_MIN, salamic_eps_MAX); /* {Z}-coordinates of planes: */ if (argparser_keyword_present(pp, "-planeZFile")) { /* Read plane positions from file: */ o->planeZFile = argparser_get_next_non_keyword(pp); o->deltaZ = NAN; o->startZ = NAN; } else { /* Uniform slicing: */ argparser_get_keyword(pp, "-deltaZ"); o->deltaZ = (float)argparser_get_next_double(pp, salamic_deltaZ_MINQ*o->eps, salamic_deltaZ_MAX); if (argparser_keyword_present(pp, "-startZ")) { o->startZ = (float)argparser_get_next_double(pp, -salamic_startZ_MAX, +salamic_startZ_MAX); } else { o->startZ = o->eps; } o->planeZFile = NULL; } /* Model, format, and size guess: */ argparser_get_keyword(pp, "-modelFile"); o->modelFile = argparser_get_next_non_keyword(pp); argparser_get_keyword(pp, "-format"); if (argparser_keyword_present_next(pp, "ascii")) { o->binary = FALSE; } else if (argparser_keyword_present_next(pp, "binary")) { o->binary = TRUE; } else { argparser_error(pp, "unrecognized file format"); } o->preSorted = argparser_keyword_present(pp, "-preSorted"); if (argparser_keyword_present(pp, "-nfGuess")) { o->nfGuess = (int)argparser_get_next_int(pp, 0, salamic_nfGuess_MAX); } else { o->nfGuess = salamic_nfGuess_DEFAULT; } /* Algorithms: */ if (argparser_keyword_present(pp, "-slicer")) { o->slicer = argparser_get_next_non_keyword(pp); } else { o->slicer = "MINETTO"; } if (argparser_keyword_present(pp, "-closer")) { o->closer = argparser_get_next_non_keyword(pp); } else { o->closer = "STOLFI"; } argparser_get_keyword(pp, "-outPrefix"); o->outPrefix = argparser_get_next_non_keyword(pp); /* Parse positional arguments: */ argparser_skip_parsed(pp); /* Check for spurious arguments: */ argparser_finish(pp); return o; }