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:
parent
39ce4c33a4
commit
ef1a273f0c
4 changed files with 41 additions and 54 deletions
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue