Fix of "Latest commit of Slic3r 1.42.0 cuts away part of the model #2063"

Fixed one bug of many in admesh library, where the face connectivity
was broken when removing a degenerate face. Likely there are some
similar issues left to be solved.
Placed a workaround to always recalculate face connectivity before slicing.
This commit is contained in:
bubnikv 2019-04-04 16:16:57 +02:00
parent 39ce4c33a4
commit ef1a273f0c
4 changed files with 41 additions and 54 deletions

View file

@ -39,8 +39,7 @@ static void stl_record_neighbors(stl_file *stl,
stl_hash_edge *edge_a, stl_hash_edge *edge_b); stl_hash_edge *edge_a, stl_hash_edge *edge_b);
static void stl_initialize_facet_check_exact(stl_file *stl); static void stl_initialize_facet_check_exact(stl_file *stl);
static void stl_initialize_facet_check_nearby(stl_file *stl); static void stl_initialize_facet_check_nearby(stl_file *stl);
static void stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge, static void stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge, const stl_vertex *a, const stl_vertex *b);
stl_vertex *a, stl_vertex *b);
static int stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge, static int stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge,
stl_vertex *a, stl_vertex *b, float tolerance); stl_vertex *a, stl_vertex *b, float tolerance);
static void insert_hash_edge(stl_file *stl, stl_hash_edge edge, static void insert_hash_edge(stl_file *stl, stl_hash_edge edge,
@ -60,41 +59,40 @@ extern int stl_check_normal_vector(stl_file *stl,
int facet_num, int normal_fix_flag); int facet_num, int normal_fix_flag);
static void stl_update_connects_remove_1(stl_file *stl, int facet_num); static void stl_update_connects_remove_1(stl_file *stl, int facet_num);
// This function builds the neighbors list. No modifications are made
void // to any of the facets. The edges are said to match only if all six
stl_check_facets_exact(stl_file *stl) { // floats of the first edge matches all six floats of the second edge.
/* This function builds the neighbors list. No modifications are made void stl_check_facets_exact(stl_file *stl)
* to any of the facets. The edges are said to match only if all six {
* floats of the first edge matches all six floats of the second edge. if (stl->error)
*/ return;
stl_hash_edge edge;
stl_facet facet;
int i;
int j;
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;
stl->stats.connected_facets_3_edge = 0; stl->stats.connected_facets_3_edge = 0;
stl_initialize_facet_check_exact(stl); // If any two of the three vertices are found to be exactally the same, call them degenerate and remove the facet.
// Do it before the next step, as the next step stores references to the face indices in the hash tables and removing a facet
// will break the references.
for (int i = 0; i < stl->stats.number_of_facets;) {
stl_facet &facet = stl->facet_start[i];
if (facet.vertex[0] == facet.vertex[1] || facet.vertex[1] == facet.vertex[2] || facet.vertex[0] == facet.vertex[2]) {
// Remove the degenerate facet.
facet = stl->facet_start[--stl->stats.number_of_facets];
stl->stats.facets_removed += 1;
stl->stats.degenerate_facets += 1;
} else
++ i;
}
for(i = 0; i < stl->stats.number_of_facets; i++) { // Connect neighbor edges.
facet = stl->facet_start[i]; stl_initialize_facet_check_exact(stl);
// If any two of the three vertices are found to be exactally the same, call them degenerate and remove the facet. for (int i = 0; i < stl->stats.number_of_facets; i++) {
if (facet.vertex[0] == facet.vertex[1] || const stl_facet &facet = stl->facet_start[i];
facet.vertex[1] == facet.vertex[2] || for (int j = 0; j < 3; j++) {
facet.vertex[0] == facet.vertex[2]) { stl_hash_edge edge;
stl->stats.degenerate_facets += 1; edge.facet_number = i;
stl_remove_facet(stl, i);
-- i;
continue;
}
for(j = 0; j < 3; j++) {
edge.facet_number = i;
edge.which_edge = j; edge.which_edge = j;
stl_load_edge_exact(stl, &edge, &facet.vertex[j], &facet.vertex[(j + 1) % 3]); stl_load_edge_exact(stl, &edge, &facet.vertex[j], &facet.vertex[(j + 1) % 3]);
insert_hash_edge(stl, edge, stl_record_neighbors); insert_hash_edge(stl, edge, stl_record_neighbors);
@ -109,9 +107,7 @@ stl_check_facets_exact(stl_file *stl) {
#endif #endif
} }
static void static void stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge, const stl_vertex *a, const stl_vertex *b) {
stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge,
stl_vertex *a, stl_vertex *b) {
if (stl->error) return; if (stl->error) return;
@ -333,7 +329,9 @@ static void stl_free_edges(stl_file *stl)
} }
} }
free(stl->heads); free(stl->heads);
stl->heads = nullptr;
free(stl->tail); free(stl->tail);
stl->tail = nullptr;
} }
static void stl_initialize_facet_check_nearby(stl_file *stl) static void stl_initialize_facet_check_nearby(stl_file *stl)

View file

@ -127,7 +127,6 @@ typedef struct {
typedef struct { typedef struct {
FILE *fp; FILE *fp;
stl_facet *facet_start; stl_facet *facet_start;
stl_edge *edge_start;
stl_hash_edge **heads; stl_hash_edge **heads;
stl_hash_edge *tail; stl_hash_edge *tail;
int M; int M;
@ -142,7 +141,6 @@ typedef struct {
extern void stl_open(stl_file *stl, const char *file); extern void stl_open(stl_file *stl, const char *file);
extern void stl_close(stl_file *stl); 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_edges(stl_file *stl, FILE *file);
extern void stl_print_neighbors(stl_file *stl, char *file); extern void 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);

View file

@ -33,24 +33,6 @@
#define SEEK_END 2 #define SEEK_END 2
#endif #endif
void
stl_print_edges(stl_file *stl, FILE *file) {
int i;
int edges_allocated;
if (stl->error) return;
edges_allocated = stl->stats.number_of_facets * 3;
for(i = 0; i < edges_allocated; i++) {
fprintf(file, "%d, %f, %f, %f, %f, %f, %f\n",
stl->edge_start[i].facet_number,
stl->edge_start[i].p1(0), stl->edge_start[i].p1(1),
stl->edge_start[i].p1(2), stl->edge_start[i].p2(0),
stl->edge_start[i].p2(1), stl->edge_start[i].p2(2));
}
}
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; if (stl->error) return;

View file

@ -1790,8 +1790,13 @@ std::vector<ExPolygons> PrintObject::_slice_volumes(const std::vector<float> &z,
if (! volumes.empty()) { if (! volumes.empty()) {
// Compose mesh. // Compose mesh.
//FIXME better to perform slicing over each volume separately and then to use a Boolean operation to merge them. //FIXME better to perform slicing over each volume separately and then to use a Boolean operation to merge them.
TriangleMesh mesh(volumes.front()->mesh); TriangleMesh mesh(volumes.front()->mesh);
mesh.transform(volumes.front()->get_matrix(), true); mesh.transform(volumes.front()->get_matrix(), true);
assert(mesh.repaired);
if (volumes.size() == 1 && mesh.repaired) {
//FIXME The admesh repair function may break the face connectivity, rather refresh it here as the slicing code relies on it.
stl_check_facets_exact(&mesh.stl);
}
for (size_t idx_volume = 1; idx_volume < volumes.size(); ++ idx_volume) { for (size_t idx_volume = 1; idx_volume < volumes.size(); ++ idx_volume) {
const ModelVolume &model_volume = *volumes[idx_volume]; const ModelVolume &model_volume = *volumes[idx_volume];
TriangleMesh vol_mesh(model_volume.mesh); TriangleMesh vol_mesh(model_volume.mesh);
@ -1821,6 +1826,10 @@ std::vector<ExPolygons> PrintObject::_slice_volume(const std::vector<float> &z,
//FIXME better to perform slicing over each volume separately and then to use a Boolean operation to merge them. //FIXME better to perform slicing over each volume separately and then to use a Boolean operation to merge them.
TriangleMesh mesh(volume.mesh); TriangleMesh mesh(volume.mesh);
mesh.transform(volume.get_matrix(), true); mesh.transform(volume.get_matrix(), true);
if (mesh.repaired) {
//FIXME The admesh repair function may break the face connectivity, rather refresh it here as the slicing code relies on it.
stl_check_facets_exact(&mesh.stl);
}
if (mesh.stl.stats.number_of_facets > 0) { if (mesh.stl.stats.number_of_facets > 0) {
mesh.transform(m_trafo, true); mesh.transform(m_trafo, true);
// apply XY shift // apply XY shift