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. // floats of the first edge matches all six floats of the second edge.
void stl_check_facets_exact(stl_file *stl) void stl_check_facets_exact(stl_file *stl)
{ {
if (stl->error)
return;
stl->stats.connected_edges = 0; stl->stats.connected_edges = 0;
stl->stats.connected_facets_1_edge = 0; stl->stats.connected_facets_1_edge = 0;
stl->stats.connected_facets_2_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) 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) 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_2_edge == stl->stats.number_of_facets)
&& (stl->stats.connected_facets_3_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 // 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 // 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(). // stl_check_facets_nearby().
if (stl->error)
return;
auto remove_facet = [stl](int facet_number) auto remove_facet = [stl](int facet_number)
{ {
++ stl->stats.facets_removed; ++ stl->stats.facets_removed;
@ -526,7 +517,6 @@ void stl_remove_unconnected_facets(stl_file *stl)
{ {
// Update statistics on face connectivity. // Update statistics on face connectivity.
auto stl_update_connects_remove_1 = [stl](int facet_num) { auto stl_update_connects_remove_1 = [stl](int facet_num) {
assert(! stl->error);
//FIXME when decreasing 3_edge, should I increase 2_edge etc? //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)) { 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 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) void stl_fill_holes(stl_file *stl)
{ {
if (stl->error)
return;
// Insert all unconnected edges into hash list. // Insert all unconnected edges into hash list.
HashTableEdges hash_table(stl->stats.number_of_facets); HashTableEdges hash_table(stl->stats.number_of_facets);
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { 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) 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->facet_start.size() == stl->stats.number_of_facets);
assert(stl->neighbors_start.size() == stl->stats.number_of_facets); assert(stl->neighbors_start.size() == stl->stats.number_of_facets);
stl->facet_start.emplace_back(*new_facet); 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 int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag);
static void static void reverse_facet(stl_file *stl, int facet_num)
stl_reverse_facet(stl_file *stl, int facet_num) { {
stl_vertex tmp_vertex; stl->stats.facets_reversed += 1;
/* int tmp_neighbor;*/
int neighbor[3];
int vnot[3];
stl->stats.facets_reversed += 1; 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] };
neighbor[0] = stl->neighbors_start[facet_num].neighbor[0]; // reverse the facet
neighbor[1] = stl->neighbors_start[facet_num].neighbor[1]; stl_vertex tmp_vertex = stl->facet_start[facet_num].vertex[0];
neighbor[2] = stl->neighbors_start[facet_num].neighbor[2]; stl->facet_start[facet_num].vertex[0] =
vnot[0] = stl->neighbors_start[facet_num].which_vertex_not[0]; stl->facet_start[facet_num].vertex[1];
vnot[1] = stl->neighbors_start[facet_num].which_vertex_not[1]; stl->facet_start[facet_num].vertex[1] = tmp_vertex;
vnot[2] = stl->neighbors_start[facet_num].which_vertex_not[2];
/* reverse the facet */ // fix the vnots of the neighboring facets
tmp_vertex = stl->facet_start[facet_num].vertex[0]; if (neighbor[0] != -1)
stl->facet_start[facet_num].vertex[0] = 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->facet_start[facet_num].vertex[1]; if (neighbor[1] != -1)
stl->facet_start[facet_num].vertex[1] = tmp_vertex; 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;
/* fix the vnots of the neighboring facets */ // swap the neighbors of the facet that is being reversed
if(neighbor[0] != -1) stl->neighbors_start[facet_num].neighbor[1] = neighbor[2];
stl->neighbors_start[neighbor[0]].which_vertex_not[(vnot[0] + 1) % 3] = stl->neighbors_start[facet_num].neighbor[2] = neighbor[1];
(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;
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;
/* swap the neighbors of the facet that is being reversed */ // swap the vnots of the facet that is being reversed
stl->neighbors_start[facet_num].neighbor[1] = neighbor[2]; stl->neighbors_start[facet_num].which_vertex_not[1] = vnot[2];
stl->neighbors_start[facet_num].neighbor[2] = neighbor[1]; stl->neighbors_start[facet_num].which_vertex_not[2] = vnot[1];
/* swap the vnots of the facet that is being reversed */ // reverse the values of 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[0] = (stl->neighbors_start[facet_num].which_vertex_not[0] + 3) % 6;
stl->neighbors_start[facet_num].which_vertex_not[2] = vnot[1]; 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 void stl_fix_normal_directions(stl_file *stl)
stl_fix_normal_directions(stl_file *stl) { {
/* int edge_num;*/ /* int edge_num;*/
/* int vnot;*/ /* int vnot;*/
int checked = 0; int checked = 0;
@ -104,8 +86,6 @@ stl_fix_normal_directions(stl_file *stl) {
int id; int id;
int force_exit = 0; int force_exit = 0;
if (stl->error) return;
// this may happen for malformed models, see: https://github.com/prusa3d/PrusaSlicer/issues/2209 // this may happen for malformed models, see: https://github.com/prusa3d/PrusaSlicer/issues/2209
if (stl->stats.number_of_facets == 0) return; 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 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: */ of it being wrong randomly are low if most of the triangles are right: */
if (stl_check_normal_vector(stl, 0, 0) == 2) { if (stl_check_normal_vector(stl, 0, 0) == 2) {
stl_reverse_facet(stl, 0); reverse_facet(stl, 0);
reversed_ids[reversed_count++] = 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) { 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) */ /* 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) { for (id = reversed_count - 1; id >= 0; --id) {
stl_reverse_facet(stl, reversed_ids[id]); reverse_facet(stl, reversed_ids[id]);
} }
force_exit = 1; force_exit = 1;
break; break;
} else { } 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]; 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. */ /* This is the first facet of the next part. */
facet_num = i; facet_num = i;
if(stl_check_normal_vector(stl, i, 0) == 2) { if(stl_check_normal_vector(stl, i, 0) == 2) {
stl_reverse_facet(stl, i); reverse_facet(stl, i);
reversed_ids[reversed_count++] = i; reversed_ids[reversed_count++] = i;
} }
@ -209,7 +189,8 @@ stl_fix_normal_directions(stl_file *stl) {
delete tail; 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 0 if the normal is within tolerance */
/* Returns 1 if the normal is not within tolerance, but direction is OK */ /* Returns 1 if the normal is not within tolerance, but direction is OK */
/* Returns 2 if the normal is not within tolerance and backwards */ /* Returns 2 if the normal is not within tolerance and backwards */
@ -260,26 +241,19 @@ static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_
return 4; return 4;
} }
void stl_fix_normal_values(stl_file *stl) { void stl_fix_normal_values(stl_file *stl)
int i; {
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
if (stl->error) return; stl_check_normal_vector(stl, i, 1);
for(i = 0; i < stl->stats.number_of_facets; i++) {
stl_check_normal_vector(stl, i, 1);
}
} }
void stl_reverse_all_facets(stl_file *stl) void stl_reverse_all_facets(stl_file *stl)
{ {
if (stl->error) stl_normal normal;
return; for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
reverse_facet(stl, i);
stl_normal normal; stl_calculate_normal(normal, &stl->facet_start[i]);
for(int i = 0; i < stl->stats.number_of_facets; i++) { stl_normalize_vector(normal);
stl_reverse_facet(stl, i); stl->facet_start[i].normal = normal;
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) 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 // 3 indices to vertex per face
stl->v_indices.assign(stl->stats.number_of_facets, v_indices_struct()); stl->v_indices.assign(stl->stats.number_of_facets, v_indices_struct());
// Shared vertices (3D coordinates) // Shared vertices (3D coordinates)
stl->v_shared.clear();
stl->v_shared.reserve(stl->stats.number_of_facets / 2); stl->v_shared.reserve(stl->stats.number_of_facets / 2);
stl->stats.shared_vertices = 0; 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 */ /* Open the file */
FILE *fp = boost::nowide::fopen(file, "w"); FILE *fp = boost::nowide::fopen(file, "w");
if (fp == nullptr) { 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); sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file);
perror(error_msg); perror(error_msg);
free(error_msg); free(error_msg);
stl->error = 1; return false;
return;
} }
fprintf(fp, "OFF\n"); 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) 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]); 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); 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 */ /* Open the file */
FILE *fp = boost::nowide::fopen(file, "w"); FILE *fp = boost::nowide::fopen(file, "w");
if (fp == nullptr) { 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); sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file);
perror(error_msg); perror(error_msg);
free(error_msg); free(error_msg);
stl->error = 1; return false;
return;
} }
fprintf(fp, "#VRML V1.0 ascii\n\n"); 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, "\t}\n");
fprintf(fp, "}\n"); fprintf(fp, "}\n");
fclose(fp); 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"); FILE *fp = boost::nowide::fopen(file, "w");
if (fp == nullptr) { 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); sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file);
perror(error_msg); perror(error_msg);
free(error_msg); free(error_msg);
stl->error = 1; return false;
return;
} }
for (int i = 0; i < stl->stats.shared_vertices; ++ i) 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) 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); 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); fclose(fp);
return true;
} }

View File

@ -127,15 +127,9 @@ struct stl_stats {
int normals_fixed; int normals_fixed;
int number_of_parts; int number_of_parts;
int shared_vertices; int shared_vertices;
// hash table statistics
int malloced;
int freed;
int collisions;
}; };
struct stl_file { struct stl_file {
FILE *fp;
std::vector<stl_facet> facet_start; std::vector<stl_facet> facet_start;
std::vector<stl_neighbors> neighbors_start; std::vector<stl_neighbors> neighbors_start;
// Indexed face set // Indexed face set
@ -143,17 +137,15 @@ struct stl_file {
std::vector<stl_vertex> v_shared; std::vector<stl_vertex> v_shared;
// Statistics // Statistics
stl_stats stats; stl_stats stats;
char error;
}; };
extern void stl_open(stl_file *stl, const char *file); extern bool stl_open(stl_file *stl, const char *file);
extern void stl_close(stl_file *stl);
extern void stl_stats_out(stl_file *stl, FILE *file, char *input_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_int(FILE *fp, int value_in);
extern void stl_put_little_float(FILE *fp, float 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 bool 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_binary(stl_file *stl, const char *file, const char *label);
extern void stl_write_binary_block(stl_file *stl, FILE *fp); 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_exact(stl_file *stl);
extern void stl_check_facets_nearby(stl_file *stl, float tolerance); 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_vertex(stl_file *stl, int facet, int vertex);
extern void stl_write_facet(stl_file *stl, char *label, int facet); 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_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_verify_neighbors(stl_file *stl);
extern void stl_fill_holes(stl_file *stl); extern void stl_fill_holes(stl_file *stl);
extern void stl_fix_normal_directions(stl_file *stl); extern void stl_fix_normal_directions(stl_file *stl);
@ -183,34 +175,28 @@ extern void stl_get_size(stl_file *stl);
template<typename T> template<typename T>
extern void stl_transform(stl_file *stl, T *trafo3x4) extern void stl_transform(stl_file *stl, T *trafo3x4)
{ {
if (stl->error) for (uint32_t i_face = 0; i_face < stl->stats.number_of_facets; ++ i_face) {
return; stl_facet &face = stl->facet_start[i_face];
for (int i_vertex = 0; i_vertex < 3; ++ i_vertex) {
stl_vertex &v_dst = face.vertex[i_vertex];
stl_vertex v_src = v_dst;
v_dst(0) = T(trafo3x4[0] * v_src(0) + trafo3x4[1] * v_src(1) + trafo3x4[2] * v_src(2) + trafo3x4[3]);
v_dst(1) = T(trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6] * v_src(2) + trafo3x4[7]);
v_dst(2) = T(trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2) + trafo3x4[11]);
}
stl_vertex &v_dst = face.normal;
stl_vertex v_src = v_dst;
v_dst(0) = T(trafo3x4[0] * v_src(0) + trafo3x4[1] * v_src(1) + trafo3x4[2] * v_src(2));
v_dst(1) = T(trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6] * v_src(2));
v_dst(2) = T(trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2));
}
for (uint32_t i_face = 0; i_face < stl->stats.number_of_facets; ++ i_face) { stl_get_size(stl);
stl_facet &face = stl->facet_start[i_face];
for (int i_vertex = 0; i_vertex < 3; ++ i_vertex) {
stl_vertex &v_dst = face.vertex[i_vertex];
stl_vertex v_src = v_dst;
v_dst(0) = T(trafo3x4[0] * v_src(0) + trafo3x4[1] * v_src(1) + trafo3x4[2] * v_src(2) + trafo3x4[3]);
v_dst(1) = T(trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6] * v_src(2) + trafo3x4[7]);
v_dst(2) = T(trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2) + trafo3x4[11]);
}
stl_vertex &v_dst = face.normal;
stl_vertex v_src = v_dst;
v_dst(0) = T(trafo3x4[0] * v_src(0) + trafo3x4[1] * v_src(1) + trafo3x4[2] * v_src(2));
v_dst(1) = T(trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6] * v_src(2));
v_dst(2) = T(trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2));
}
stl_get_size(stl);
} }
template<typename T> template<typename T>
inline void stl_transform(stl_file *stl, const Eigen::Transform<T, 3, Eigen::Affine, Eigen::DontAlign>& 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); 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) { for (size_t i = 0; i < stl->stats.number_of_facets; ++i) {
stl_facet &f = stl->facet_start[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> template<typename T>
inline void stl_transform(stl_file *stl, const Eigen::Matrix<T, 3, 3, Eigen::DontAlign>& m) 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) { for (size_t i = 0; i < stl->stats.number_of_facets; ++i) {
stl_facet &f = stl->facet_start[i]; stl_facet &f = stl->facet_start[i];
for (size_t j = 0; j < 3; ++j) 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); 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_invalidate_shared_vertices(stl_file *stl);
extern void stl_generate_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 bool stl_write_obj(stl_file *stl, const char *file);
extern void stl_write_off(stl_file *stl, const char *file); extern bool stl_write_off(stl_file *stl, const char *file);
extern void stl_write_dxf(stl_file *stl, const char *file, char *label); extern bool 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_vrml(stl_file *stl, const char *file);
inline void stl_calculate_normal(stl_normal &normal, stl_facet *facet) { 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]); 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_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_reset(stl_file *stl);
extern void stl_count_facets(stl_file *stl, const char *file);
extern void stl_allocate(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_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_facet_stats(stl_file *stl, stl_facet facet, bool &first);
extern void stl_reallocate(stl_file *stl); extern void stl_reallocate(stl_file *stl);
extern void stl_add_facet(stl_file *stl, const stl_facet *new_facet); 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. // Validate the mesh, assert on error.
extern bool stl_validate(stl_file *stl); extern bool stl_validate(stl_file *stl);

View File

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

View File

@ -35,42 +35,8 @@
#error "SEEK_SET not defined" #error "SEEK_SET not defined"
#endif #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; long file_size;
uint32_t header_num_facets; uint32_t header_num_facets;
uint32_t num_facets; uint32_t num_facets;
@ -80,30 +46,27 @@ stl_count_facets(stl_file *stl, const char *file) {
int num_lines = 1; int num_lines = 1;
char *error_msg; char *error_msg;
if (stl->error) return;
/* Open the file in binary mode first */ /* Open the file in binary mode first */
stl->fp = boost::nowide::fopen(file, "rb"); FILE *fp = boost::nowide::fopen(file, "rb");
if(stl->fp == NULL) { if (fp == nullptr) {
error_msg = (char*) error_msg = (char*)
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
sprintf(error_msg, "stl_initialize: Couldn't open %s for reading", sprintf(error_msg, "stl_initialize: Couldn't open %s for reading",
file); file);
perror(error_msg); perror(error_msg);
free(error_msg); free(error_msg);
stl->error = 1; return nullptr;
return;
} }
/* Find size of file */ /* Find size of file */
fseek(stl->fp, 0, SEEK_END); fseek(fp, 0, SEEK_END);
file_size = ftell(stl->fp); file_size = ftell(fp);
/* Check for binary or ASCII file */ /* Check for binary or ASCII file */
fseek(stl->fp, HEADER_SIZE, SEEK_SET); fseek(fp, HEADER_SIZE, SEEK_SET);
if (!fread(chtest, sizeof(chtest), 1, stl->fp)) { if (!fread(chtest, sizeof(chtest), 1, fp)) {
perror("The input is an empty file"); perror("The input is an empty file");
stl->error = 1; fclose(fp);
return; return nullptr;
} }
stl->stats.type = ascii; stl->stats.type = ascii;
for(s = 0; s < sizeof(chtest); s++) { for(s = 0; s < sizeof(chtest); s++) {
@ -112,7 +75,7 @@ stl_count_facets(stl_file *stl, const char *file) {
break; break;
} }
} }
rewind(stl->fp); 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 */
@ -121,18 +84,18 @@ stl_count_facets(stl_file *stl, const char *file) {
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)) {
fprintf(stderr, "The file %s has the wrong size.\n", file); fprintf(stderr, "The file %s has the wrong size.\n", file);
stl->error = 1; fclose(fp);
return; 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, stl->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, stl->fp) != 0; 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);
@ -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) */ /* 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....
stl->fp = boost::nowide::freopen(file, "r", stl->fp); fp = boost::nowide::freopen(file, "r", fp);
// do another null check to be safe // do another null check to be safe
if(stl->fp == NULL) { if(fp == nullptr) {
error_msg = (char*) error_msg = (char*)
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
sprintf(error_msg, "stl_initialize: Couldn't open %s for reading", sprintf(error_msg, "stl_initialize: Couldn't open %s for reading",
file); file);
perror(error_msg); perror(error_msg);
free(error_msg); free(error_msg);
stl->error = 1; fclose(fp);
return; return nullptr;
} }
/* Find the number of facets */ /* Find the number of facets */
char linebuf[100]; char linebuf[100];
while (fgets(linebuf, 100, stl->fp) != NULL) { while (fgets(linebuf, 100, fp) != nullptr) {
/* don't count short lines */ /* don't count short lines */
if (strlen(linebuf) <= 4) continue; if (strlen(linebuf) <= 4) continue;
@ -173,11 +136,11 @@ stl_count_facets(stl_file *stl, const char *file) {
++num_lines; ++num_lines;
} }
rewind(stl->fp); rewind(fp);
/* Get the header */ /* Get the header */
for(i = 0; 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[i] = '\0'; /* Lose the '\n' */
stl->stats.header[80] = '\0'; 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.number_of_facets += num_facets;
stl->stats.original_num_facets = stl->stats.number_of_facets; stl->stats.original_num_facets = stl->stats.number_of_facets;
return fp;
} }
void stl_allocate(stl_file *stl) /* Reads the contents of the file pointed to by fp into the stl structure,
{
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,
starting at facet first_facet. The second argument says if it's our first 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. */ 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; stl_facet facet;
if (stl->error) return;
if(stl->stats.type == binary) { if(stl->stats.type == binary) {
fseek(stl->fp, HEADER_SIZE, SEEK_SET); fseek(fp, HEADER_SIZE, SEEK_SET);
} else { } else {
rewind(stl->fp); rewind(fp);
} }
char normal_buf[3][32]; 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 */ /* Read a single facet from a binary .STL file */
{ {
/* we assume little-endian architecture! */ /* we assume little-endian architecture! */
if (fread(&facet, 1, SIZEOF_STL_FACET, stl->fp) != SIZEOF_STL_FACET) { if (fread(&facet, 1, SIZEOF_STL_FACET, fp) != SIZEOF_STL_FACET)
stl->error = 1; return false;
return;
}
#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);
@ -284,27 +181,26 @@ void stl_read(stl_file *stl, int first_facet, bool first) {
{ {
// 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(stl->fp, "endsolid%*[^\n]\n"); fscanf(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, "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(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); 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); 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); 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); 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); assert(res_vertex3 == 3);
int res_endloop = fscanf(stl->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(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) { 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!"); perror("Something is syntactically very wrong with this ASCII STL!");
stl->error = 1; return false;
return;
} }
// 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.
@ -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.size = stl->stats.max - stl->stats.min;
stl->stats.bounding_diameter = stl->stats.size.norm(); 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) 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 // 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

View File

@ -34,9 +34,6 @@ static float get_volume(stl_file *stl);
void stl_verify_neighbors(stl_file *stl) void stl_verify_neighbors(stl_file *stl)
{ {
if (stl->error)
return;
stl->stats.backwards_edges = 0; stl->stats.backwards_edges = 0;
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { 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) 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 new_min(x, y, z);
stl_vertex shift = new_min - stl->stats.min; stl_vertex shift = new_min - stl->stats.min;
for (int i = 0; i < stl->stats.number_of_facets; ++ i) 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 */ /* 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) void stl_translate_relative(stl_file *stl, float x, float y, float z)
{ {
if (stl->error)
return;
stl_vertex shift(x, y, z); stl_vertex shift(x, y, z);
for (int i = 0; i < stl->stats.number_of_facets; ++ i) for (int i = 0; i < stl->stats.number_of_facets; ++ i)
for (int j = 0; j < 3; ++ j) 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) void stl_scale_versor(stl_file *stl, const stl_vertex &versor)
{ {
if (stl->error)
return;
// Scale extents. // Scale extents.
auto s = versor.array(); auto s = versor.array();
stl->stats.min.array() *= s; 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) static void calculate_normals(stl_file *stl)
{ {
if (stl->error)
return;
stl_normal normal; stl_normal normal;
for(uint32_t i = 0; i < stl->stats.number_of_facets; i++) { for(uint32_t i = 0; i < stl->stats.number_of_facets; i++) {
stl_calculate_normal(normal, &stl->facet_start[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 c = cos(radian_angle);
double s = sin(radian_angle); double s = sin(radian_angle);
if (stl->error) return;
for(i = 0; i < stl->stats.number_of_facets; i++) { for(i = 0; i < stl->stats.number_of_facets; i++) {
for(j = 0; j < 3; j++) { for(j = 0; j < 3; j++) {
stl_rotate(&stl->facet_start[i].vertex[j](1), 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 c = cos(radian_angle);
double s = sin(radian_angle); double s = sin(radian_angle);
if (stl->error) return;
for(i = 0; i < stl->stats.number_of_facets; i++) { for(i = 0; i < stl->stats.number_of_facets; i++) {
for(j = 0; j < 3; j++) { for(j = 0; j < 3; j++) {
stl_rotate(&stl->facet_start[i].vertex[j](2), 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 c = cos(radian_angle);
double s = sin(radian_angle); double s = sin(radian_angle);
if (stl->error) return;
for(i = 0; i < stl->stats.number_of_facets; i++) { for(i = 0; i < stl->stats.number_of_facets; i++) {
for(j = 0; j < 3; j++) { for(j = 0; j < 3; j++) {
stl_rotate(&stl->facet_start[i].vertex[j](0), 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) void stl_get_size(stl_file *stl)
{ {
if (stl->error || stl->stats.number_of_facets == 0) if (stl->stats.number_of_facets == 0)
return; return;
stl->stats.min = stl->facet_start[0].vertex[0]; stl->stats.min = stl->facet_start[0].vertex[0];
stl->stats.max = stl->stats.min; stl->stats.max = stl->stats.min;
@ -220,9 +199,6 @@ void stl_get_size(stl_file *stl)
void stl_mirror_xy(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 i = 0; i < stl->stats.number_of_facets; i++) {
for(int j = 0; j < 3; j++) { for(int j = 0; j < 3; j++) {
stl->facet_start[i].vertex[j](2) *= -1.0; 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) void stl_mirror_yz(stl_file *stl)
{ {
if (stl->error) return;
for (int i = 0; i < stl->stats.number_of_facets; i++) { for (int i = 0; i < stl->stats.number_of_facets; i++) {
for (int j = 0; j < 3; j++) { for (int j = 0; j < 3; j++) {
stl->facet_start[i].vertex[j](0) *= -1.0; 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) void stl_mirror_xz(stl_file *stl)
{ {
if (stl->error)
return;
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
for (int j = 0; j < 3; ++ j) for (int j = 0; j < 3; ++ j)
stl->facet_start[i].vertex[j](1) *= -1.0; 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) static float get_volume(stl_file *stl)
{ {
if (stl->error)
return 0;
// Choose a point, any point as the reference. // Choose a point, any point as the reference.
stl_vertex p0 = stl->facet_start[0].vertex[0]; stl_vertex p0 = stl->facet_start[0].vertex[0];
float volume = 0.f; float volume = 0.f;
@ -291,7 +259,6 @@ static float get_volume(stl_file *stl)
void stl_calculate_volume(stl_file *stl) void stl_calculate_volume(stl_file *stl)
{ {
if (stl->error) return;
stl->stats.volume = get_volume(stl); stl->stats.volume = get_volume(stl);
if(stl->stats.volume < 0.0) { if(stl->stats.volume < 0.0) {
stl_reverse_all_facets(stl); stl_reverse_all_facets(stl);
@ -346,8 +313,6 @@ void stl_repair(stl_file *stl,
int i; int i;
int last_edges_fixed = 0; int last_edges_fixed = 0;
if (stl->error) return;
if(exact_flag || fixall_flag || nearby_flag || remove_unconnected_flag if(exact_flag || fixall_flag || nearby_flag || remove_unconnected_flag
|| fill_holes_flag || normal_directions_flag) { || fill_holes_flag || normal_directions_flag) {
if (verbose_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. // Check validity of the mesh, assert on error.
bool stl_validate(stl_file *stl) bool stl_validate(stl_file *stl)
{ {
assert(! stl->error);
assert(stl->fp == nullptr);
assert(! stl->facet_start.empty()); assert(! stl->facet_start.empty());
assert(stl->facet_start.size() == stl->stats.number_of_facets); assert(stl->facet_start.size() == stl->stats.number_of_facets);
assert(stl->neighbors_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 { else {
// Header has been extracted. Now read the faces. // Header has been extracted. Now read the faces.
stl_file &stl = mesh.stl; stl_file &stl = mesh.stl;
stl.error = 0;
stl.stats.type = inmemory; stl.stats.type = inmemory;
stl.stats.number_of_facets = header.nTriangles; stl.stats.number_of_facets = header.nTriangles;
stl.stats.original_num_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) bool load_stl(const char *path, Model *model, const char *object_name_in)
{ {
TriangleMesh mesh; TriangleMesh mesh;
mesh.ReadSTLFile(path); if (! mesh.ReadSTLFile(path)) {
if (mesh.stl.error) {
// die "Failed to open $file\n" if !-e $path; // die "Failed to open $file\n" if !-e $path;
return false; return false;
} }

View File

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

View File

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

View File

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