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);
static void stl_initialize_facet_check_exact(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,
stl_vertex *a, stl_vertex *b);
static void stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge, const stl_vertex *a, const stl_vertex *b);
static int stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge,
stl_vertex *a, stl_vertex *b, float tolerance);
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);
static void stl_update_connects_remove_1(stl_file *stl, int facet_num);
void
stl_check_facets_exact(stl_file *stl) {
/* This function builds the neighbors list. No modifications are made
* 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.
*/
stl_hash_edge edge;
stl_facet facet;
int i;
int j;
if (stl->error) return;
// This function builds the neighbors list. No modifications are made
// 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.
void stl_check_facets_exact(stl_file *stl)
{
if (stl->error)
return;
stl->stats.connected_edges = 0;
stl->stats.connected_facets_1_edge = 0;
stl->stats.connected_facets_2_edge = 0;
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++) {
facet = stl->facet_start[i];
// If any two of the three vertices are found to be exactally the same, call them degenerate and remove the facet.
if (facet.vertex[0] == facet.vertex[1] ||
facet.vertex[1] == facet.vertex[2] ||
facet.vertex[0] == facet.vertex[2]) {
stl->stats.degenerate_facets += 1;
stl_remove_facet(stl, i);
-- i;
continue;
}
for(j = 0; j < 3; j++) {
edge.facet_number = i;
// Connect neighbor edges.
stl_initialize_facet_check_exact(stl);
for (int i = 0; i < stl->stats.number_of_facets; i++) {
const stl_facet &facet = stl->facet_start[i];
for (int j = 0; j < 3; j++) {
stl_hash_edge edge;
edge.facet_number = i;
edge.which_edge = j;
stl_load_edge_exact(stl, &edge, &facet.vertex[j], &facet.vertex[(j + 1) % 3]);
insert_hash_edge(stl, edge, stl_record_neighbors);
@ -109,9 +107,7 @@ stl_check_facets_exact(stl_file *stl) {
#endif
}
static void
stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge,
stl_vertex *a, stl_vertex *b) {
static void stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge, const stl_vertex *a, const stl_vertex *b) {
if (stl->error) return;
@ -333,7 +329,9 @@ static void stl_free_edges(stl_file *stl)
}
}
free(stl->heads);
stl->heads = nullptr;
free(stl->tail);
stl->tail = nullptr;
}
static void stl_initialize_facet_check_nearby(stl_file *stl)

View file

@ -127,7 +127,6 @@ typedef struct {
typedef struct {
FILE *fp;
stl_facet *facet_start;
stl_edge *edge_start;
stl_hash_edge **heads;
stl_hash_edge *tail;
int M;
@ -142,7 +141,6 @@ typedef struct {
extern void 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_print_edges(stl_file *stl, FILE *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_float(FILE *fp, float value_in);

View file

@ -33,24 +33,6 @@
#define SEEK_END 2
#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
stl_stats_out(stl_file *stl, FILE *file, char *input_file) {
if (stl->error) return;

View file

@ -1790,8 +1790,13 @@ std::vector<ExPolygons> PrintObject::_slice_volumes(const std::vector<float> &z,
if (! volumes.empty()) {
// Compose mesh.
//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);
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) {
const ModelVolume &model_volume = *volumes[idx_volume];
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.
TriangleMesh mesh(volume.mesh);
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) {
mesh.transform(m_trafo, true);
// apply XY shift