diff --git a/xs/src/TriangleMesh.cpp b/xs/src/TriangleMesh.cpp index acb2b931b..ba0c1fdb6 100644 --- a/xs/src/TriangleMesh.cpp +++ b/xs/src/TriangleMesh.cpp @@ -411,6 +411,22 @@ TriangleMeshSlicer::slice(const std::vector &z, std::vector* la } } +void +TriangleMeshSlicer::slice(const std::vector &z, std::vector* layers) +{ + std::vector layers_p; + this->slice(z, &layers_p); + + layers->resize(z.size()); + for (std::vector::const_iterator loops = layers_p.begin(); loops != layers_p.end(); ++loops) { + #ifdef SLIC3R_DEBUG + printf("Layer %zu (slice_z = %.2f): ", layer_id, z[layer_id]); + #endif + + this->make_expolygons(*loops, &(*layers)[ loops - layers_p.begin() ]); + } +} + void TriangleMeshSlicer::slice_facet(float slice_z, const stl_facet &facet, const int &facet_idx, const float &min_z, const float &max_z, std::vector* lines) const { @@ -664,11 +680,8 @@ class _area_comp { }; void -TriangleMeshSlicer::slice(const std::vector &z, std::vector* layers) +TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slices) { - std::vector layers_p; - this->slice(z, &layers_p); - /* Input loops are not suitable for evenodd nor nonzero fill types, as we might get two consecutive concentric loops having the same winding order - and we have to @@ -685,55 +698,57 @@ TriangleMeshSlicer::slice(const std::vector &z, std::vector* the previous sorting method, based on $b->contains_point($a->[0]), failed to nest loops correctly in some edge cases when original model had overlapping facets */ - - layers->resize(z.size()); - - for (std::vector::const_iterator loops = layers_p.begin(); loops != layers_p.end(); ++loops) { - size_t layer_id = loops - layers_p.begin(); - - std::vector area; - std::vector abs_area; - std::vector sorted_area; // vector of indices - for (Polygons::const_iterator loop = loops->begin(); loop != loops->end(); ++loop) { - double a = loop->area(); - area.push_back(a); - abs_area.push_back(std::fabs(a)); - sorted_area.push_back(loop - loops->begin()); - } - - std::sort(sorted_area.begin(), sorted_area.end(), _area_comp(&abs_area)); // outer first - - // we don't perform a safety offset now because it might reverse cw loops - Polygons slices; - for (std::vector::const_iterator loop_idx = sorted_area.begin(); loop_idx != sorted_area.end(); ++loop_idx) { - /* we rely on the already computed area to determine the winding order - of the loops, since the Orientation() function provided by Clipper - would do the same, thus repeating the calculation */ - Polygons::const_iterator loop = loops->begin() + *loop_idx; - if (area[*loop_idx] >= 0) { - slices.push_back(*loop); - } else { - diff(slices, *loop, slices); - } - } - - // perform a safety offset to merge very close facets (TODO: find test case for this) - double safety_offset = scale_(0.0499); - ExPolygons ex_slices; - offset2_ex(slices, ex_slices, +safety_offset, -safety_offset); - - #ifdef SLIC3R_DEBUG - size_t holes_count = 0; - for (ExPolygons::const_iterator e = ex_slices.begin(); e != ex_slices.end(); ++e) { - holes_count += e->holes.size(); - } - printf("Layer %zu (slice_z = %.2f): %zu surface(s) having %zu holes detected from %zu polylines\n", - layer_id, z[layer_id], ex_slices.size(), holes_count, loops->size()); - #endif - - ExPolygons* layer = &(*layers)[layer_id]; - layer->insert(layer->end(), ex_slices.begin(), ex_slices.end()); + + std::vector area; + std::vector abs_area; + std::vector sorted_area; // vector of indices + for (Polygons::const_iterator loop = loops.begin(); loop != loops.end(); ++loop) { + double a = loop->area(); + area.push_back(a); + abs_area.push_back(std::fabs(a)); + sorted_area.push_back(loop - loops.begin()); } + + std::sort(sorted_area.begin(), sorted_area.end(), _area_comp(&abs_area)); // outer first + + // we don't perform a safety offset now because it might reverse cw loops + Polygons p_slices; + for (std::vector::const_iterator loop_idx = sorted_area.begin(); loop_idx != sorted_area.end(); ++loop_idx) { + /* we rely on the already computed area to determine the winding order + of the loops, since the Orientation() function provided by Clipper + would do the same, thus repeating the calculation */ + Polygons::const_iterator loop = loops.begin() + *loop_idx; + if (area[*loop_idx] >= 0) { + p_slices.push_back(*loop); + } else { + diff(p_slices, *loop, p_slices); + } + } + + // perform a safety offset to merge very close facets (TODO: find test case for this) + double safety_offset = scale_(0.0499); + ExPolygons ex_slices; + offset2_ex(p_slices, ex_slices, +safety_offset, -safety_offset); + + #ifdef SLIC3R_DEBUG + size_t holes_count = 0; + for (ExPolygons::const_iterator e = ex_slices.begin(); e != ex_slices.end(); ++e) { + holes_count += e->holes.size(); + } + printf("%zu surface(s) having %zu holes detected from %zu polylines\n", + ex_slices.size(), holes_count, loops.size()); + #endif + + // append to the supplied collection + slices->insert(slices->end(), ex_slices.begin(), ex_slices.end()); +} + +void +TriangleMeshSlicer::make_expolygons(std::vector &lines, ExPolygons* slices) +{ + Polygons pp; + this->make_loops(lines, &pp); + this->make_expolygons(pp, slices); } void @@ -817,8 +832,8 @@ TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower) } // compute shape of section - Polygons section; - this->make_loops(lines, §ion); + ExPolygons section; + this->make_expolygons(lines, §ion); /* stl_get_size(&(upper->stl)); diff --git a/xs/src/TriangleMesh.hpp b/xs/src/TriangleMesh.hpp index 4042f994d..b1e9fea04 100644 --- a/xs/src/TriangleMesh.hpp +++ b/xs/src/TriangleMesh.hpp @@ -91,6 +91,8 @@ class TriangleMeshSlicer t_facets_edges facets_edges; stl_vertex* v_scaled_shared; void make_loops(std::vector &lines, Polygons* loops); + void make_expolygons(const Polygons &loops, ExPolygons* slices); + void make_expolygons(std::vector &lines, ExPolygons* slices); }; }