mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-11 08:47:52 -06:00
admesh refactoring: replaced various diagnostics outputs with boost::log
This commit is contained in:
parent
6defabea53
commit
313ec7424a
7 changed files with 405 additions and 481 deletions
|
@ -28,6 +28,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
#include <boost/detail/endian.hpp>
|
#include <boost/detail/endian.hpp>
|
||||||
|
|
||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
|
@ -124,7 +125,9 @@ struct HashTableEdges {
|
||||||
for (HashEdge *temp = this->heads[i]; this->heads[i] != this->tail; temp = this->heads[i]) {
|
for (HashEdge *temp = this->heads[i]; this->heads[i] != this->tail; temp = this->heads[i]) {
|
||||||
this->heads[i] = this->heads[i]->next;
|
this->heads[i] = this->heads[i]->next;
|
||||||
delete temp;
|
delete temp;
|
||||||
|
#ifndef NDEBUG
|
||||||
++ this->freed;
|
++ this->freed;
|
||||||
|
#endif /* NDEBUG */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->heads.clear();
|
this->heads.clear();
|
||||||
|
@ -139,7 +142,9 @@ struct HashTableEdges {
|
||||||
if (link == this->tail) {
|
if (link == this->tail) {
|
||||||
// This list doesn't have any edges currently in it. Add this one.
|
// This list doesn't have any edges currently in it. Add this one.
|
||||||
HashEdge *new_edge = new HashEdge(edge);
|
HashEdge *new_edge = new HashEdge(edge);
|
||||||
|
#ifndef NDEBUG
|
||||||
++ this->malloced;
|
++ this->malloced;
|
||||||
|
#endif /* NDEBUG */
|
||||||
new_edge->next = this->tail;
|
new_edge->next = this->tail;
|
||||||
this->heads[chain_number] = new_edge;
|
this->heads[chain_number] = new_edge;
|
||||||
} else if (edges_equal(edge, *link)) {
|
} else if (edges_equal(edge, *link)) {
|
||||||
|
@ -148,18 +153,24 @@ struct HashTableEdges {
|
||||||
// Delete the matched edge from the list.
|
// Delete the matched edge from the list.
|
||||||
this->heads[chain_number] = link->next;
|
this->heads[chain_number] = link->next;
|
||||||
delete link;
|
delete link;
|
||||||
|
#ifndef NDEBUG
|
||||||
++ this->freed;
|
++ this->freed;
|
||||||
|
#endif /* NDEBUG */
|
||||||
} else {
|
} else {
|
||||||
// Continue through the rest of the list.
|
// Continue through the rest of the list.
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (link->next == this->tail) {
|
if (link->next == this->tail) {
|
||||||
// This is the last item in the list. Insert a new edge.
|
// This is the last item in the list. Insert a new edge.
|
||||||
HashEdge *new_edge = new HashEdge;
|
HashEdge *new_edge = new HashEdge;
|
||||||
|
#ifndef NDEBUG
|
||||||
++ this->malloced;
|
++ this->malloced;
|
||||||
|
#endif /* NDEBUG */
|
||||||
*new_edge = edge;
|
*new_edge = edge;
|
||||||
new_edge->next = this->tail;
|
new_edge->next = this->tail;
|
||||||
link->next = new_edge;
|
link->next = new_edge;
|
||||||
|
#ifndef NDEBUG
|
||||||
++ this->collisions;
|
++ this->collisions;
|
||||||
|
#endif /* NDEBUG */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (edges_equal(edge, *link->next)) {
|
if (edges_equal(edge, *link->next)) {
|
||||||
|
@ -169,12 +180,16 @@ struct HashTableEdges {
|
||||||
HashEdge *temp = link->next;
|
HashEdge *temp = link->next;
|
||||||
link->next = link->next->next;
|
link->next = link->next->next;
|
||||||
delete temp;
|
delete temp;
|
||||||
|
#ifndef NDEBUG
|
||||||
++ this->freed;
|
++ this->freed;
|
||||||
|
#endif /* NDEBUG */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// This is not a match. Go to the next link.
|
// This is not a match. Go to the next link.
|
||||||
link = link->next;
|
link = link->next;
|
||||||
|
#ifndef NDEBUG
|
||||||
++ this->collisions;
|
++ this->collisions;
|
||||||
|
#endif /* NDEBUG */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,9 +199,11 @@ struct HashTableEdges {
|
||||||
HashEdge* tail;
|
HashEdge* tail;
|
||||||
int M;
|
int M;
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
size_t malloced = 0;
|
size_t malloced = 0;
|
||||||
size_t freed = 0;
|
size_t freed = 0;
|
||||||
size_t collisions = 0;
|
size_t collisions = 0;
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static inline size_t hash_size_from_nr_faces(const size_t nr_faces)
|
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) {
|
if (facet_num == first_facet) {
|
||||||
// back to the beginning
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -506,7 +523,7 @@ void stl_remove_unconnected_facets(stl_file *stl)
|
||||||
if (neighbors.neighbor[i] != -1) {
|
if (neighbors.neighbor[i] != -1) {
|
||||||
int &other_face_idx = stl->neighbors_start[neighbors.neighbor[i]].neighbor[(neighbors.which_vertex_not[i] + 1) % 3];
|
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) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
other_face_idx = facet_number;
|
other_face_idx = facet_number;
|
||||||
|
@ -697,7 +714,7 @@ void stl_fill_holes(stl_file *stl)
|
||||||
|
|
||||||
if (facet_num == first_facet) {
|
if (facet_num == first_facet) {
|
||||||
// back to the beginning
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
#include <boost/nowide/cstdio.hpp>
|
#include <boost/nowide/cstdio.hpp>
|
||||||
|
|
||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
|
@ -129,10 +130,7 @@ bool its_write_off(const indexed_triangle_set &its, const char *file)
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
FILE *fp = boost::nowide::fopen(file, "w");
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
if (fp == nullptr) {
|
if (fp == nullptr) {
|
||||||
char *error_msg = (char*)malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
BOOST_LOG_TRIVIAL(error) << "stl_write_ascii: Couldn't open " << file << " for writing";
|
||||||
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file);
|
|
||||||
perror(error_msg);
|
|
||||||
free(error_msg);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,10 +149,7 @@ bool its_write_vrml(const indexed_triangle_set &its, const char *file)
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
FILE *fp = boost::nowide::fopen(file, "w");
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
if (fp == nullptr) {
|
if (fp == nullptr) {
|
||||||
char *error_msg = (char*)malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
BOOST_LOG_TRIVIAL(error) << "stl_write_vrml: Couldn't open " << file << " for writing";
|
||||||
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file);
|
|
||||||
perror(error_msg);
|
|
||||||
free(error_msg);
|
|
||||||
return false;
|
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");
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
if (fp == nullptr) {
|
if (fp == nullptr) {
|
||||||
char* error_msg = (char*)malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
BOOST_LOG_TRIVIAL(error) << "stl_write_obj: Couldn't open " << file << " for writing";
|
||||||
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file);
|
|
||||||
perror(error_msg);
|
|
||||||
free(error_msg);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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_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_reset(stl_file *stl);
|
||||||
extern void stl_allocate(stl_file *stl);
|
extern void stl_allocate(stl_file *stl);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
#include <boost/nowide/cstdio.hpp>
|
#include <boost/nowide/cstdio.hpp>
|
||||||
#include <boost/detail/endian.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)
|
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 */
|
fprintf(fp, "solid %s\n", label);
|
||||||
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);
|
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, "endsolid %s\n", label);
|
||||||
fprintf(fp, " facet normal % .8E % .8E % .8E\n",
|
fclose(fp);
|
||||||
stl->facet_start[i].normal(0), stl->facet_start[i].normal(1),
|
return true;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool stl_print_neighbors(stl_file *stl, char *file)
|
bool stl_print_neighbors(stl_file *stl, char *file)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
char *error_msg;
|
if (fp == NULL) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "stl_print_neighbors: Couldn't open " << file << " for writing";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Open the file */
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
fp = boost::nowide::fopen(file, "w");
|
fprintf(fp, "%d, %d,%d, %d,%d, %d,%d\n",
|
||||||
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",
|
|
||||||
i,
|
i,
|
||||||
stl->neighbors_start[i].neighbor[0],
|
stl->neighbors_start[i].neighbor[0],
|
||||||
(int)stl->neighbors_start[i].which_vertex_not[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],
|
(int)stl->neighbors_start[i].which_vertex_not[1],
|
||||||
stl->neighbors_start[i].neighbor[2],
|
stl->neighbors_start[i].neighbor[2],
|
||||||
(int)stl->neighbors_start[i].which_vertex_not[2]);
|
(int)stl->neighbors_start[i].which_vertex_not[2]);
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef BOOST_LITTLE_ENDIAN
|
#ifndef BOOST_LITTLE_ENDIAN
|
||||||
// Swap a buffer of 32bit data from little endian to big endian and vice versa.
|
// 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)
|
void stl_internal_reverse_quads(char *buf, size_t cnt)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < cnt; i += 4) {
|
for (size_t i = 0; i < cnt; i += 4) {
|
||||||
std::swap(buf[i], buf[i+3]);
|
std::swap(buf[i], buf[i+3]);
|
||||||
std::swap(buf[i+1], buf[i+2]);
|
std::swap(buf[i+1], buf[i+2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool stl_write_binary(stl_file *stl, const char *file, const char *label)
|
bool stl_write_binary(stl_file *stl, const char *file, const char *label)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp = boost::nowide::fopen(file, "wb");
|
||||||
char *error_msg;
|
if (fp == NULL) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "stl_write_binary: Couldn't open " << file << " for writing";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Open the file */
|
fprintf(fp, "%s", label);
|
||||||
fp = boost::nowide::fopen(file, "wb");
|
for (size_t i = strlen(label); i < LABEL_SIZE; ++ i)
|
||||||
if(fp == NULL) {
|
putc(0, fp);
|
||||||
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);
|
fseek(fp, LABEL_SIZE, SEEK_SET);
|
||||||
for(size_t i = strlen(label); i < LABEL_SIZE; i++) putc(0, fp);
|
|
||||||
|
|
||||||
fseek(fp, LABEL_SIZE, SEEK_SET);
|
|
||||||
#ifdef BOOST_LITTLE_ENDIAN
|
#ifdef BOOST_LITTLE_ENDIAN
|
||||||
fwrite(&stl->stats.number_of_facets, 4, 1, fp);
|
fwrite(&stl->stats.number_of_facets, 4, 1, fp);
|
||||||
for (const stl_facet &facet : stl->facet_start)
|
for (const stl_facet &facet : stl->facet_start)
|
||||||
fwrite(&facet, SIZEOF_STL_FACET, 1, fp);
|
fwrite(&facet, SIZEOF_STL_FACET, 1, fp);
|
||||||
#else /* BOOST_LITTLE_ENDIAN */
|
#else /* BOOST_LITTLE_ENDIAN */
|
||||||
char buffer[50];
|
char buffer[50];
|
||||||
// Convert the number of facets to little endian.
|
// Convert the number of facets to little endian.
|
||||||
memcpy(buffer, &stl->stats.number_of_facets, 4);
|
memcpy(buffer, &stl->stats.number_of_facets, 4);
|
||||||
stl_internal_reverse_quads(buffer, 4);
|
stl_internal_reverse_quads(buffer, 4);
|
||||||
fwrite(buffer, 4, 1, fp);
|
fwrite(buffer, 4, 1, fp);
|
||||||
for (i = 0; i < stl->stats.number_of_facets; ++ i) {
|
for (i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
memcpy(buffer, stl->facet_start + i, 50);
|
memcpy(buffer, stl->facet_start + i, 50);
|
||||||
// Convert to little endian.
|
// Convert to little endian.
|
||||||
stl_internal_reverse_quads(buffer, 48);
|
stl_internal_reverse_quads(buffer, 48);
|
||||||
fwrite(buffer, SIZEOF_STL_FACET, 1, fp);
|
fwrite(buffer, SIZEOF_STL_FACET, 1, fp);
|
||||||
}
|
}
|
||||||
#endif /* BOOST_LITTLE_ENDIAN */
|
#endif /* BOOST_LITTLE_ENDIAN */
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_write_vertex(stl_file *stl, int facet, int vertex)
|
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)
|
bool stl_write_quad_object(stl_file *stl, char *file)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
stl_vertex connect_color = stl_vertex::Zero();
|
||||||
char *error_msg;
|
stl_vertex uncon_1_color = stl_vertex::Zero();
|
||||||
stl_vertex connect_color = stl_vertex::Zero();
|
stl_vertex uncon_2_color = stl_vertex::Zero();
|
||||||
stl_vertex uncon_1_color = stl_vertex::Zero();
|
stl_vertex uncon_3_color = stl_vertex::Zero();
|
||||||
stl_vertex uncon_2_color = stl_vertex::Zero();
|
stl_vertex color;
|
||||||
stl_vertex uncon_3_color = stl_vertex::Zero();
|
|
||||||
stl_vertex color;
|
|
||||||
|
|
||||||
/* Open the file */
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
fp = boost::nowide::fopen(file, "w");
|
if (fp == NULL) {
|
||||||
if(fp == NULL) {
|
BOOST_LOG_TRIVIAL(error) << "stl_write_quad_object: Couldn't open " << file << " for writing";
|
||||||
error_msg = (char*)
|
return false;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fp, "CQUAD\n");
|
fprintf(fp, "CQUAD\n");
|
||||||
for (uint32_t i = 0; i < stl->stats.number_of_facets; i++) {
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
int j = ((stl->neighbors_start[i].neighbor[0] == -1) +
|
switch (stl->neighbors_start[i].num_neighbors_missing()) {
|
||||||
(stl->neighbors_start[i].neighbor[1] == -1) +
|
case 0: color = connect_color; break;
|
||||||
(stl->neighbors_start[i].neighbor[2] == -1));
|
case 1: color = uncon_1_color; break;
|
||||||
if(j == 0) {
|
case 2: color = uncon_2_color; break;
|
||||||
color = connect_color;
|
default: color = uncon_3_color;
|
||||||
} else if(j == 1) {
|
}
|
||||||
color = uncon_1_color;
|
fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n",
|
||||||
} 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",
|
|
||||||
stl->facet_start[i].vertex[0](0),
|
stl->facet_start[i].vertex[0](0),
|
||||||
stl->facet_start[i].vertex[0](1),
|
stl->facet_start[i].vertex[0](1),
|
||||||
stl->facet_start[i].vertex[0](2), color(0), color(1), color(2));
|
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](0),
|
||||||
stl->facet_start[i].vertex[1](1),
|
stl->facet_start[i].vertex[1](1),
|
||||||
stl->facet_start[i].vertex[1](2), color(0), color(1), color(2));
|
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](0),
|
||||||
stl->facet_start[i].vertex[2](1),
|
stl->facet_start[i].vertex[2](1),
|
||||||
stl->facet_start[i].vertex[2](2), color(0), color(1), color(2));
|
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](0),
|
||||||
stl->facet_start[i].vertex[2](1),
|
stl->facet_start[i].vertex[2](1),
|
||||||
stl->facet_start[i].vertex[2](2), color(0), color(1), color(2));
|
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)
|
bool stl_write_dxf(stl_file *stl, const char *file, char *label)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
char *error_msg;
|
if (fp == NULL) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "stl_write_quad_object: Couldn't open " << file << " for writing";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Open the file */
|
fprintf(fp, "999\n%s\n", label);
|
||||||
fp = boost::nowide::fopen(file, "w");
|
fprintf(fp, "0\nSECTION\n2\nHEADER\n0\nENDSEC\n");
|
||||||
if(fp == NULL) {
|
fprintf(fp, "0\nSECTION\n2\nTABLES\n0\nTABLE\n2\nLAYER\n70\n1\n\
|
||||||
error_msg = (char*)
|
0\nLAYER\n2\n0\n70\n0\n62\n7\n6\nCONTINUOUS\n0\nENDTAB\n0\nENDSEC\n");
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
fprintf(fp, "0\nSECTION\n2\nBLOCKS\n0\nENDSEC\n");
|
||||||
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\nENTITIES\n");
|
||||||
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");
|
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\nENDSEC\n0\nEOF\n");
|
||||||
fprintf(fp, "0\n3DFACE\n8\n0\n");
|
fclose(fp);
|
||||||
fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n",
|
return true;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
#include <boost/nowide/cstdio.hpp>
|
#include <boost/nowide/cstdio.hpp>
|
||||||
#include <boost/detail/endian.hpp>
|
#include <boost/detail/endian.hpp>
|
||||||
|
|
||||||
|
@ -37,118 +38,102 @@
|
||||||
|
|
||||||
static FILE* stl_open_count_facets(stl_file *stl, const char *file)
|
static FILE* stl_open_count_facets(stl_file *stl, const char *file)
|
||||||
{
|
{
|
||||||
long file_size;
|
// Open the file in binary mode first.
|
||||||
uint32_t header_num_facets;
|
FILE *fp = boost::nowide::fopen(file, "rb");
|
||||||
uint32_t num_facets;
|
if (fp == nullptr) {
|
||||||
int i;
|
BOOST_LOG_TRIVIAL(error) << "stl_open_count_facets: Couldn't open " << file << " for reading";
|
||||||
size_t s;
|
return nullptr;
|
||||||
unsigned char chtest[128];
|
}
|
||||||
int num_lines = 1;
|
// Find size of file.
|
||||||
char *error_msg;
|
fseek(fp, 0, SEEK_END);
|
||||||
|
long file_size = ftell(fp);
|
||||||
|
|
||||||
/* Open the file in binary mode first */
|
// Check for binary or ASCII file.
|
||||||
FILE *fp = boost::nowide::fopen(file, "rb");
|
fseek(fp, HEADER_SIZE, SEEK_SET);
|
||||||
if (fp == nullptr) {
|
unsigned char chtest[128];
|
||||||
error_msg = (char*)
|
if (! fread(chtest, sizeof(chtest), 1, fp)) {
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
BOOST_LOG_TRIVIAL(error) << "stl_open_count_facets: The input is an empty file: " << file;
|
||||||
sprintf(error_msg, "stl_initialize: Couldn't open %s for reading",
|
fclose(fp);
|
||||||
file);
|
return nullptr;
|
||||||
perror(error_msg);
|
}
|
||||||
free(error_msg);
|
stl->stats.type = ascii;
|
||||||
return nullptr;
|
for (size_t s = 0; s < sizeof(chtest); s++) {
|
||||||
}
|
if (chtest[s] > 127) {
|
||||||
/* Find size of file */
|
stl->stats.type = binary;
|
||||||
fseek(fp, 0, SEEK_END);
|
break;
|
||||||
file_size = ftell(fp);
|
}
|
||||||
|
}
|
||||||
|
rewind(fp);
|
||||||
|
|
||||||
/* Check for binary or ASCII file */
|
uint32_t num_facets = 0;
|
||||||
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);
|
|
||||||
|
|
||||||
/* Get the header and the number of facets in the .STL file */
|
// Get the header and the number of facets in the .STL file.
|
||||||
/* If the .STL file is binary, then do the following */
|
// If the .STL file is binary, then do the following:
|
||||||
if(stl->stats.type == binary) {
|
if (stl->stats.type == binary) {
|
||||||
/* Test if the STL file has the right size */
|
// Test if the STL file has the right size.
|
||||||
if(((file_size - HEADER_SIZE) % SIZEOF_STL_FACET != 0)
|
if (((file_size - HEADER_SIZE) % SIZEOF_STL_FACET != 0) || (file_size < STL_MIN_FILE_SIZE)) {
|
||||||
|| (file_size < STL_MIN_FILE_SIZE)) {
|
BOOST_LOG_TRIVIAL(error) << "stl_open_count_facets: The file " << file << " has the wrong size.";
|
||||||
fprintf(stderr, "The file %s has the wrong size.\n", file);
|
fclose(fp);
|
||||||
fclose(fp);
|
return nullptr;
|
||||||
return nullptr;
|
}
|
||||||
}
|
num_facets = (file_size - HEADER_SIZE) / SIZEOF_STL_FACET;
|
||||||
num_facets = (file_size - HEADER_SIZE) / SIZEOF_STL_FACET;
|
|
||||||
|
|
||||||
/* Read the header */
|
// Read the header.
|
||||||
if (fread(stl->stats.header, LABEL_SIZE, 1, fp) > 79) {
|
if (fread(stl->stats.header, LABEL_SIZE, 1, fp) > 79)
|
||||||
stl->stats.header[80] = '\0';
|
stl->stats.header[80] = '\0';
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the int following the header. This should contain # of facets */
|
// 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;
|
uint32_t header_num_facets;
|
||||||
|
bool header_num_faces_read = fread(&header_num_facets, sizeof(uint32_t), 1, fp) != 0;
|
||||||
#ifndef BOOST_LITTLE_ENDIAN
|
#ifndef BOOST_LITTLE_ENDIAN
|
||||||
// Convert from little endian to big endian.
|
// Convert from little endian to big endian.
|
||||||
stl_internal_reverse_quads((char*)&header_num_facets, 4);
|
stl_internal_reverse_quads((char*)&header_num_facets, 4);
|
||||||
#endif /* BOOST_LITTLE_ENDIAN */
|
#endif /* BOOST_LITTLE_ENDIAN */
|
||||||
if (! header_num_faces_read || num_facets != header_num_facets) {
|
if (! header_num_faces_read || num_facets != header_num_facets)
|
||||||
fprintf(stderr,
|
BOOST_LOG_TRIVIAL(info) << "stl_open_count_facets: Warning: File size doesn't match number of facets in the header: " << file;
|
||||||
"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
|
||||||
/* Otherwise, if the .STL file is ASCII, then do the following */
|
{
|
||||||
else {
|
// Reopen the file in text mode (for getting correct newlines on Windows)
|
||||||
/* Reopen the file in text mode (for getting correct newlines on Windows) */
|
// fix to silence a warning about unused return value.
|
||||||
// fix to silence a warning about unused return value.
|
// obviously if it fails we have problems....
|
||||||
// obviously if it fails we have problems....
|
fp = boost::nowide::freopen(file, "r", fp);
|
||||||
fp = boost::nowide::freopen(file, "r", fp);
|
|
||||||
|
|
||||||
// do another null check to be safe
|
// do another null check to be safe
|
||||||
if(fp == nullptr) {
|
if (fp == nullptr) {
|
||||||
error_msg = (char*)
|
BOOST_LOG_TRIVIAL(error) << "stl_open_count_facets: Couldn't open " << file << " for reading";
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
fclose(fp);
|
||||||
sprintf(error_msg, "stl_initialize: Couldn't open %s for reading",
|
return nullptr;
|
||||||
file);
|
}
|
||||||
perror(error_msg);
|
|
||||||
free(error_msg);
|
|
||||||
fclose(fp);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the number of facets */
|
// Find the number of facets.
|
||||||
char linebuf[100];
|
char linebuf[100];
|
||||||
while (fgets(linebuf, 100, fp) != nullptr) {
|
int num_lines = 1;
|
||||||
/* don't count short lines */
|
while (fgets(linebuf, 100, fp) != nullptr) {
|
||||||
if (strlen(linebuf) <= 4) continue;
|
// Don't count short lines.
|
||||||
|
if (strlen(linebuf) <= 4)
|
||||||
/* skip solid/endsolid lines as broken STL file generators may put several of them */
|
continue;
|
||||||
if (strncmp(linebuf, "solid", 5) == 0 || strncmp(linebuf, "endsolid", 8) == 0) 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)
|
||||||
++num_lines;
|
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';
|
|
||||||
|
|
||||||
num_facets = num_lines / ASCII_LINES_PER_FACET;
|
rewind(fp);
|
||||||
}
|
|
||||||
stl->stats.number_of_facets += num_facets;
|
// Get the header.
|
||||||
stl->stats.original_num_facets = stl->stats.number_of_facets;
|
int i = 0;
|
||||||
return fp;
|
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,
|
/* 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. */
|
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)
|
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) {
|
char normal_buf[3][32];
|
||||||
fseek(fp, HEADER_SIZE, SEEK_SET);
|
for (uint32_t i = first_facet; i < stl->stats.number_of_facets; ++i) {
|
||||||
} else {
|
stl_facet facet;
|
||||||
rewind(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
char normal_buf[3][32];
|
if (stl->stats.type == binary) {
|
||||||
for(uint32_t i = first_facet; i < stl->stats.number_of_facets; i++) {
|
// Read a single facet from a binary .STL file. We assume little-endian architecture!
|
||||||
if(stl->stats.type == binary)
|
if (fread(&facet, 1, SIZEOF_STL_FACET, fp) != SIZEOF_STL_FACET)
|
||||||
/* Read a single facet from a binary .STL file */
|
return false;
|
||||||
{
|
|
||||||
/* we assume little-endian architecture! */
|
|
||||||
if (fread(&facet, 1, SIZEOF_STL_FACET, fp) != SIZEOF_STL_FACET)
|
|
||||||
return false;
|
|
||||||
#ifndef BOOST_LITTLE_ENDIAN
|
#ifndef BOOST_LITTLE_ENDIAN
|
||||||
// Convert the loaded little endian data to big endian.
|
// Convert the loaded little endian data to big endian.
|
||||||
stl_internal_reverse_quads((char*)&facet, 48);
|
stl_internal_reverse_quads((char*)&facet, 48);
|
||||||
#endif /* BOOST_LITTLE_ENDIAN */
|
#endif /* BOOST_LITTLE_ENDIAN */
|
||||||
} else
|
} else {
|
||||||
/* Read a single facet from an ASCII .STL file */
|
// Read a single facet from an ASCII .STL file
|
||||||
{
|
// skip solid/endsolid
|
||||||
// skip solid/endsolid
|
// (in this order, otherwise it won't work when they are paired in the middle of a file)
|
||||||
// (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, "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")
|
||||||
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.
|
||||||
// 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]);
|
||||||
int res_normal = fscanf(fp, " facet normal %31s %31s %31s", normal_buf[0], normal_buf[1], normal_buf[2]);
|
assert(res_normal == 3);
|
||||||
assert(res_normal == 3);
|
int res_outer_loop = fscanf(fp, " outer loop");
|
||||||
int res_outer_loop = fscanf(fp, " outer loop");
|
assert(res_outer_loop == 0);
|
||||||
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));
|
||||||
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);
|
||||||
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));
|
||||||
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);
|
||||||
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));
|
||||||
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);
|
||||||
assert(res_vertex3 == 3);
|
int res_endloop = fscanf(fp, " endloop");
|
||||||
int res_endloop = fscanf(fp, " endloop");
|
assert(res_endloop == 0);
|
||||||
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.
|
||||||
// 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 ");
|
||||||
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) {
|
||||||
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! ";
|
||||||
perror("Something is syntactically very wrong with this ASCII STL!");
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// The facet normal has been parsed as a single string as to workaround for not a numbers in the normal definition.
|
// 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 ||
|
if (sscanf(normal_buf[0], "%f", &facet.normal(0)) != 1 ||
|
||||||
sscanf(normal_buf[1], "%f", &facet.normal(1)) != 1 ||
|
sscanf(normal_buf[1], "%f", &facet.normal(1)) != 1 ||
|
||||||
sscanf(normal_buf[2], "%f", &facet.normal(2)) != 1) {
|
sscanf(normal_buf[2], "%f", &facet.normal(2)) != 1) {
|
||||||
// Normal was mangled. Maybe denormals or "not a number" were stored?
|
// Normal was mangled. Maybe denormals or "not a number" were stored?
|
||||||
// Just reset the normal and silently ignore it.
|
// Just reset the normal and silently ignore it.
|
||||||
memset(&facet.normal, 0, sizeof(facet.normal));
|
memset(&facet.normal, 0, sizeof(facet.normal));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Report close to zero vertex coordinates. Due to the nature of the floating point numbers,
|
// 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.
|
// 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
|
// It may be worth to round these numbers to zero during loading to reduce the number of errors reported
|
||||||
// during the STL import.
|
// during the STL import.
|
||||||
for (size_t j = 0; j < 3; ++ j) {
|
for (size_t j = 0; j < 3; ++ j) {
|
||||||
if (facet.vertex[j](0) > -1e-12f && facet.vertex[j](0) < 1e-12f)
|
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));
|
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)
|
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));
|
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)
|
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));
|
printf("stl_read: facet %d(2) = %e\r\n", j, facet.vertex[j](2));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Write the facet into memory. */
|
// Write the facet into memory.
|
||||||
stl->facet_start[i] = facet;
|
stl->facet_start[i] = facet;
|
||||||
stl_facet_stats(stl, facet, first);
|
stl_facet_stats(stl, facet, first);
|
||||||
}
|
}
|
||||||
stl->stats.size = stl->stats.max - stl->stats.min;
|
|
||||||
stl->stats.bounding_diameter = stl->stats.size.norm();
|
stl->stats.size = stl->stats.max - stl->stats.min;
|
||||||
return true;
|
stl->stats.bounding_diameter = stl->stats.size.norm();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool stl_open(stl_file *stl, const char *file)
|
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)
|
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
|
// While we are going through all of the facets, let's find the
|
||||||
// maximum and minimum values for x, y, and z
|
// maximum and minimum values for x, y, and z
|
||||||
|
|
||||||
if (first) {
|
if (first) {
|
||||||
// Initialize the max and min values the first time through
|
// Initialize the max and min values the first time through
|
||||||
stl->stats.min = facet.vertex[0];
|
stl->stats.min = facet.vertex[0];
|
||||||
stl->stats.max = facet.vertex[0];
|
stl->stats.max = facet.vertex[0];
|
||||||
stl_vertex diff = (facet.vertex[1] - facet.vertex[0]).cwiseAbs();
|
stl_vertex diff = (facet.vertex[1] - facet.vertex[0]).cwiseAbs();
|
||||||
stl->stats.shortest_edge = std::max(diff(0), std::max(diff(1), diff(2)));
|
stl->stats.shortest_edge = std::max(diff(0), std::max(diff(1), diff(2)));
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now find the max and min values.
|
// Now find the max and min values.
|
||||||
for (size_t i = 0; i < 3; ++ i) {
|
for (size_t i = 0; i < 3; ++ i) {
|
||||||
stl->stats.min = stl->stats.min.cwiseMin(facet.vertex[i]);
|
stl->stats.min = stl->stats.min.cwiseMin(facet.vertex[i]);
|
||||||
stl->stats.max = stl->stats.max.cwiseMax(facet.vertex[i]);
|
stl->stats.max = stl->stats.max.cwiseMax(facet.vertex[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,13 +25,14 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
|
|
||||||
static void stl_rotate(float *x, float *y, const double c, const double s);
|
static void stl_rotate(float *x, float *y, const double c, const double s);
|
||||||
static float get_area(stl_facet *facet);
|
static float get_area(stl_facet *facet);
|
||||||
static float get_volume(stl_file *stl);
|
static float get_volume(stl_file *stl);
|
||||||
|
|
||||||
|
|
||||||
void stl_verify_neighbors(stl_file *stl)
|
void stl_verify_neighbors(stl_file *stl)
|
||||||
{
|
{
|
||||||
stl->stats.backwards_edges = 0;
|
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) {
|
if (edge_a.p1 != edge_b.p1 || edge_a.p2 != edge_b.p2) {
|
||||||
// These edges should match but they don't. Print results.
|
// 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*)"first facet", i);
|
||||||
stl_write_facet(stl, (char*)"second facet", neighbor);
|
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);
|
return 0.5f * n.dot(sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_repair(stl_file *stl,
|
void stl_repair(
|
||||||
int fixall_flag,
|
stl_file *stl,
|
||||||
int exact_flag,
|
bool fixall_flag,
|
||||||
int tolerance_flag,
|
bool exact_flag,
|
||||||
float tolerance,
|
bool tolerance_flag,
|
||||||
int increment_flag,
|
float tolerance,
|
||||||
float increment,
|
bool increment_flag,
|
||||||
int nearby_flag,
|
float increment,
|
||||||
int iterations,
|
bool nearby_flag,
|
||||||
int remove_unconnected_flag,
|
int iterations,
|
||||||
int fill_holes_flag,
|
bool remove_unconnected_flag,
|
||||||
int normal_directions_flag,
|
bool fill_holes_flag,
|
||||||
int normal_values_flag,
|
bool normal_directions_flag,
|
||||||
int reverse_all_flag,
|
bool normal_values_flag,
|
||||||
int verbose_flag) {
|
bool reverse_all_flag,
|
||||||
|
bool verbose_flag)
|
||||||
int i;
|
{
|
||||||
int last_edges_fixed = 0;
|
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
|
if (nearby_flag || fixall_flag) {
|
||||||
|| fill_holes_flag || normal_directions_flag) {
|
if (! tolerance_flag)
|
||||||
if (verbose_flag)
|
tolerance = stl->stats.shortest_edge;
|
||||||
printf("Checking exact...\n");
|
if (! increment_flag)
|
||||||
exact_flag = 1;
|
increment = stl->stats.bounding_diameter / 10000.0;
|
||||||
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(stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
||||||
for(i = 0; i < iterations; i++) {
|
int last_edges_fixed = 0;
|
||||||
if(stl->stats.connected_facets_3_edge <
|
for (int i = 0; i < iterations; ++ i) {
|
||||||
stl->stats.number_of_facets) {
|
if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
||||||
if (verbose_flag)
|
if (verbose_flag)
|
||||||
printf("\
|
printf("Checking nearby. Tolerance= %f Iteration=%d of %d...", tolerance, i + 1, iterations);
|
||||||
Checking nearby. Tolerance= %f Iteration=%d of %d...",
|
stl_check_facets_nearby(stl, tolerance);
|
||||||
tolerance, i + 1, iterations);
|
if (verbose_flag)
|
||||||
stl_check_facets_nearby(stl, tolerance);
|
printf(" Fixed %d edges.\n", stl->stats.edges_fixed - last_edges_fixed);
|
||||||
if (verbose_flag)
|
last_edges_fixed = stl->stats.edges_fixed;
|
||||||
printf(" Fixed %d edges.\n",
|
tolerance += increment;
|
||||||
stl->stats.edges_fixed - last_edges_fixed);
|
} else {
|
||||||
last_edges_fixed = stl->stats.edges_fixed;
|
if (verbose_flag)
|
||||||
tolerance += increment;
|
printf("All facets connected. No further nearby check necessary.\n");
|
||||||
} else {
|
break;
|
||||||
if (verbose_flag)
|
}
|
||||||
printf("\
|
}
|
||||||
All facets connected. No further nearby check necessary.\n");
|
} else if (verbose_flag)
|
||||||
break;
|
printf("All facets connected. No nearby check necessary.\n");
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (verbose_flag)
|
|
||||||
printf("All facets connected. No nearby check necessary.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(remove_unconnected_flag || fixall_flag || fill_holes_flag) {
|
if (remove_unconnected_flag || fixall_flag || fill_holes_flag) {
|
||||||
if(stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
||||||
if (verbose_flag)
|
if (verbose_flag)
|
||||||
printf("Removing unconnected facets...\n");
|
printf("Removing unconnected facets...\n");
|
||||||
stl_remove_unconnected_facets(stl);
|
stl_remove_unconnected_facets(stl);
|
||||||
} else
|
} else if (verbose_flag)
|
||||||
if (verbose_flag)
|
printf("No unconnected need to be removed.\n");
|
||||||
printf("No unconnected need to be removed.\n");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(fill_holes_flag || fixall_flag) {
|
if (fill_holes_flag || fixall_flag) {
|
||||||
if(stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
||||||
if (verbose_flag)
|
if (verbose_flag)
|
||||||
printf("Filling holes...\n");
|
printf("Filling holes...\n");
|
||||||
stl_fill_holes(stl);
|
stl_fill_holes(stl);
|
||||||
} else
|
} else if (verbose_flag)
|
||||||
if (verbose_flag)
|
printf("No holes need to be filled.\n");
|
||||||
printf("No holes need to be filled.\n");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(reverse_all_flag) {
|
if (reverse_all_flag) {
|
||||||
if (verbose_flag)
|
if (verbose_flag)
|
||||||
printf("Reversing all facets...\n");
|
printf("Reversing all facets...\n");
|
||||||
stl_reverse_all_facets(stl);
|
stl_reverse_all_facets(stl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(normal_directions_flag || fixall_flag) {
|
if (normal_directions_flag || fixall_flag) {
|
||||||
if (verbose_flag)
|
if (verbose_flag)
|
||||||
printf("Checking normal directions...\n");
|
printf("Checking normal directions...\n");
|
||||||
stl_fix_normal_directions(stl);
|
stl_fix_normal_directions(stl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(normal_values_flag || fixall_flag) {
|
if (normal_values_flag || fixall_flag) {
|
||||||
if (verbose_flag)
|
if (verbose_flag)
|
||||||
printf("Checking normal values...\n");
|
printf("Checking normal values...\n");
|
||||||
stl_fix_normal_values(stl);
|
stl_fix_normal_values(stl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Always calculate the volume. It shouldn't take too long */
|
// Always calculate the volume. It shouldn't take too long.
|
||||||
if (verbose_flag)
|
if (verbose_flag)
|
||||||
printf("Calculating volume...\n");
|
printf("Calculating volume...\n");
|
||||||
stl_calculate_volume(stl);
|
stl_calculate_volume(stl);
|
||||||
|
|
||||||
if(exact_flag) {
|
if (exact_flag) {
|
||||||
if (verbose_flag)
|
if (verbose_flag)
|
||||||
printf("Verifying neighbors...\n");
|
printf("Verifying neighbors...\n");
|
||||||
stl_verify_neighbors(stl);
|
stl_verify_neighbors(stl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -837,7 +837,7 @@ void PresetBundle::load_config_file_config_bundle(const std::string &path, const
|
||||||
return preset_name_dst;
|
return preset_name_dst;
|
||||||
// Try to generate another name.
|
// Try to generate another name.
|
||||||
char buf[64];
|
char buf[64];
|
||||||
sprintf(buf, " (%d)", i);
|
sprintf(buf, " (%d)", (int)i);
|
||||||
preset_name_dst = preset_name_src + buf + bundle_name;
|
preset_name_dst = preset_name_src + buf + bundle_name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue