admesh refactoring: replaced various diagnostics outputs with boost::log

This commit is contained in:
bubnikv 2019-06-10 19:45:38 +02:00
parent 6defabea53
commit 313ec7424a
7 changed files with 405 additions and 481 deletions

View File

@ -28,6 +28,7 @@
#include <algorithm>
#include <vector>
#include <boost/log/trivial.hpp>
#include <boost/detail/endian.hpp>
#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;
}
}

View File

@ -25,6 +25,7 @@
#include <vector>
#include <boost/log/trivial.hpp>
#include <boost/nowide/cstdio.hpp>
#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;
}

View File

@ -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);

View File

@ -24,6 +24,7 @@
#include <string.h>
#include "stl.h"
#include <boost/log/trivial.hpp>
#include <boost/nowide/cstdio.hpp>
#include <boost/detail/endian.hpp>
@ -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;
}

View File

@ -26,6 +26,7 @@
#include <math.h>
#include <assert.h>
#include <boost/log/trivial.hpp>
#include <boost/nowide/cstdio.hpp>
#include <boost/detail/endian.hpp>
@ -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]);
}
}

View File

@ -25,13 +25,14 @@
#include <string.h>
#include <math.h>
#include <boost/log/trivial.hpp>
#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);
}
}

View File

@ -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;
}
}