mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-05-07 06:39:05 +08:00
Refactored admesh to get rid of the error and fp members of stl_file.
This commit is contained in:
parent
40b27e8332
commit
a1c38794fb
@ -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);
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user