diff --git a/src/admesh/connect.cpp b/src/admesh/connect.cpp index 9553e7c4d..5ae03597e 100644 --- a/src/admesh/connect.cpp +++ b/src/admesh/connect.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include "stl.h" @@ -124,7 +125,9 @@ struct HashTableEdges { for (HashEdge *temp = this->heads[i]; this->heads[i] != this->tail; temp = this->heads[i]) { this->heads[i] = this->heads[i]->next; delete temp; +#ifndef NDEBUG ++ this->freed; +#endif /* NDEBUG */ } } this->heads.clear(); @@ -139,7 +142,9 @@ struct HashTableEdges { if (link == this->tail) { // This list doesn't have any edges currently in it. Add this one. HashEdge *new_edge = new HashEdge(edge); +#ifndef NDEBUG ++ this->malloced; +#endif /* NDEBUG */ new_edge->next = this->tail; this->heads[chain_number] = new_edge; } else if (edges_equal(edge, *link)) { @@ -148,18 +153,24 @@ struct HashTableEdges { // Delete the matched edge from the list. this->heads[chain_number] = link->next; delete link; +#ifndef NDEBUG ++ this->freed; +#endif /* NDEBUG */ } else { // Continue through the rest of the list. for (;;) { if (link->next == this->tail) { // This is the last item in the list. Insert a new edge. HashEdge *new_edge = new HashEdge; +#ifndef NDEBUG ++ this->malloced; +#endif /* NDEBUG */ *new_edge = edge; new_edge->next = this->tail; link->next = new_edge; +#ifndef NDEBUG ++ this->collisions; +#endif /* NDEBUG */ break; } if (edges_equal(edge, *link->next)) { @@ -169,12 +180,16 @@ struct HashTableEdges { HashEdge *temp = link->next; link->next = link->next->next; delete temp; +#ifndef NDEBUG ++ this->freed; +#endif /* NDEBUG */ break; } // This is not a match. Go to the next link. link = link->next; +#ifndef NDEBUG ++ this->collisions; +#endif /* NDEBUG */ } } } @@ -184,9 +199,11 @@ struct HashTableEdges { HashEdge* tail; int M; +#ifndef NDEBUG size_t malloced = 0; size_t freed = 0; size_t collisions = 0; +#endif /* NDEBUG */ private: static inline size_t hash_size_from_nr_faces(const size_t nr_faces) @@ -366,7 +383,7 @@ static void match_neighbors_nearby(stl_file *stl, const HashEdge &edge_a, const if (facet_num == first_facet) { // back to the beginning - printf("Back to the first facet changing vertices: probably a mobius part.\nTry using a smaller tolerance or don't do a nearby check\n"); + BOOST_LOG_TRIVIAL(info) << "Back to the first facet changing vertices: probably a mobius part. Try using a smaller tolerance or don't do a nearby check."; return; } } @@ -506,7 +523,7 @@ void stl_remove_unconnected_facets(stl_file *stl) if (neighbors.neighbor[i] != -1) { int &other_face_idx = stl->neighbors_start[neighbors.neighbor[i]].neighbor[(neighbors.which_vertex_not[i] + 1) % 3]; if (other_face_idx != stl->stats.number_of_facets) { - printf("in remove_facet: neighbor = %d numfacets = %d this is wrong\n", other_face_idx, stl->stats.number_of_facets); + BOOST_LOG_TRIVIAL(info) << "in remove_facet: neighbor = " << other_face_idx << " numfacets = " << stl->stats.number_of_facets << " this is wrong"; return; } other_face_idx = facet_number; @@ -697,7 +714,7 @@ void stl_fill_holes(stl_file *stl) if (facet_num == first_facet) { // back to the beginning - printf("Back to the first facet filling holes: probably a mobius part.\nTry using a smaller tolerance or don't do a nearby check\n"); + BOOST_LOG_TRIVIAL(info) << "Back to the first facet filling holes: probably a mobius part. Try using a smaller tolerance or don't do a nearby check."; return; } } diff --git a/src/admesh/shared.cpp b/src/admesh/shared.cpp index 7da2841b0..fe6d5e656 100644 --- a/src/admesh/shared.cpp +++ b/src/admesh/shared.cpp @@ -25,6 +25,7 @@ #include +#include #include #include "stl.h" @@ -129,10 +130,7 @@ bool its_write_off(const indexed_triangle_set &its, const char *file) /* Open the file */ FILE *fp = boost::nowide::fopen(file, "w"); if (fp == nullptr) { - char *error_msg = (char*)malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file); - perror(error_msg); - free(error_msg); + BOOST_LOG_TRIVIAL(error) << "stl_write_ascii: Couldn't open " << file << " for writing"; return false; } @@ -151,10 +149,7 @@ bool its_write_vrml(const indexed_triangle_set &its, const char *file) /* Open the file */ FILE *fp = boost::nowide::fopen(file, "w"); if (fp == nullptr) { - char *error_msg = (char*)malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file); - perror(error_msg); - free(error_msg); + BOOST_LOG_TRIVIAL(error) << "stl_write_vrml: Couldn't open " << file << " for writing"; return false; } @@ -196,10 +191,7 @@ bool its_write_obj(const indexed_triangle_set &its, const char *file) FILE *fp = boost::nowide::fopen(file, "w"); if (fp == nullptr) { - char* error_msg = (char*)malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file); - perror(error_msg); - free(error_msg); + BOOST_LOG_TRIVIAL(error) << "stl_write_obj: Couldn't open " << file << " for writing"; return false; } diff --git a/src/admesh/stl.h b/src/admesh/stl.h index bb5d25296..500d6bfdb 100644 --- a/src/admesh/stl.h +++ b/src/admesh/stl.h @@ -242,7 +242,7 @@ inline bool stl_vertex_lower(const stl_vertex &a, const stl_vertex &b) { } extern void stl_calculate_volume(stl_file *stl); -extern void stl_repair(stl_file *stl, int fixall_flag, int exact_flag, int tolerance_flag, float tolerance, int increment_flag, float increment, int nearby_flag, int iterations, int remove_unconnected_flag, int fill_holes_flag, int normal_directions_flag, int normal_values_flag, int reverse_all_flag, int verbose_flag); +extern void stl_repair(stl_file *stl, bool fixall_flag, bool exact_flag, bool tolerance_flag, float tolerance, bool increment_flag, float increment, bool nearby_flag, int iterations, bool remove_unconnected_flag, bool fill_holes_flag, bool normal_directions_flag, bool normal_values_flag, bool reverse_all_flag, bool verbose_flag); extern void stl_reset(stl_file *stl); extern void stl_allocate(stl_file *stl); diff --git a/src/admesh/stl_io.cpp b/src/admesh/stl_io.cpp index 8f809d379..dc4e4a7db 100644 --- a/src/admesh/stl_io.cpp +++ b/src/admesh/stl_io.cpp @@ -24,6 +24,7 @@ #include #include "stl.h" +#include #include #include @@ -107,65 +108,47 @@ Normals fixed : %5d\n", stl->stats.normals_fixed); bool stl_write_ascii(stl_file *stl, const char *file, const char *label) { - char *error_msg; + FILE *fp = boost::nowide::fopen(file, "w"); + if (fp == NULL) { + BOOST_LOG_TRIVIAL(error) << "stl_write_ascii: Couldn't open " << file << " for writing"; + return false; + } - /* Open the file */ - FILE *fp = boost::nowide::fopen(file, "w"); - if(fp == NULL) { - error_msg = (char*) - malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", - file); - perror(error_msg); - free(error_msg); - return false; - } + fprintf(fp, "solid %s\n", label); - fprintf(fp, "solid %s\n", label); + for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { + fprintf(fp, " facet normal % .8E % .8E % .8E\n", + stl->facet_start[i].normal(0), stl->facet_start[i].normal(1), + stl->facet_start[i].normal(2)); + fprintf(fp, " outer loop\n"); + fprintf(fp, " vertex % .8E % .8E % .8E\n", + stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1), + stl->facet_start[i].vertex[0](2)); + fprintf(fp, " vertex % .8E % .8E % .8E\n", + stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1), + stl->facet_start[i].vertex[1](2)); + fprintf(fp, " vertex % .8E % .8E % .8E\n", + stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), + stl->facet_start[i].vertex[2](2)); + fprintf(fp, " endloop\n"); + fprintf(fp, " endfacet\n"); + } - for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { - fprintf(fp, " facet normal % .8E % .8E % .8E\n", - stl->facet_start[i].normal(0), stl->facet_start[i].normal(1), - stl->facet_start[i].normal(2)); - fprintf(fp, " outer loop\n"); - fprintf(fp, " vertex % .8E % .8E % .8E\n", - stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1), - stl->facet_start[i].vertex[0](2)); - fprintf(fp, " vertex % .8E % .8E % .8E\n", - stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1), - stl->facet_start[i].vertex[1](2)); - fprintf(fp, " vertex % .8E % .8E % .8E\n", - stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), - stl->facet_start[i].vertex[2](2)); - fprintf(fp, " endloop\n"); - fprintf(fp, " endfacet\n"); - } - - fprintf(fp, "endsolid %s\n", label); - - fclose(fp); - return true; + fprintf(fp, "endsolid %s\n", label); + fclose(fp); + return true; } bool stl_print_neighbors(stl_file *stl, char *file) { - FILE *fp; - char *error_msg; + FILE *fp = boost::nowide::fopen(file, "w"); + if (fp == NULL) { + BOOST_LOG_TRIVIAL(error) << "stl_print_neighbors: Couldn't open " << file << " for writing"; + return false; + } - /* Open the file */ - fp = boost::nowide::fopen(file, "w"); - if(fp == NULL) { - error_msg = (char*) - malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_print_neighbors: Couldn't open %s for writing", - file); - perror(error_msg); - free(error_msg); - return false; - } - - for (uint32_t i = 0; i < stl->stats.number_of_facets; i++) { - fprintf(fp, "%d, %d,%d, %d,%d, %d,%d\n", + for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { + fprintf(fp, "%d, %d,%d, %d,%d, %d,%d\n", i, stl->neighbors_start[i].neighbor[0], (int)stl->neighbors_start[i].which_vertex_not[0], @@ -173,62 +156,54 @@ bool stl_print_neighbors(stl_file *stl, char *file) (int)stl->neighbors_start[i].which_vertex_not[1], stl->neighbors_start[i].neighbor[2], (int)stl->neighbors_start[i].which_vertex_not[2]); - } - fclose(fp); - return true; + } + fclose(fp); + return true; } #ifndef BOOST_LITTLE_ENDIAN // Swap a buffer of 32bit data from little endian to big endian and vice versa. void stl_internal_reverse_quads(char *buf, size_t cnt) { - for (size_t i = 0; i < cnt; i += 4) { - std::swap(buf[i], buf[i+3]); - std::swap(buf[i+1], buf[i+2]); - } + for (size_t i = 0; i < cnt; i += 4) { + std::swap(buf[i], buf[i+3]); + std::swap(buf[i+1], buf[i+2]); + } } #endif bool stl_write_binary(stl_file *stl, const char *file, const char *label) { - FILE *fp; - char *error_msg; + FILE *fp = boost::nowide::fopen(file, "wb"); + if (fp == NULL) { + BOOST_LOG_TRIVIAL(error) << "stl_write_binary: Couldn't open " << file << " for writing"; + return false; + } - /* Open the file */ - fp = boost::nowide::fopen(file, "wb"); - if(fp == NULL) { - error_msg = (char*) - malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_write_binary: Couldn't open %s for writing", - file); - perror(error_msg); - free(error_msg); - return false; - } + fprintf(fp, "%s", label); + for (size_t i = strlen(label); i < LABEL_SIZE; ++ i) + putc(0, fp); - fprintf(fp, "%s", label); - for(size_t i = strlen(label); i < LABEL_SIZE; i++) putc(0, fp); - - fseek(fp, LABEL_SIZE, SEEK_SET); + fseek(fp, LABEL_SIZE, SEEK_SET); #ifdef BOOST_LITTLE_ENDIAN - fwrite(&stl->stats.number_of_facets, 4, 1, fp); - for (const stl_facet &facet : stl->facet_start) - fwrite(&facet, SIZEOF_STL_FACET, 1, fp); + fwrite(&stl->stats.number_of_facets, 4, 1, fp); + for (const stl_facet &facet : stl->facet_start) + fwrite(&facet, SIZEOF_STL_FACET, 1, fp); #else /* BOOST_LITTLE_ENDIAN */ - char buffer[50]; - // Convert the number of facets to little endian. - memcpy(buffer, &stl->stats.number_of_facets, 4); - stl_internal_reverse_quads(buffer, 4); - fwrite(buffer, 4, 1, fp); - for (i = 0; i < stl->stats.number_of_facets; ++ i) { - memcpy(buffer, stl->facet_start + i, 50); - // Convert to little endian. - stl_internal_reverse_quads(buffer, 48); - fwrite(buffer, SIZEOF_STL_FACET, 1, fp); - } + char buffer[50]; + // Convert the number of facets to little endian. + memcpy(buffer, &stl->stats.number_of_facets, 4); + stl_internal_reverse_quads(buffer, 4); + fwrite(buffer, 4, 1, fp); + for (i = 0; i < stl->stats.number_of_facets; ++ i) { + memcpy(buffer, stl->facet_start + i, 50); + // Convert to little endian. + stl_internal_reverse_quads(buffer, 48); + fwrite(buffer, SIZEOF_STL_FACET, 1, fp); + } #endif /* BOOST_LITTLE_ENDIAN */ - fclose(fp); - return true; + fclose(fp); + return true; } void stl_write_vertex(stl_file *stl, int facet, int vertex) @@ -260,53 +235,39 @@ void stl_write_neighbor(stl_file *stl, int facet) bool stl_write_quad_object(stl_file *stl, char *file) { - FILE *fp; - char *error_msg; - stl_vertex connect_color = stl_vertex::Zero(); - stl_vertex uncon_1_color = stl_vertex::Zero(); - stl_vertex uncon_2_color = stl_vertex::Zero(); - stl_vertex uncon_3_color = stl_vertex::Zero(); - stl_vertex color; + stl_vertex connect_color = stl_vertex::Zero(); + stl_vertex uncon_1_color = stl_vertex::Zero(); + stl_vertex uncon_2_color = stl_vertex::Zero(); + stl_vertex uncon_3_color = stl_vertex::Zero(); + stl_vertex color; - /* Open the file */ - fp = boost::nowide::fopen(file, "w"); - if(fp == NULL) { - error_msg = (char*) - malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_write_quad_object: Couldn't open %s for writing", - file); - perror(error_msg); - free(error_msg); - return false; - } + FILE *fp = boost::nowide::fopen(file, "w"); + if (fp == NULL) { + BOOST_LOG_TRIVIAL(error) << "stl_write_quad_object: Couldn't open " << file << " for writing"; + return false; + } - fprintf(fp, "CQUAD\n"); - for (uint32_t i = 0; i < stl->stats.number_of_facets; i++) { - int j = ((stl->neighbors_start[i].neighbor[0] == -1) + - (stl->neighbors_start[i].neighbor[1] == -1) + - (stl->neighbors_start[i].neighbor[2] == -1)); - if(j == 0) { - color = connect_color; - } else if(j == 1) { - color = uncon_1_color; - } else if(j == 2) { - color = uncon_2_color; - } else { - color = uncon_3_color; - } - fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n", + fprintf(fp, "CQUAD\n"); + for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { + switch (stl->neighbors_start[i].num_neighbors_missing()) { + case 0: color = connect_color; break; + case 1: color = uncon_1_color; break; + case 2: color = uncon_2_color; break; + default: color = uncon_3_color; + } + fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n", stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1), stl->facet_start[i].vertex[0](2), color(0), color(1), color(2)); - fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n", + fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n", stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1), stl->facet_start[i].vertex[1](2), color(0), color(1), color(2)); - fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n", + fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n", stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), stl->facet_start[i].vertex[2](2), color(0), color(1), color(2)); - fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n", + fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n", stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), stl->facet_start[i].vertex[2](2), color(0), color(1), color(2)); @@ -317,47 +278,37 @@ bool stl_write_quad_object(stl_file *stl, char *file) bool stl_write_dxf(stl_file *stl, const char *file, char *label) { - FILE *fp; - char *error_msg; + FILE *fp = boost::nowide::fopen(file, "w"); + if (fp == NULL) { + BOOST_LOG_TRIVIAL(error) << "stl_write_quad_object: Couldn't open " << file << " for writing"; + return false; + } - /* Open the file */ - fp = boost::nowide::fopen(file, "w"); - if(fp == NULL) { - error_msg = (char*) - malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", - file); - perror(error_msg); - free(error_msg); - return false; - } + fprintf(fp, "999\n%s\n", label); + fprintf(fp, "0\nSECTION\n2\nHEADER\n0\nENDSEC\n"); + fprintf(fp, "0\nSECTION\n2\nTABLES\n0\nTABLE\n2\nLAYER\n70\n1\n\ + 0\nLAYER\n2\n0\n70\n0\n62\n7\n6\nCONTINUOUS\n0\nENDTAB\n0\nENDSEC\n"); + fprintf(fp, "0\nSECTION\n2\nBLOCKS\n0\nENDSEC\n"); - fprintf(fp, "999\n%s\n", label); - fprintf(fp, "0\nSECTION\n2\nHEADER\n0\nENDSEC\n"); - fprintf(fp, "0\nSECTION\n2\nTABLES\n0\nTABLE\n2\nLAYER\n70\n1\n\ -0\nLAYER\n2\n0\n70\n0\n62\n7\n6\nCONTINUOUS\n0\nENDTAB\n0\nENDSEC\n"); - fprintf(fp, "0\nSECTION\n2\nBLOCKS\n0\nENDSEC\n"); + fprintf(fp, "0\nSECTION\n2\nENTITIES\n"); - fprintf(fp, "0\nSECTION\n2\nENTITIES\n"); + for (uint32_t i = 0; i < stl->stats.number_of_facets; i++) { + fprintf(fp, "0\n3DFACE\n8\n0\n"); + fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n", + stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1), + stl->facet_start[i].vertex[0](2)); + fprintf(fp, "11\n%f\n21\n%f\n31\n%f\n", + stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1), + stl->facet_start[i].vertex[1](2)); + fprintf(fp, "12\n%f\n22\n%f\n32\n%f\n", + stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), + stl->facet_start[i].vertex[2](2)); + fprintf(fp, "13\n%f\n23\n%f\n33\n%f\n", + stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), + stl->facet_start[i].vertex[2](2)); + } - for (uint32_t i = 0; i < stl->stats.number_of_facets; i++) { - fprintf(fp, "0\n3DFACE\n8\n0\n"); - fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n", - stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1), - stl->facet_start[i].vertex[0](2)); - fprintf(fp, "11\n%f\n21\n%f\n31\n%f\n", - stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1), - stl->facet_start[i].vertex[1](2)); - fprintf(fp, "12\n%f\n22\n%f\n32\n%f\n", - stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), - stl->facet_start[i].vertex[2](2)); - fprintf(fp, "13\n%f\n23\n%f\n33\n%f\n", - stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), - stl->facet_start[i].vertex[2](2)); - } - - fprintf(fp, "0\nENDSEC\n0\nEOF\n"); - - fclose(fp); - return true; + fprintf(fp, "0\nENDSEC\n0\nEOF\n"); + fclose(fp); + return true; } diff --git a/src/admesh/stlinit.cpp b/src/admesh/stlinit.cpp index 44477511f..24fbe9edc 100644 --- a/src/admesh/stlinit.cpp +++ b/src/admesh/stlinit.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -37,118 +38,102 @@ static FILE* stl_open_count_facets(stl_file *stl, const char *file) { - long file_size; - uint32_t header_num_facets; - uint32_t num_facets; - int i; - size_t s; - unsigned char chtest[128]; - int num_lines = 1; - char *error_msg; + // Open the file in binary mode first. + FILE *fp = boost::nowide::fopen(file, "rb"); + if (fp == nullptr) { + BOOST_LOG_TRIVIAL(error) << "stl_open_count_facets: Couldn't open " << file << " for reading"; + return nullptr; + } + // Find size of file. + fseek(fp, 0, SEEK_END); + long file_size = ftell(fp); - /* Open the file in binary mode first */ - FILE *fp = boost::nowide::fopen(file, "rb"); - if (fp == nullptr) { - error_msg = (char*) - malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_initialize: Couldn't open %s for reading", - file); - perror(error_msg); - free(error_msg); - return nullptr; - } - /* Find size of file */ - fseek(fp, 0, SEEK_END); - file_size = ftell(fp); + // Check for binary or ASCII file. + fseek(fp, HEADER_SIZE, SEEK_SET); + unsigned char chtest[128]; + if (! fread(chtest, sizeof(chtest), 1, fp)) { + BOOST_LOG_TRIVIAL(error) << "stl_open_count_facets: The input is an empty file: " << file; + fclose(fp); + return nullptr; + } + stl->stats.type = ascii; + for (size_t s = 0; s < sizeof(chtest); s++) { + if (chtest[s] > 127) { + stl->stats.type = binary; + break; + } + } + rewind(fp); - /* Check for binary or ASCII file */ - fseek(fp, HEADER_SIZE, SEEK_SET); - if (!fread(chtest, sizeof(chtest), 1, fp)) { - perror("The input is an empty file"); - fclose(fp); - return nullptr; - } - stl->stats.type = ascii; - for(s = 0; s < sizeof(chtest); s++) { - if(chtest[s] > 127) { - stl->stats.type = binary; - break; - } - } - rewind(fp); + uint32_t num_facets = 0; - /* Get the header and the number of facets in the .STL file */ - /* If the .STL file is binary, then do the following */ - if(stl->stats.type == binary) { - /* Test if the STL file has the right size */ - if(((file_size - HEADER_SIZE) % SIZEOF_STL_FACET != 0) - || (file_size < STL_MIN_FILE_SIZE)) { - fprintf(stderr, "The file %s has the wrong size.\n", file); - fclose(fp); - return nullptr; - } - num_facets = (file_size - HEADER_SIZE) / SIZEOF_STL_FACET; + // Get the header and the number of facets in the .STL file. + // If the .STL file is binary, then do the following: + if (stl->stats.type == binary) { + // Test if the STL file has the right size. + if (((file_size - HEADER_SIZE) % SIZEOF_STL_FACET != 0) || (file_size < STL_MIN_FILE_SIZE)) { + BOOST_LOG_TRIVIAL(error) << "stl_open_count_facets: The file " << file << " has the wrong size."; + fclose(fp); + return nullptr; + } + num_facets = (file_size - HEADER_SIZE) / SIZEOF_STL_FACET; - /* Read the header */ - if (fread(stl->stats.header, LABEL_SIZE, 1, fp) > 79) { - stl->stats.header[80] = '\0'; - } + // Read the header. + if (fread(stl->stats.header, LABEL_SIZE, 1, fp) > 79) + stl->stats.header[80] = '\0'; - /* Read the int following the header. This should contain # of facets */ - bool header_num_faces_read = fread(&header_num_facets, sizeof(uint32_t), 1, fp) != 0; + // Read the int following the header. This should contain # of facets. + uint32_t header_num_facets; + bool header_num_faces_read = fread(&header_num_facets, sizeof(uint32_t), 1, fp) != 0; #ifndef BOOST_LITTLE_ENDIAN - // Convert from little endian to big endian. - stl_internal_reverse_quads((char*)&header_num_facets, 4); + // Convert from little endian to big endian. + stl_internal_reverse_quads((char*)&header_num_facets, 4); #endif /* BOOST_LITTLE_ENDIAN */ - if (! header_num_faces_read || num_facets != header_num_facets) { - fprintf(stderr, - "Warning: File size doesn't match number of facets in the header\n"); - } - } - /* Otherwise, if the .STL file is ASCII, then do the following */ - else { - /* Reopen the file in text mode (for getting correct newlines on Windows) */ - // fix to silence a warning about unused return value. - // obviously if it fails we have problems.... - fp = boost::nowide::freopen(file, "r", fp); + if (! header_num_faces_read || num_facets != header_num_facets) + BOOST_LOG_TRIVIAL(info) << "stl_open_count_facets: Warning: File size doesn't match number of facets in the header: " << file; + } + // Otherwise, if the .STL file is ASCII, then do the following: + else + { + // Reopen the file in text mode (for getting correct newlines on Windows) + // fix to silence a warning about unused return value. + // obviously if it fails we have problems.... + fp = boost::nowide::freopen(file, "r", fp); - // do another null check to be safe - if(fp == nullptr) { - error_msg = (char*) - malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_initialize: Couldn't open %s for reading", - file); - perror(error_msg); - free(error_msg); - fclose(fp); - return nullptr; - } + // do another null check to be safe + if (fp == nullptr) { + BOOST_LOG_TRIVIAL(error) << "stl_open_count_facets: Couldn't open " << file << " for reading"; + fclose(fp); + return nullptr; + } - /* Find the number of facets */ - char linebuf[100]; - while (fgets(linebuf, 100, fp) != nullptr) { - /* don't count short lines */ - if (strlen(linebuf) <= 4) continue; - - /* skip solid/endsolid lines as broken STL file generators may put several of them */ - if (strncmp(linebuf, "solid", 5) == 0 || strncmp(linebuf, "endsolid", 8) == 0) continue; - - ++num_lines; - } - - rewind(fp); - - /* Get the header */ - for(i = 0; - (i < 80) && (stl->stats.header[i] = getc(fp)) != '\n'; i++); - stl->stats.header[i] = '\0'; /* Lose the '\n' */ - stl->stats.header[80] = '\0'; + // Find the number of facets. + char linebuf[100]; + int num_lines = 1; + while (fgets(linebuf, 100, fp) != nullptr) { + // Don't count short lines. + if (strlen(linebuf) <= 4) + continue; + // Skip solid/endsolid lines as broken STL file generators may put several of them. + if (strncmp(linebuf, "solid", 5) == 0 || strncmp(linebuf, "endsolid", 8) == 0) + continue; + ++ num_lines; + } - num_facets = num_lines / ASCII_LINES_PER_FACET; - } - stl->stats.number_of_facets += num_facets; - stl->stats.original_num_facets = stl->stats.number_of_facets; - return fp; + rewind(fp); + + // Get the header. + int i = 0; + for (; i < 80 && (stl->stats.header[i] = getc(fp)) != '\n'; ++ i) ; + stl->stats.header[i] = '\0'; // Lose the '\n' + stl->stats.header[80] = '\0'; + + num_facets = num_lines / ASCII_LINES_PER_FACET; + } + + stl->stats.number_of_facets += num_facets; + stl->stats.original_num_facets = stl->stats.number_of_facets; + return fp; } /* Reads the contents of the file pointed to by fp into the stl structure, @@ -156,85 +141,82 @@ static FILE* stl_open_count_facets(stl_file *stl, const char *file) time running this for the stl and therefore we should reset our max and min stats. */ static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first) { - stl_facet facet; + if (stl->stats.type == binary) + fseek(fp, HEADER_SIZE, SEEK_SET); + else + rewind(fp); - if(stl->stats.type == binary) { - fseek(fp, HEADER_SIZE, SEEK_SET); - } else { - rewind(fp); - } + char normal_buf[3][32]; + for (uint32_t i = first_facet; i < stl->stats.number_of_facets; ++i) { + stl_facet facet; - char normal_buf[3][32]; - for(uint32_t i = first_facet; i < stl->stats.number_of_facets; i++) { - if(stl->stats.type == binary) - /* Read a single facet from a binary .STL file */ - { - /* we assume little-endian architecture! */ - if (fread(&facet, 1, SIZEOF_STL_FACET, fp) != SIZEOF_STL_FACET) - return false; + if (stl->stats.type == binary) { + // Read a single facet from a binary .STL file. We assume little-endian architecture! + if (fread(&facet, 1, SIZEOF_STL_FACET, fp) != SIZEOF_STL_FACET) + return false; #ifndef BOOST_LITTLE_ENDIAN - // Convert the loaded little endian data to big endian. - stl_internal_reverse_quads((char*)&facet, 48); + // Convert the loaded little endian data to big endian. + stl_internal_reverse_quads((char*)&facet, 48); #endif /* BOOST_LITTLE_ENDIAN */ - } else - /* Read a single facet from an ASCII .STL file */ - { - // skip solid/endsolid - // (in this order, otherwise it won't work when they are paired in the middle of a file) - fscanf(fp, "endsolid%*[^\n]\n"); - fscanf(fp, "solid%*[^\n]\n"); // name might contain spaces so %*s doesn't work and it also can be empty (just "solid") - // Leading space in the fscanf format skips all leading white spaces including numerous new lines and tabs. - int res_normal = fscanf(fp, " facet normal %31s %31s %31s", normal_buf[0], normal_buf[1], normal_buf[2]); - assert(res_normal == 3); - int res_outer_loop = fscanf(fp, " outer loop"); - assert(res_outer_loop == 0); - int res_vertex1 = fscanf(fp, " vertex %f %f %f", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2)); - assert(res_vertex1 == 3); - int res_vertex2 = fscanf(fp, " vertex %f %f %f", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2)); - assert(res_vertex2 == 3); - int res_vertex3 = fscanf(fp, " vertex %f %f %f", &facet.vertex[2](0), &facet.vertex[2](1), &facet.vertex[2](2)); - assert(res_vertex3 == 3); - int res_endloop = fscanf(fp, " endloop"); - assert(res_endloop == 0); - // There is a leading and trailing white space around endfacet to eat up all leading and trailing white spaces including numerous tabs and new lines. - int res_endfacet = fscanf(fp, " endfacet "); - if (res_normal != 3 || res_outer_loop != 0 || res_vertex1 != 3 || res_vertex2 != 3 || res_vertex3 != 3 || res_endloop != 0 || res_endfacet != 0) { - perror("Something is syntactically very wrong with this ASCII STL!"); - return false; - } + } else { + // Read a single facet from an ASCII .STL file + // skip solid/endsolid + // (in this order, otherwise it won't work when they are paired in the middle of a file) + fscanf(fp, "endsolid%*[^\n]\n"); + fscanf(fp, "solid%*[^\n]\n"); // name might contain spaces so %*s doesn't work and it also can be empty (just "solid") + // Leading space in the fscanf format skips all leading white spaces including numerous new lines and tabs. + int res_normal = fscanf(fp, " facet normal %31s %31s %31s", normal_buf[0], normal_buf[1], normal_buf[2]); + assert(res_normal == 3); + int res_outer_loop = fscanf(fp, " outer loop"); + assert(res_outer_loop == 0); + int res_vertex1 = fscanf(fp, " vertex %f %f %f", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2)); + assert(res_vertex1 == 3); + int res_vertex2 = fscanf(fp, " vertex %f %f %f", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2)); + assert(res_vertex2 == 3); + int res_vertex3 = fscanf(fp, " vertex %f %f %f", &facet.vertex[2](0), &facet.vertex[2](1), &facet.vertex[2](2)); + assert(res_vertex3 == 3); + int res_endloop = fscanf(fp, " endloop"); + assert(res_endloop == 0); + // There is a leading and trailing white space around endfacet to eat up all leading and trailing white spaces including numerous tabs and new lines. + int res_endfacet = fscanf(fp, " endfacet "); + if (res_normal != 3 || res_outer_loop != 0 || res_vertex1 != 3 || res_vertex2 != 3 || res_vertex3 != 3 || res_endloop != 0 || res_endfacet != 0) { + BOOST_LOG_TRIVIAL(error) << "Something is syntactically very wrong with this ASCII STL! "; + return false; + } - // The facet normal has been parsed as a single string as to workaround for not a numbers in the normal definition. - if (sscanf(normal_buf[0], "%f", &facet.normal(0)) != 1 || - sscanf(normal_buf[1], "%f", &facet.normal(1)) != 1 || - sscanf(normal_buf[2], "%f", &facet.normal(2)) != 1) { - // Normal was mangled. Maybe denormals or "not a number" were stored? - // Just reset the normal and silently ignore it. - memset(&facet.normal, 0, sizeof(facet.normal)); - } - } + // The facet normal has been parsed as a single string as to workaround for not a numbers in the normal definition. + if (sscanf(normal_buf[0], "%f", &facet.normal(0)) != 1 || + sscanf(normal_buf[1], "%f", &facet.normal(1)) != 1 || + sscanf(normal_buf[2], "%f", &facet.normal(2)) != 1) { + // Normal was mangled. Maybe denormals or "not a number" were stored? + // Just reset the normal and silently ignore it. + memset(&facet.normal, 0, sizeof(facet.normal)); + } + } #if 0 - // Report close to zero vertex coordinates. Due to the nature of the floating point numbers, - // close to zero values may be represented with singificantly higher precision than the rest of the vertices. - // It may be worth to round these numbers to zero during loading to reduce the number of errors reported - // during the STL import. - for (size_t j = 0; j < 3; ++ j) { - if (facet.vertex[j](0) > -1e-12f && facet.vertex[j](0) < 1e-12f) - printf("stl_read: facet %d(0) = %e\r\n", j, facet.vertex[j](0)); - if (facet.vertex[j](1) > -1e-12f && facet.vertex[j](1) < 1e-12f) - printf("stl_read: facet %d(1) = %e\r\n", j, facet.vertex[j](1)); - if (facet.vertex[j](2) > -1e-12f && facet.vertex[j](2) < 1e-12f) - printf("stl_read: facet %d(2) = %e\r\n", j, facet.vertex[j](2)); - } + // Report close to zero vertex coordinates. Due to the nature of the floating point numbers, + // close to zero values may be represented with singificantly higher precision than the rest of the vertices. + // It may be worth to round these numbers to zero during loading to reduce the number of errors reported + // during the STL import. + for (size_t j = 0; j < 3; ++ j) { + if (facet.vertex[j](0) > -1e-12f && facet.vertex[j](0) < 1e-12f) + printf("stl_read: facet %d(0) = %e\r\n", j, facet.vertex[j](0)); + if (facet.vertex[j](1) > -1e-12f && facet.vertex[j](1) < 1e-12f) + printf("stl_read: facet %d(1) = %e\r\n", j, facet.vertex[j](1)); + if (facet.vertex[j](2) > -1e-12f && facet.vertex[j](2) < 1e-12f) + printf("stl_read: facet %d(2) = %e\r\n", j, facet.vertex[j](2)); + } #endif - /* Write the facet into memory. */ - stl->facet_start[i] = facet; - stl_facet_stats(stl, facet, first); - } - stl->stats.size = stl->stats.max - stl->stats.min; - stl->stats.bounding_diameter = stl->stats.size.norm(); - return true; + // Write the facet into memory. + stl->facet_start[i] = facet; + stl_facet_stats(stl, facet, first); + } + + stl->stats.size = stl->stats.max - stl->stats.min; + stl->stats.bounding_diameter = stl->stats.size.norm(); + return true; } bool stl_open(stl_file *stl, const char *file) @@ -277,21 +259,21 @@ void stl_reallocate(stl_file *stl) void stl_facet_stats(stl_file *stl, stl_facet facet, bool &first) { - // While we are going through all of the facets, let's find the - // maximum and minimum values for x, y, and z + // While we are going through all of the facets, let's find the + // maximum and minimum values for x, y, and z - if (first) { - // Initialize the max and min values the first time through - stl->stats.min = facet.vertex[0]; - stl->stats.max = facet.vertex[0]; - stl_vertex diff = (facet.vertex[1] - facet.vertex[0]).cwiseAbs(); - stl->stats.shortest_edge = std::max(diff(0), std::max(diff(1), diff(2))); - first = false; - } + if (first) { + // Initialize the max and min values the first time through + stl->stats.min = facet.vertex[0]; + stl->stats.max = facet.vertex[0]; + stl_vertex diff = (facet.vertex[1] - facet.vertex[0]).cwiseAbs(); + stl->stats.shortest_edge = std::max(diff(0), std::max(diff(1), diff(2))); + first = false; + } - // Now find the max and min values. - for (size_t i = 0; i < 3; ++ i) { - stl->stats.min = stl->stats.min.cwiseMin(facet.vertex[i]); - stl->stats.max = stl->stats.max.cwiseMax(facet.vertex[i]); - } + // Now find the max and min values. + for (size_t i = 0; i < 3; ++ i) { + stl->stats.min = stl->stats.min.cwiseMin(facet.vertex[i]); + stl->stats.max = stl->stats.max.cwiseMax(facet.vertex[i]); + } } diff --git a/src/admesh/util.cpp b/src/admesh/util.cpp index f4e4dbf0a..bb135db95 100644 --- a/src/admesh/util.cpp +++ b/src/admesh/util.cpp @@ -25,13 +25,14 @@ #include #include +#include + #include "stl.h" static void stl_rotate(float *x, float *y, const double c, const double s); static float get_area(stl_facet *facet); static float get_volume(stl_file *stl); - void stl_verify_neighbors(stl_file *stl) { stl->stats.backwards_edges = 0; @@ -56,7 +57,7 @@ void stl_verify_neighbors(stl_file *stl) } if (edge_a.p1 != edge_b.p1 || edge_a.p2 != edge_b.p2) { // These edges should match but they don't. Print results. - printf("edge %d of facet %d doesn't match edge %d of facet %d\n", j, i, vnot + 1, neighbor); + BOOST_LOG_TRIVIAL(info) << "edge " << j << " of facet " << i << " doesn't match edge " << (vnot + 1) << " of facet " << neighbor; stl_write_facet(stl, (char*)"first facet", i); stl_write_facet(stl, (char*)"second facet", neighbor); } @@ -291,123 +292,104 @@ static float get_area(stl_facet *facet) return 0.5f * n.dot(sum); } -void stl_repair(stl_file *stl, - int fixall_flag, - int exact_flag, - int tolerance_flag, - float tolerance, - int increment_flag, - float increment, - int nearby_flag, - int iterations, - int remove_unconnected_flag, - int fill_holes_flag, - int normal_directions_flag, - int normal_values_flag, - int reverse_all_flag, - int verbose_flag) { - - int i; - int last_edges_fixed = 0; +void stl_repair( + stl_file *stl, + bool fixall_flag, + bool exact_flag, + bool tolerance_flag, + float tolerance, + bool increment_flag, + float increment, + bool nearby_flag, + int iterations, + bool remove_unconnected_flag, + bool fill_holes_flag, + bool normal_directions_flag, + bool normal_values_flag, + bool reverse_all_flag, + bool verbose_flag) +{ + if (exact_flag || fixall_flag || nearby_flag || remove_unconnected_flag || fill_holes_flag || normal_directions_flag) { + if (verbose_flag) + printf("Checking exact...\n"); + exact_flag = true; + stl_check_facets_exact(stl); + stl->stats.facets_w_1_bad_edge = (stl->stats.connected_facets_2_edge - stl->stats.connected_facets_3_edge); + stl->stats.facets_w_2_bad_edge = (stl->stats.connected_facets_1_edge - stl->stats.connected_facets_2_edge); + stl->stats.facets_w_3_bad_edge = (stl->stats.number_of_facets - stl->stats.connected_facets_1_edge); + } - if(exact_flag || fixall_flag || nearby_flag || remove_unconnected_flag - || fill_holes_flag || normal_directions_flag) { - if (verbose_flag) - printf("Checking exact...\n"); - exact_flag = 1; - stl_check_facets_exact(stl); - stl->stats.facets_w_1_bad_edge = - (stl->stats.connected_facets_2_edge - - stl->stats.connected_facets_3_edge); - stl->stats.facets_w_2_bad_edge = - (stl->stats.connected_facets_1_edge - - stl->stats.connected_facets_2_edge); - stl->stats.facets_w_3_bad_edge = - (stl->stats.number_of_facets - - stl->stats.connected_facets_1_edge); - } - - if(nearby_flag || fixall_flag) { - if(!tolerance_flag) { - tolerance = stl->stats.shortest_edge; - } - if(!increment_flag) { - increment = stl->stats.bounding_diameter / 10000.0; + if (nearby_flag || fixall_flag) { + if (! tolerance_flag) + tolerance = stl->stats.shortest_edge; + if (! increment_flag) + increment = stl->stats.bounding_diameter / 10000.0; } - if(stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) { - for(i = 0; i < iterations; i++) { - if(stl->stats.connected_facets_3_edge < - stl->stats.number_of_facets) { - if (verbose_flag) - printf("\ -Checking nearby. Tolerance= %f Iteration=%d of %d...", - tolerance, i + 1, iterations); - stl_check_facets_nearby(stl, tolerance); - if (verbose_flag) - printf(" Fixed %d edges.\n", - stl->stats.edges_fixed - last_edges_fixed); - last_edges_fixed = stl->stats.edges_fixed; - tolerance += increment; - } else { - if (verbose_flag) - printf("\ -All facets connected. No further nearby check necessary.\n"); - break; - } - } - } else { - if (verbose_flag) - printf("All facets connected. No nearby check necessary.\n"); - } - } + if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) { + int last_edges_fixed = 0; + for (int i = 0; i < iterations; ++ i) { + if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) { + if (verbose_flag) + printf("Checking nearby. Tolerance= %f Iteration=%d of %d...", tolerance, i + 1, iterations); + stl_check_facets_nearby(stl, tolerance); + if (verbose_flag) + printf(" Fixed %d edges.\n", stl->stats.edges_fixed - last_edges_fixed); + last_edges_fixed = stl->stats.edges_fixed; + tolerance += increment; + } else { + if (verbose_flag) + printf("All facets connected. No further nearby check necessary.\n"); + break; + } + } + } else if (verbose_flag) + printf("All facets connected. No nearby check necessary.\n"); - if(remove_unconnected_flag || fixall_flag || fill_holes_flag) { - if(stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) { - if (verbose_flag) - printf("Removing unconnected facets...\n"); - stl_remove_unconnected_facets(stl); - } else - if (verbose_flag) - printf("No unconnected need to be removed.\n"); - } + if (remove_unconnected_flag || fixall_flag || fill_holes_flag) { + if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) { + if (verbose_flag) + printf("Removing unconnected facets...\n"); + stl_remove_unconnected_facets(stl); + } else if (verbose_flag) + printf("No unconnected need to be removed.\n"); + } - if(fill_holes_flag || fixall_flag) { - if(stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) { - if (verbose_flag) - printf("Filling holes...\n"); - stl_fill_holes(stl); - } else - if (verbose_flag) - printf("No holes need to be filled.\n"); - } + if (fill_holes_flag || fixall_flag) { + if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) { + if (verbose_flag) + printf("Filling holes...\n"); + stl_fill_holes(stl); + } else if (verbose_flag) + printf("No holes need to be filled.\n"); + } - if(reverse_all_flag) { - if (verbose_flag) - printf("Reversing all facets...\n"); - stl_reverse_all_facets(stl); - } + if (reverse_all_flag) { + if (verbose_flag) + printf("Reversing all facets...\n"); + stl_reverse_all_facets(stl); + } - if(normal_directions_flag || fixall_flag) { - if (verbose_flag) - printf("Checking normal directions...\n"); - stl_fix_normal_directions(stl); - } + if (normal_directions_flag || fixall_flag) { + if (verbose_flag) + printf("Checking normal directions...\n"); + stl_fix_normal_directions(stl); + } - if(normal_values_flag || fixall_flag) { - if (verbose_flag) - printf("Checking normal values...\n"); - stl_fix_normal_values(stl); - } + if (normal_values_flag || fixall_flag) { + if (verbose_flag) + printf("Checking normal values...\n"); + stl_fix_normal_values(stl); + } - /* Always calculate the volume. It shouldn't take too long */ - if (verbose_flag) - printf("Calculating volume...\n"); - stl_calculate_volume(stl); + // Always calculate the volume. It shouldn't take too long. + if (verbose_flag) + printf("Calculating volume...\n"); + stl_calculate_volume(stl); - if(exact_flag) { - if (verbose_flag) - printf("Verifying neighbors...\n"); - stl_verify_neighbors(stl); - } + if (exact_flag) { + if (verbose_flag) + printf("Verifying neighbors...\n"); + stl_verify_neighbors(stl); + } } diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index 45092f257..b28cb2eda 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -837,7 +837,7 @@ void PresetBundle::load_config_file_config_bundle(const std::string &path, const return preset_name_dst; // Try to generate another name. char buf[64]; - sprintf(buf, " (%d)", i); + sprintf(buf, " (%d)", (int)i); preset_name_dst = preset_name_src + buf + bundle_name; } }