Refactored admesh to get rid of the error and fp members of stl_file.

This commit is contained in:
bubnikv 2019-06-10 17:17:36 +02:00
parent 40b27e8332
commit a1c38794fb
12 changed files with 213 additions and 429 deletions

View file

@ -396,9 +396,6 @@ static void match_neighbors_nearby(stl_file *stl, const HashEdge &edge_a, const
// floats of the first edge matches all six floats of the second edge.
void stl_check_facets_exact(stl_file *stl)
{
if (stl->error)
return;
stl->stats.connected_edges = 0;
stl->stats.connected_facets_1_edge = 0;
stl->stats.connected_facets_2_edge = 0;
@ -444,9 +441,6 @@ void stl_check_facets_exact(stl_file *stl)
void stl_check_facets_nearby(stl_file *stl, float tolerance)
{
if (stl->error)
return;
if ( (stl->stats.connected_facets_1_edge == stl->stats.number_of_facets)
&& (stl->stats.connected_facets_2_edge == stl->stats.number_of_facets)
&& (stl->stats.connected_facets_3_edge == stl->stats.number_of_facets)) {
@ -476,9 +470,6 @@ void stl_remove_unconnected_facets(stl_file *stl)
// A couple of things need to be done here. One is to remove any completely unconnected facets (0 edges connected) since these are
// useless and could be completely wrong. The second thing that needs to be done is to remove any degenerate facets that were created during
// stl_check_facets_nearby().
if (stl->error)
return;
auto remove_facet = [stl](int facet_number)
{
++ stl->stats.facets_removed;
@ -526,7 +517,6 @@ void stl_remove_unconnected_facets(stl_file *stl)
{
// Update statistics on face connectivity.
auto stl_update_connects_remove_1 = [stl](int facet_num) {
assert(! stl->error);
//FIXME when decreasing 3_edge, should I increase 2_edge etc?
switch ((stl->neighbors_start[facet_num].neighbor[0] == -1) + (stl->neighbors_start[facet_num].neighbor[1] == -1) + (stl->neighbors_start[facet_num].neighbor[2] == -1)) {
case 0: // Facet has 3 neighbors
@ -636,9 +626,6 @@ void stl_remove_unconnected_facets(stl_file *stl)
void stl_fill_holes(stl_file *stl)
{
if (stl->error)
return;
// Insert all unconnected edges into hash list.
HashTableEdges hash_table(stl->stats.number_of_facets);
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
@ -720,8 +707,6 @@ void stl_fill_holes(stl_file *stl)
void stl_add_facet(stl_file *stl, const stl_facet *new_facet)
{
if (stl->error)
return;
assert(stl->facet_start.size() == stl->stats.number_of_facets);
assert(stl->neighbors_start.size() == stl->stats.number_of_facets);
stl->facet_start.emplace_back(*new_facet);

View file

@ -29,61 +29,43 @@
static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag);
static void
stl_reverse_facet(stl_file *stl, int facet_num) {
stl_vertex tmp_vertex;
/* int tmp_neighbor;*/
int neighbor[3];
int vnot[3];
static void reverse_facet(stl_file *stl, int facet_num)
{
stl->stats.facets_reversed += 1;
neighbor[0] = stl->neighbors_start[facet_num].neighbor[0];
neighbor[1] = stl->neighbors_start[facet_num].neighbor[1];
neighbor[2] = stl->neighbors_start[facet_num].neighbor[2];
vnot[0] = stl->neighbors_start[facet_num].which_vertex_not[0];
vnot[1] = stl->neighbors_start[facet_num].which_vertex_not[1];
vnot[2] = stl->neighbors_start[facet_num].which_vertex_not[2];
int neighbor[3] = { stl->neighbors_start[facet_num].neighbor[0], stl->neighbors_start[facet_num].neighbor[1], stl->neighbors_start[facet_num].neighbor[2] };
int vnot[3] = { stl->neighbors_start[facet_num].which_vertex_not[0], stl->neighbors_start[facet_num].which_vertex_not[1], stl->neighbors_start[facet_num].which_vertex_not[2] };
/* reverse the facet */
tmp_vertex = stl->facet_start[facet_num].vertex[0];
// reverse the facet
stl_vertex tmp_vertex = stl->facet_start[facet_num].vertex[0];
stl->facet_start[facet_num].vertex[0] =
stl->facet_start[facet_num].vertex[1];
stl->facet_start[facet_num].vertex[1] = tmp_vertex;
/* fix the vnots of the neighboring facets */
// fix the vnots of the neighboring facets
if (neighbor[0] != -1)
stl->neighbors_start[neighbor[0]].which_vertex_not[(vnot[0] + 1) % 3] =
(stl->neighbors_start[neighbor[0]].
which_vertex_not[(vnot[0] + 1) % 3] + 3) % 6;
stl->neighbors_start[neighbor[0]].which_vertex_not[(vnot[0] + 1) % 3] = (stl->neighbors_start[neighbor[0]].which_vertex_not[(vnot[0] + 1) % 3] + 3) % 6;
if (neighbor[1] != -1)
stl->neighbors_start[neighbor[1]].which_vertex_not[(vnot[1] + 1) % 3] =
(stl->neighbors_start[neighbor[1]].
which_vertex_not[(vnot[1] + 1) % 3] + 4) % 6;
stl->neighbors_start[neighbor[1]].which_vertex_not[(vnot[1] + 1) % 3] = (stl->neighbors_start[neighbor[1]].which_vertex_not[(vnot[1] + 1) % 3] + 4) % 6;
if (neighbor[2] != -1)
stl->neighbors_start[neighbor[2]].which_vertex_not[(vnot[2] + 1) % 3] =
(stl->neighbors_start[neighbor[2]].
which_vertex_not[(vnot[2] + 1) % 3] + 2) % 6;
stl->neighbors_start[neighbor[2]].which_vertex_not[(vnot[2] + 1) % 3] = (stl->neighbors_start[neighbor[2]].which_vertex_not[(vnot[2] + 1) % 3] + 2) % 6;
/* swap the neighbors of the facet that is being reversed */
// swap the neighbors of the facet that is being reversed
stl->neighbors_start[facet_num].neighbor[1] = neighbor[2];
stl->neighbors_start[facet_num].neighbor[2] = neighbor[1];
/* swap the vnots of the facet that is being reversed */
// swap the vnots of the facet that is being reversed
stl->neighbors_start[facet_num].which_vertex_not[1] = vnot[2];
stl->neighbors_start[facet_num].which_vertex_not[2] = vnot[1];
/* reverse the values of the vnots of the facet that is being reversed */
stl->neighbors_start[facet_num].which_vertex_not[0] =
(stl->neighbors_start[facet_num].which_vertex_not[0] + 3) % 6;
stl->neighbors_start[facet_num].which_vertex_not[1] =
(stl->neighbors_start[facet_num].which_vertex_not[1] + 3) % 6;
stl->neighbors_start[facet_num].which_vertex_not[2] =
(stl->neighbors_start[facet_num].which_vertex_not[2] + 3) % 6;
// reverse the values of the vnots of the facet that is being reversed
stl->neighbors_start[facet_num].which_vertex_not[0] = (stl->neighbors_start[facet_num].which_vertex_not[0] + 3) % 6;
stl->neighbors_start[facet_num].which_vertex_not[1] = (stl->neighbors_start[facet_num].which_vertex_not[1] + 3) % 6;
stl->neighbors_start[facet_num].which_vertex_not[2] = (stl->neighbors_start[facet_num].which_vertex_not[2] + 3) % 6;
}
void
stl_fix_normal_directions(stl_file *stl) {
void stl_fix_normal_directions(stl_file *stl)
{
/* int edge_num;*/
/* int vnot;*/
int checked = 0;
@ -104,8 +86,6 @@ stl_fix_normal_directions(stl_file *stl) {
int id;
int force_exit = 0;
if (stl->error) return;
// this may happen for malformed models, see: https://github.com/prusa3d/PrusaSlicer/issues/2209
if (stl->stats.number_of_facets == 0) return;
@ -125,7 +105,7 @@ stl_fix_normal_directions(stl_file *stl) {
Arbitrarily starts at face 0. If this one is wrong, we're screwed. Thankfully, the chances
of it being wrong randomly are low if most of the triangles are right: */
if (stl_check_normal_vector(stl, 0, 0) == 2) {
stl_reverse_facet(stl, 0);
reverse_facet(stl, 0);
reversed_ids[reversed_count++] = 0;
}
@ -144,12 +124,12 @@ stl_fix_normal_directions(stl_file *stl) {
if (norm_sw[stl->neighbors_start[facet_num].neighbor[j]] == 1) {
/* trying to modify a facet already marked as fixed, revert all changes made until now and exit (fixes: #716, #574, #413, #269, #262, #259, #230, #228, #206) */
for (id = reversed_count - 1; id >= 0; --id) {
stl_reverse_facet(stl, reversed_ids[id]);
reverse_facet(stl, reversed_ids[id]);
}
force_exit = 1;
break;
} else {
stl_reverse_facet(stl, stl->neighbors_start[facet_num].neighbor[j]);
reverse_facet(stl, stl->neighbors_start[facet_num].neighbor[j]);
reversed_ids[reversed_count++] = stl->neighbors_start[facet_num].neighbor[j];
}
}
@ -193,7 +173,7 @@ stl_fix_normal_directions(stl_file *stl) {
/* This is the first facet of the next part. */
facet_num = i;
if(stl_check_normal_vector(stl, i, 0) == 2) {
stl_reverse_facet(stl, i);
reverse_facet(stl, i);
reversed_ids[reversed_count++] = i;
}
@ -209,7 +189,8 @@ stl_fix_normal_directions(stl_file *stl) {
delete tail;
}
static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag) {
static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag)
{
/* Returns 0 if the normal is within tolerance */
/* Returns 1 if the normal is not within tolerance, but direction is OK */
/* Returns 2 if the normal is not within tolerance and backwards */
@ -260,24 +241,17 @@ static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_
return 4;
}
void stl_fix_normal_values(stl_file *stl) {
int i;
if (stl->error) return;
for(i = 0; i < stl->stats.number_of_facets; i++) {
void stl_fix_normal_values(stl_file *stl)
{
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
stl_check_normal_vector(stl, i, 1);
}
}
void stl_reverse_all_facets(stl_file *stl)
{
if (stl->error)
return;
stl_normal normal;
for(int i = 0; i < stl->stats.number_of_facets; i++) {
stl_reverse_facet(stl, i);
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
reverse_facet(stl, i);
stl_calculate_normal(normal, &stl->facet_start[i]);
stl_normalize_vector(normal);
stl->facet_start[i].normal = normal;

View file

@ -38,15 +38,10 @@ void stl_invalidate_shared_vertices(stl_file *stl)
void stl_generate_shared_vertices(stl_file *stl)
{
if (stl->error)
return;
/* make sure this function is idempotent and does not leak memory */
stl_invalidate_shared_vertices(stl);
// 3 indices to vertex per face
stl->v_indices.assign(stl->stats.number_of_facets, v_indices_struct());
// Shared vertices (3D coordinates)
stl->v_shared.clear();
stl->v_shared.reserve(stl->stats.number_of_facets / 2);
stl->stats.shared_vertices = 0;
@ -139,11 +134,8 @@ void stl_generate_shared_vertices(stl_file *stl)
}
}
void stl_write_off(stl_file *stl, const char *file)
bool stl_write_off(stl_file *stl, const char *file)
{
if (stl->error)
return;
/* Open the file */
FILE *fp = boost::nowide::fopen(file, "w");
if (fp == nullptr) {
@ -151,8 +143,7 @@ void stl_write_off(stl_file *stl, const char *file)
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file);
perror(error_msg);
free(error_msg);
stl->error = 1;
return;
return false;
}
fprintf(fp, "OFF\n");
@ -162,13 +153,11 @@ void stl_write_off(stl_file *stl, const char *file)
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
fprintf(fp, "\t3 %d %d %d\n", stl->v_indices[i].vertex[0], stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]);
fclose(fp);
return true;
}
void stl_write_vrml(stl_file *stl, const char *file)
bool stl_write_vrml(stl_file *stl, const char *file)
{
if (stl->error)
return;
/* Open the file */
FILE *fp = boost::nowide::fopen(file, "w");
if (fp == nullptr) {
@ -176,8 +165,7 @@ void stl_write_vrml(stl_file *stl, const char *file)
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file);
perror(error_msg);
free(error_msg);
stl->error = 1;
return;
return false;
}
fprintf(fp, "#VRML V1.0 ascii\n\n");
@ -210,12 +198,11 @@ void stl_write_vrml(stl_file *stl, const char *file)
fprintf(fp, "\t}\n");
fprintf(fp, "}\n");
fclose(fp);
return true;
}
void stl_write_obj (stl_file *stl, const char *file)
bool stl_write_obj(stl_file *stl, const char *file)
{
if (stl->error)
return;
FILE *fp = boost::nowide::fopen(file, "w");
if (fp == nullptr) {
@ -223,8 +210,7 @@ void stl_write_obj (stl_file *stl, const char *file)
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file);
perror(error_msg);
free(error_msg);
stl->error = 1;
return;
return false;
}
for (int i = 0; i < stl->stats.shared_vertices; ++ i)
@ -232,4 +218,5 @@ void stl_write_obj (stl_file *stl, const char *file)
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
fprintf(fp, "f %d %d %d\n", stl->v_indices[i].vertex[0]+1, stl->v_indices[i].vertex[1]+1, stl->v_indices[i].vertex[2]+1);
fclose(fp);
return true;
}

View file

@ -127,15 +127,9 @@ struct stl_stats {
int normals_fixed;
int number_of_parts;
int shared_vertices;
// hash table statistics
int malloced;
int freed;
int collisions;
};
struct stl_file {
FILE *fp;
std::vector<stl_facet> facet_start;
std::vector<stl_neighbors> neighbors_start;
// Indexed face set
@ -143,17 +137,15 @@ struct stl_file {
std::vector<stl_vertex> v_shared;
// Statistics
stl_stats stats;
char error;
};
extern void stl_open(stl_file *stl, const char *file);
extern void stl_close(stl_file *stl);
extern bool stl_open(stl_file *stl, const char *file);
extern void stl_stats_out(stl_file *stl, FILE *file, char *input_file);
extern void stl_print_neighbors(stl_file *stl, char *file);
extern bool stl_print_neighbors(stl_file *stl, char *file);
extern void stl_put_little_int(FILE *fp, int value_in);
extern void stl_put_little_float(FILE *fp, float value_in);
extern void stl_write_ascii(stl_file *stl, const char *file, const char *label);
extern void stl_write_binary(stl_file *stl, const char *file, const char *label);
extern bool stl_write_ascii(stl_file *stl, const char *file, const char *label);
extern bool stl_write_binary(stl_file *stl, const char *file, const char *label);
extern void stl_write_binary_block(stl_file *stl, FILE *fp);
extern void stl_check_facets_exact(stl_file *stl);
extern void stl_check_facets_nearby(stl_file *stl, float tolerance);
@ -161,7 +153,7 @@ extern void stl_remove_unconnected_facets(stl_file *stl);
extern void stl_write_vertex(stl_file *stl, int facet, int vertex);
extern void stl_write_facet(stl_file *stl, char *label, int facet);
extern void stl_write_neighbor(stl_file *stl, int facet);
extern void stl_write_quad_object(stl_file *stl, char *file);
extern bool stl_write_quad_object(stl_file *stl, char *file);
extern void stl_verify_neighbors(stl_file *stl);
extern void stl_fill_holes(stl_file *stl);
extern void stl_fix_normal_directions(stl_file *stl);
@ -183,9 +175,6 @@ extern void stl_get_size(stl_file *stl);
template<typename T>
extern void stl_transform(stl_file *stl, T *trafo3x4)
{
if (stl->error)
return;
for (uint32_t i_face = 0; i_face < stl->stats.number_of_facets; ++ i_face) {
stl_facet &face = stl->facet_start[i_face];
for (int i_vertex = 0; i_vertex < 3; ++ i_vertex) {
@ -208,9 +197,6 @@ extern void stl_transform(stl_file *stl, T *trafo3x4)
template<typename T>
inline void stl_transform(stl_file *stl, const Eigen::Transform<T, 3, Eigen::Affine, Eigen::DontAlign>& t)
{
if (stl->error)
return;
const Eigen::Matrix<double, 3, 3, Eigen::DontAlign> r = t.matrix().template block<3, 3>(0, 0);
for (size_t i = 0; i < stl->stats.number_of_facets; ++i) {
stl_facet &f = stl->facet_start[i];
@ -225,9 +211,6 @@ inline void stl_transform(stl_file *stl, const Eigen::Transform<T, 3, Eigen::Aff
template<typename T>
inline void stl_transform(stl_file *stl, const Eigen::Matrix<T, 3, 3, Eigen::DontAlign>& m)
{
if (stl->error)
return;
for (size_t i = 0; i < stl->stats.number_of_facets; ++i) {
stl_facet &f = stl->facet_start[i];
for (size_t j = 0; j < 3; ++j)
@ -238,13 +221,12 @@ inline void stl_transform(stl_file *stl, const Eigen::Matrix<T, 3, 3, Eigen::Don
stl_get_size(stl);
}
extern void stl_open_merge(stl_file *stl, char *file);
extern void stl_invalidate_shared_vertices(stl_file *stl);
extern void stl_generate_shared_vertices(stl_file *stl);
extern void stl_write_obj(stl_file *stl, const char *file);
extern void stl_write_off(stl_file *stl, const char *file);
extern void stl_write_dxf(stl_file *stl, const char *file, char *label);
extern void stl_write_vrml(stl_file *stl, const char *file);
extern bool stl_write_obj(stl_file *stl, const char *file);
extern bool stl_write_off(stl_file *stl, const char *file);
extern bool stl_write_dxf(stl_file *stl, const char *file, char *label);
extern bool stl_write_vrml(stl_file *stl, const char *file);
inline void stl_calculate_normal(stl_normal &normal, stl_facet *facet) {
normal = (facet->vertex[1] - facet->vertex[0]).cross(facet->vertex[2] - facet->vertex[0]);
}
@ -263,17 +245,13 @@ 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_initialize(stl_file *stl);
extern void stl_count_facets(stl_file *stl, const char *file);
extern void stl_reset(stl_file *stl);
extern void stl_allocate(stl_file *stl);
extern void stl_read(stl_file *stl, int first_facet, bool first);
extern void stl_facet_stats(stl_file *stl, stl_facet facet, bool &first);
extern void stl_reallocate(stl_file *stl);
extern void stl_add_facet(stl_file *stl, const stl_facet *new_facet);
extern void stl_clear_error(stl_file *stl);
extern int stl_get_error(stl_file *stl);
extern void stl_exit_on_error(stl_file *stl);
// Validate the mesh, assert on error.
extern bool stl_validate(stl_file *stl);

View file

@ -33,10 +33,8 @@
#define SEEK_END 2
#endif
void
stl_stats_out(stl_file *stl, FILE *file, char *input_file) {
if (stl->error) return;
void stl_stats_out(stl_file *stl, FILE *file, char *input_file)
{
/* this is here for Slic3r, without our config.h
it won't use this part of the code anyway */
#ifndef VERSION
@ -107,12 +105,10 @@ Backwards edges : %5d\n", stl->stats.backwards_edges);
Normals fixed : %5d\n", stl->stats.normals_fixed);
}
void
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;
if (stl->error) return;
/* Open the file */
FILE *fp = boost::nowide::fopen(file, "w");
if(fp == NULL) {
@ -122,8 +118,7 @@ stl_write_ascii(stl_file *stl, const char *file, const char *label) {
file);
perror(error_msg);
free(error_msg);
stl->error = 1;
return;
return false;
}
fprintf(fp, "solid %s\n", label);
@ -149,15 +144,14 @@ stl_write_ascii(stl_file *stl, const char *file, const char *label) {
fprintf(fp, "endsolid %s\n", label);
fclose(fp);
return true;
}
void
stl_print_neighbors(stl_file *stl, char *file) {
bool stl_print_neighbors(stl_file *stl, char *file)
{
FILE *fp;
char *error_msg;
if (stl->error) return;
/* Open the file */
fp = boost::nowide::fopen(file, "w");
if(fp == NULL) {
@ -167,8 +161,7 @@ stl_print_neighbors(stl_file *stl, char *file) {
file);
perror(error_msg);
free(error_msg);
stl->error = 1;
return;
return false;
}
for (uint32_t i = 0; i < stl->stats.number_of_facets; i++) {
@ -182,6 +175,7 @@ stl_print_neighbors(stl_file *stl, char *file) {
(int)stl->neighbors_start[i].which_vertex_not[2]);
}
fclose(fp);
return true;
}
#ifndef BOOST_LITTLE_ENDIAN
@ -195,13 +189,11 @@ void stl_internal_reverse_quads(char *buf, size_t cnt)
}
#endif
void
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;
char *error_msg;
if (stl->error) return;
/* Open the file */
fp = boost::nowide::fopen(file, "wb");
if(fp == NULL) {
@ -211,8 +203,7 @@ stl_write_binary(stl_file *stl, const char *file, const char *label) {
file);
perror(error_msg);
free(error_msg);
stl->error = 1;
return;
return false;
}
fprintf(fp, "%s", label);
@ -237,29 +228,27 @@ stl_write_binary(stl_file *stl, const char *file, const char *label) {
}
#endif /* BOOST_LITTLE_ENDIAN */
fclose(fp);
return true;
}
void
stl_write_vertex(stl_file *stl, int facet, int vertex) {
if (stl->error) return;
void stl_write_vertex(stl_file *stl, int facet, int vertex)
{
printf(" vertex %d/%d % .8E % .8E % .8E\n", vertex, facet,
stl->facet_start[facet].vertex[vertex](0),
stl->facet_start[facet].vertex[vertex](1),
stl->facet_start[facet].vertex[vertex](2));
}
void
stl_write_facet(stl_file *stl, char *label, int facet) {
if (stl->error) return;
void stl_write_facet(stl_file *stl, char *label, int facet)
{
printf("facet (%d)/ %s\n", facet, label);
stl_write_vertex(stl, facet, 0);
stl_write_vertex(stl, facet, 1);
stl_write_vertex(stl, facet, 2);
}
void
stl_write_neighbor(stl_file *stl, int facet) {
if (stl->error) return;
void stl_write_neighbor(stl_file *stl, int facet)
{
printf("Neighbors %d: %d, %d, %d ; %d, %d, %d\n", facet,
stl->neighbors_start[facet].neighbor[0],
stl->neighbors_start[facet].neighbor[1],
@ -269,8 +258,8 @@ stl_write_neighbor(stl_file *stl, int facet) {
stl->neighbors_start[facet].which_vertex_not[2]);
}
void
stl_write_quad_object(stl_file *stl, char *file) {
bool stl_write_quad_object(stl_file *stl, char *file)
{
FILE *fp;
char *error_msg;
stl_vertex connect_color = stl_vertex::Zero();
@ -279,8 +268,6 @@ stl_write_quad_object(stl_file *stl, char *file) {
stl_vertex uncon_3_color = stl_vertex::Zero();
stl_vertex color;
if (stl->error) return;
/* Open the file */
fp = boost::nowide::fopen(file, "w");
if(fp == NULL) {
@ -290,8 +277,7 @@ stl_write_quad_object(stl_file *stl, char *file) {
file);
perror(error_msg);
free(error_msg);
stl->error = 1;
return;
return false;
}
fprintf(fp, "CQUAD\n");
@ -326,15 +312,14 @@ stl_write_quad_object(stl_file *stl, char *file) {
stl->facet_start[i].vertex[2](2), color(0), color(1), color(2));
}
fclose(fp);
return true;
}
void 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;
char *error_msg;
if (stl->error) return;
/* Open the file */
fp = boost::nowide::fopen(file, "w");
if(fp == NULL) {
@ -344,8 +329,7 @@ void stl_write_dxf(stl_file *stl, const char *file, char *label)
file);
perror(error_msg);
free(error_msg);
stl->error = 1;
return;
return false;
}
fprintf(fp, "999\n%s\n", label);
@ -375,22 +359,5 @@ void stl_write_dxf(stl_file *stl, const char *file, char *label)
fprintf(fp, "0\nENDSEC\n0\nEOF\n");
fclose(fp);
}
void
stl_clear_error(stl_file *stl) {
stl->error = 0;
}
void
stl_exit_on_error(stl_file *stl) {
if (!stl->error) return;
stl->error = 0;
stl_close(stl);
exit(1);
}
int
stl_get_error(stl_file *stl) {
return stl->error;
return true;
}

View file

@ -35,42 +35,8 @@
#error "SEEK_SET not defined"
#endif
void stl_open(stl_file *stl, const char *file)
static FILE* stl_open_count_facets(stl_file *stl, const char *file)
{
stl_initialize(stl);
stl_count_facets(stl, file);
stl_allocate(stl);
stl_read(stl, 0, true);
if (stl->fp != nullptr) {
fclose(stl->fp);
stl->fp = nullptr;
}
}
void stl_initialize(stl_file *stl)
{
stl->fp = nullptr;
stl->error = 0;
stl->facet_start.clear();
stl->neighbors_start.clear();
stl->v_indices.clear();
stl->v_shared.clear();
memset(&stl->stats, 0, sizeof(stl_stats));
stl->stats.volume = -1.0;
}
void stl_close(stl_file *stl)
{
assert(stl->fp == nullptr);
stl_initialize(stl);
}
#ifndef BOOST_LITTLE_ENDIAN
extern void stl_internal_reverse_quads(char *buf, size_t cnt);
#endif /* BOOST_LITTLE_ENDIAN */
void
stl_count_facets(stl_file *stl, const char *file) {
long file_size;
uint32_t header_num_facets;
uint32_t num_facets;
@ -80,30 +46,27 @@ stl_count_facets(stl_file *stl, const char *file) {
int num_lines = 1;
char *error_msg;
if (stl->error) return;
/* Open the file in binary mode first */
stl->fp = boost::nowide::fopen(file, "rb");
if(stl->fp == NULL) {
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);
stl->error = 1;
return;
return nullptr;
}
/* Find size of file */
fseek(stl->fp, 0, SEEK_END);
file_size = ftell(stl->fp);
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
/* Check for binary or ASCII file */
fseek(stl->fp, HEADER_SIZE, SEEK_SET);
if (!fread(chtest, sizeof(chtest), 1, stl->fp)) {
fseek(fp, HEADER_SIZE, SEEK_SET);
if (!fread(chtest, sizeof(chtest), 1, fp)) {
perror("The input is an empty file");
stl->error = 1;
return;
fclose(fp);
return nullptr;
}
stl->stats.type = ascii;
for(s = 0; s < sizeof(chtest); s++) {
@ -112,7 +75,7 @@ stl_count_facets(stl_file *stl, const char *file) {
break;
}
}
rewind(stl->fp);
rewind(fp);
/* Get the header and the number of facets in the .STL file */
/* If the .STL file is binary, then do the following */
@ -121,18 +84,18 @@ stl_count_facets(stl_file *stl, const char *file) {
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);
stl->error = 1;
return;
fclose(fp);
return nullptr;
}
num_facets = (file_size - HEADER_SIZE) / SIZEOF_STL_FACET;
/* Read the header */
if (fread(stl->stats.header, LABEL_SIZE, 1, stl->fp) > 79) {
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, stl->fp) != 0;
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);
@ -147,23 +110,23 @@ stl_count_facets(stl_file *stl, const char *file) {
/* 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....
stl->fp = boost::nowide::freopen(file, "r", stl->fp);
fp = boost::nowide::freopen(file, "r", fp);
// do another null check to be safe
if(stl->fp == NULL) {
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);
stl->error = 1;
return;
fclose(fp);
return nullptr;
}
/* Find the number of facets */
char linebuf[100];
while (fgets(linebuf, 100, stl->fp) != NULL) {
while (fgets(linebuf, 100, fp) != nullptr) {
/* don't count short lines */
if (strlen(linebuf) <= 4) continue;
@ -173,11 +136,11 @@ stl_count_facets(stl_file *stl, const char *file) {
++num_lines;
}
rewind(stl->fp);
rewind(fp);
/* Get the header */
for(i = 0;
(i < 80) && (stl->stats.header[i] = getc(stl->fp)) != '\n'; i++);
(i < 80) && (stl->stats.header[i] = getc(fp)) != '\n'; i++);
stl->stats.header[i] = '\0'; /* Lose the '\n' */
stl->stats.header[80] = '\0';
@ -185,84 +148,20 @@ stl_count_facets(stl_file *stl, const char *file) {
}
stl->stats.number_of_facets += num_facets;
stl->stats.original_num_facets = stl->stats.number_of_facets;
return fp;
}
void stl_allocate(stl_file *stl)
{
if (stl->error)
return;
// Allocate memory for the entire .STL file.
stl->facet_start.assign(stl->stats.number_of_facets, stl_facet());
// Allocate memory for the neighbors list.
stl->neighbors_start.assign(stl->stats.number_of_facets, stl_neighbors());
}
void
stl_open_merge(stl_file *stl, char *file_to_merge) {
int num_facets_so_far;
stl_type origStlType;
FILE *origFp;
stl_file stl_to_merge;
if (stl->error) return;
/* Record how many facets we have so far from the first file. We will start putting
facets in the next position. Since we're 0-indexed, it'l be the same position. */
num_facets_so_far = stl->stats.number_of_facets;
/* Record the file type we started with: */
origStlType=stl->stats.type;
/* Record the file pointer too: */
origFp=stl->fp;
/* Initialize the sturucture with zero stats, header info and sizes: */
stl_initialize(&stl_to_merge);
stl_count_facets(&stl_to_merge, file_to_merge);
/* Copy what we need to into stl so that we can read the file_to_merge directly into it
using stl_read: Save the rest of the valuable info: */
stl->stats.type=stl_to_merge.stats.type;
stl->fp=stl_to_merge.fp;
/* Add the number of facets we already have in stl with what we we found in stl_to_merge but
haven't read yet. */
stl->stats.number_of_facets=num_facets_so_far+stl_to_merge.stats.number_of_facets;
/* Allocate enough room for stl->stats.number_of_facets facets and neighbors: */
stl_reallocate(stl);
/* Read the file to merge directly into stl, adding it to what we have already.
Start at num_facets_so_far, the index to the first unused facet. Also say
that this isn't our first time so we should augment stats like min and max
instead of erasing them. */
stl_read(stl, num_facets_so_far, false);
/* Restore the stl information we overwrote (for stl_read) so that it still accurately
reflects the subject part: */
stl->stats.type=origStlType;
stl->fp=origFp;
}
void stl_reallocate(stl_file *stl)
{
if (stl->error)
return;
stl->facet_start.resize(stl->stats.number_of_facets);
stl->neighbors_start.resize(stl->stats.number_of_facets);
}
/* Reads the contents of the file pointed to by stl->fp into the stl structure,
/* Reads the contents of the file pointed to by fp into the stl structure,
starting at facet first_facet. The second argument says if it's our first
time running this for the stl and therefore we should reset our max and min stats. */
void stl_read(stl_file *stl, int first_facet, bool first) {
static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first)
{
stl_facet facet;
if (stl->error) return;
if(stl->stats.type == binary) {
fseek(stl->fp, HEADER_SIZE, SEEK_SET);
fseek(fp, HEADER_SIZE, SEEK_SET);
} else {
rewind(stl->fp);
rewind(fp);
}
char normal_buf[3][32];
@ -271,10 +170,8 @@ void stl_read(stl_file *stl, int first_facet, bool first) {
/* Read a single facet from a binary .STL file */
{
/* we assume little-endian architecture! */
if (fread(&facet, 1, SIZEOF_STL_FACET, stl->fp) != SIZEOF_STL_FACET) {
stl->error = 1;
return;
}
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);
@ -284,27 +181,26 @@ void stl_read(stl_file *stl, int first_facet, bool first) {
{
// skip solid/endsolid
// (in this order, otherwise it won't work when they are paired in the middle of a file)
fscanf(stl->fp, "endsolid%*[^\n]\n");
fscanf(stl->fp, "solid%*[^\n]\n"); // name might contain spaces so %*s doesn't work and it also can be empty (just "solid")
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(stl->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);
int res_outer_loop = fscanf(stl->fp, " outer loop");
int res_outer_loop = fscanf(fp, " outer loop");
assert(res_outer_loop == 0);
int res_vertex1 = fscanf(stl->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);
int res_vertex2 = fscanf(stl->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);
int res_vertex3 = fscanf(stl->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);
int res_endloop = fscanf(stl->fp, " endloop");
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(stl->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) {
perror("Something is syntactically very wrong with this ASCII STL!");
stl->error = 1;
return;
return false;
}
// The facet normal has been parsed as a single string as to workaround for not a numbers in the normal definition.
@ -338,13 +234,51 @@ void stl_read(stl_file *stl, int first_facet, bool 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)
{
stl_reset(stl);
FILE *fp = stl_open_count_facets(stl, file);
if (fp == nullptr)
return false;
stl_allocate(stl);
bool result = stl_read(stl, fp, 0, true);
fclose(fp);
return result;
}
void stl_reset(stl_file *stl)
{
stl->facet_start.clear();
stl->neighbors_start.clear();
stl->v_indices.clear();
stl->v_shared.clear();
memset(&stl->stats, 0, sizeof(stl_stats));
stl->stats.volume = -1.0;
}
#ifndef BOOST_LITTLE_ENDIAN
extern void stl_internal_reverse_quads(char *buf, size_t cnt);
#endif /* BOOST_LITTLE_ENDIAN */
void stl_allocate(stl_file *stl)
{
// Allocate memory for the entire .STL file.
stl->facet_start.assign(stl->stats.number_of_facets, stl_facet());
// Allocate memory for the neighbors list.
stl->neighbors_start.assign(stl->stats.number_of_facets, stl_neighbors());
}
void stl_reallocate(stl_file *stl)
{
stl->facet_start.resize(stl->stats.number_of_facets);
stl->neighbors_start.resize(stl->stats.number_of_facets);
}
void stl_facet_stats(stl_file *stl, stl_facet facet, bool &first)
{
if (stl->error)
return;
// While we are going through all of the facets, let's find the
// maximum and minimum values for x, y, and z

View file

@ -34,9 +34,6 @@ static float get_volume(stl_file *stl);
void stl_verify_neighbors(stl_file *stl)
{
if (stl->error)
return;
stl->stats.backwards_edges = 0;
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
@ -69,9 +66,6 @@ void stl_verify_neighbors(stl_file *stl)
void stl_translate(stl_file *stl, float x, float y, float z)
{
if (stl->error)
return;
stl_vertex new_min(x, y, z);
stl_vertex shift = new_min - stl->stats.min;
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
@ -85,9 +79,6 @@ void stl_translate(stl_file *stl, float x, float y, float z)
/* Translates the stl by x,y,z, relatively from wherever it is currently */
void stl_translate_relative(stl_file *stl, float x, float y, float z)
{
if (stl->error)
return;
stl_vertex shift(x, y, z);
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
for (int j = 0; j < 3; ++ j)
@ -99,9 +90,6 @@ void stl_translate_relative(stl_file *stl, float x, float y, float z)
void stl_scale_versor(stl_file *stl, const stl_vertex &versor)
{
if (stl->error)
return;
// Scale extents.
auto s = versor.array();
stl->stats.min.array() *= s;
@ -120,9 +108,6 @@ void stl_scale_versor(stl_file *stl, const stl_vertex &versor)
static void calculate_normals(stl_file *stl)
{
if (stl->error)
return;
stl_normal normal;
for(uint32_t i = 0; i < stl->stats.number_of_facets; i++) {
stl_calculate_normal(normal, &stl->facet_start[i]);
@ -139,8 +124,6 @@ stl_rotate_x(stl_file *stl, float angle) {
double c = cos(radian_angle);
double s = sin(radian_angle);
if (stl->error) return;
for(i = 0; i < stl->stats.number_of_facets; i++) {
for(j = 0; j < 3; j++) {
stl_rotate(&stl->facet_start[i].vertex[j](1),
@ -159,8 +142,6 @@ stl_rotate_y(stl_file *stl, float angle) {
double c = cos(radian_angle);
double s = sin(radian_angle);
if (stl->error) return;
for(i = 0; i < stl->stats.number_of_facets; i++) {
for(j = 0; j < 3; j++) {
stl_rotate(&stl->facet_start[i].vertex[j](2),
@ -179,8 +160,6 @@ stl_rotate_z(stl_file *stl, float angle) {
double c = cos(radian_angle);
double s = sin(radian_angle);
if (stl->error) return;
for(i = 0; i < stl->stats.number_of_facets; i++) {
for(j = 0; j < 3; j++) {
stl_rotate(&stl->facet_start[i].vertex[j](0),
@ -203,7 +182,7 @@ stl_rotate(float *x, float *y, const double c, const double s) {
void stl_get_size(stl_file *stl)
{
if (stl->error || stl->stats.number_of_facets == 0)
if (stl->stats.number_of_facets == 0)
return;
stl->stats.min = stl->facet_start[0].vertex[0];
stl->stats.max = stl->stats.min;
@ -220,9 +199,6 @@ void stl_get_size(stl_file *stl)
void stl_mirror_xy(stl_file *stl)
{
if (stl->error)
return;
for(int i = 0; i < stl->stats.number_of_facets; i++) {
for(int j = 0; j < 3; j++) {
stl->facet_start[i].vertex[j](2) *= -1.0;
@ -239,8 +215,6 @@ void stl_mirror_xy(stl_file *stl)
void stl_mirror_yz(stl_file *stl)
{
if (stl->error) return;
for (int i = 0; i < stl->stats.number_of_facets; i++) {
for (int j = 0; j < 3; j++) {
stl->facet_start[i].vertex[j](0) *= -1.0;
@ -257,9 +231,6 @@ void stl_mirror_yz(stl_file *stl)
void stl_mirror_xz(stl_file *stl)
{
if (stl->error)
return;
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
for (int j = 0; j < 3; ++ j)
stl->facet_start[i].vertex[j](1) *= -1.0;
@ -274,9 +245,6 @@ void stl_mirror_xz(stl_file *stl)
static float get_volume(stl_file *stl)
{
if (stl->error)
return 0;
// Choose a point, any point as the reference.
stl_vertex p0 = stl->facet_start[0].vertex[0];
float volume = 0.f;
@ -291,7 +259,6 @@ static float get_volume(stl_file *stl)
void stl_calculate_volume(stl_file *stl)
{
if (stl->error) return;
stl->stats.volume = get_volume(stl);
if(stl->stats.volume < 0.0) {
stl_reverse_all_facets(stl);
@ -346,8 +313,6 @@ void stl_repair(stl_file *stl,
int i;
int last_edges_fixed = 0;
if (stl->error) return;
if(exact_flag || fixall_flag || nearby_flag || remove_unconnected_flag
|| fill_holes_flag || normal_directions_flag) {
if (verbose_flag)
@ -453,8 +418,6 @@ All facets connected. No further nearby check necessary.\n");
// Check validity of the mesh, assert on error.
bool stl_validate(stl_file *stl)
{
assert(! stl->error);
assert(stl->fp == nullptr);
assert(! stl->facet_start.empty());
assert(stl->facet_start.size() == stl->stats.number_of_facets);
assert(stl->neighbors_start.size() == stl->stats.number_of_facets);

View file

@ -161,7 +161,6 @@ static void extract_model_from_archive(
else {
// Header has been extracted. Now read the faces.
stl_file &stl = mesh.stl;
stl.error = 0;
stl.stats.type = inmemory;
stl.stats.number_of_facets = header.nTriangles;
stl.stats.original_num_facets = header.nTriangles;

View file

@ -17,8 +17,7 @@ namespace Slic3r {
bool load_stl(const char *path, Model *model, const char *object_name_in)
{
TriangleMesh mesh;
mesh.ReadSTLFile(path);
if (mesh.stl.error) {
if (! mesh.ReadSTLFile(path)) {
// die "Failed to open $file\n" if !-e $path;
return false;
}

View file

@ -45,7 +45,7 @@ namespace Slic3r {
TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector<Vec3crd>& facets)
: repaired(false)
{
stl_initialize(&this->stl);
stl_reset(&this->stl);
stl_file &stl = this->stl;
stl.stats.type = inmemory;
@ -74,7 +74,7 @@ TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector<Vec3crd>& f
TriangleMesh& TriangleMesh::operator=(const TriangleMesh &other)
{
stl_close(&this->stl);
stl_reset(&this->stl);
this->stl = other.stl;
this->repaired = other.repaired;
return *this;
@ -426,7 +426,6 @@ TriangleMeshPtrs TriangleMesh::split() const
mesh->stl.stats.type = inmemory;
mesh->stl.stats.number_of_facets = (uint32_t)facets.size();
mesh->stl.stats.original_num_facets = mesh->stl.stats.number_of_facets;
stl_clear_error(&mesh->stl);
stl_allocate(&mesh->stl);
// Assign the facets to the new mesh.

View file

@ -21,18 +21,18 @@ typedef std::vector<TriangleMesh*> TriangleMeshPtrs;
class TriangleMesh
{
public:
TriangleMesh() : repaired(false) { stl_initialize(&this->stl); }
TriangleMesh() : repaired(false) { stl_reset(&this->stl); }
TriangleMesh(const Pointf3s &points, const std::vector<Vec3crd> &facets);
TriangleMesh(const TriangleMesh &other) : repaired(false) { stl_initialize(&this->stl); *this = other; }
TriangleMesh(TriangleMesh &&other) : repaired(false) { stl_initialize(&this->stl); this->swap(other); }
TriangleMesh(const TriangleMesh &other) : repaired(false) { stl_reset(&this->stl); *this = other; }
TriangleMesh(TriangleMesh &&other) : repaired(false) { stl_reset(&this->stl); this->swap(other); }
~TriangleMesh() { clear(); }
TriangleMesh& operator=(const TriangleMesh &other);
TriangleMesh& operator=(TriangleMesh &&other) { this->swap(other); return *this; }
void clear() { stl_close(&this->stl); this->repaired = false; }
void clear() { stl_reset(&this->stl); this->repaired = false; }
void swap(TriangleMesh &other) { std::swap(this->stl, other.stl); std::swap(this->repaired, other.repaired); }
void ReadSTLFile(const char* input_file) { stl_open(&stl, input_file); }
void write_ascii(const char* output_file) { stl_write_ascii(&this->stl, output_file, ""); }
void write_binary(const char* output_file) { stl_write_binary(&this->stl, output_file, ""); }
bool ReadSTLFile(const char* input_file) { return stl_open(&stl, input_file); }
bool write_ascii(const char* output_file) { return stl_write_ascii(&this->stl, output_file, ""); }
bool write_binary(const char* output_file) { return stl_write_binary(&this->stl, output_file, ""); }
void repair();
float volume();
void check_topology();

View file

@ -46,7 +46,6 @@ TriangleMesh::ReadFromPerl(vertices, facets)
SV* facets
CODE:
stl_file &stl = THIS->stl;
stl.error = 0;
stl.stats.type = inmemory;
// count facets and allocate memory