// merge all regions' slices to get islands void Layer::make_slices() { ExPolygons slices; if (m_regions.size() == 1) { // optimization: if we only have one region, take its slices slices = m_regions.front()->slices; } else { Polygons slices_p; for (LayerRegion *layerm : m_regions) polygons_append(slices_p, to_polygons(layerm->slices)); slices = union_ex(slices_p); } this->slices.expolygons.clear(); this->slices.expolygons.reserve(slices.size()); // prepare ordering points Points ordering_points; ordering_points.reserve(slices.size()); for (const ExPolygon &ex : slices) ordering_points.push_back(ex.contour.first_point()); // sort slices std::vector<Points::size_type> order; Slic3r::Geometry::chained_path(ordering_points, order); // populate slices vector for (size_t i : order) this->slices.expolygons.push_back(std::move(slices[i])); }
vector<ExPoly> Clipping::getExPolys(const CL::PolyTree &ctree, double z, double extrusionfactor) { ExPolygons cexpolys; PolyTreeToExPolygons(&ctree, cexpolys); vector<ExPoly> expolys(cexpolys.size()); for (uint j = 0 ; j < cexpolys.size(); j++) { expolys[j].outer = getPoly(cexpolys[0].outer, z, extrusionfactor); for (uint i = 0 ; i < cexpolys[j].holes.size(); i++) expolys[j].holes.push_back(getPoly(cexpolys[j].holes[i], z, extrusionfactor)); } return expolys; }
void LayerRegion::merge_slices() { // without safety offset, artifacts are generated (GH #2494) ExPolygons expp = union_ex((Polygons)this->slices, true); this->slices.surfaces.clear(); this->slices.surfaces.reserve(expp.size()); for (ExPolygons::const_iterator expoly = expp.begin(); expoly != expp.end(); ++expoly) this->slices.surfaces.push_back(Surface(stInternal, *expoly)); }
ExtrusionEntityCollection PerimeterGenerator::_fill_gaps(double min, double max, double w, const Polygons &gaps) const { ExtrusionEntityCollection coll; min *= (1 - INSET_OVERLAP_TOLERANCE); ExPolygons curr = diff_ex( offset2(gaps, -min/2, +min/2), offset2(gaps, -max/2, +max/2), true ); Polylines polylines; for (ExPolygons::const_iterator ex = curr.begin(); ex != curr.end(); ++ex) ex->medial_axis(max, min/2, &polylines); if (polylines.empty()) return coll; #ifdef SLIC3R_DEBUG if (!curr.empty()) printf(" %zu gaps filled with extrusion width = %f\n", curr.size(), w); #endif //my $flow = $layerm->flow(FLOW_ROLE_SOLID_INFILL, 0, $w); Flow flow( w, this->layer_height, this->solid_infill_flow.nozzle_diameter ); double mm3_per_mm = flow.mm3_per_mm(); for (Polylines::const_iterator p = polylines.begin(); p != polylines.end(); ++p) { ExtrusionPath path(erGapFill); path.polyline = *p; path.mm3_per_mm = mm3_per_mm; path.width = flow.width; path.height = this->layer_height; if (p->is_valid() && p->first_point().coincides_with(p->last_point())) { // since medial_axis() now returns only Polyline objects, detect loops here ExtrusionLoop loop; loop.paths.push_back(path); coll.append(loop); } else { coll.append(path); } } return coll; }
void Clipping::AddOuterPolyNodeToExPolygons(const CL::PolyNode * polynode, ExPolygons& expolygons) { size_t cnt = expolygons.size(); expolygons.resize(cnt + 1); expolygons[cnt].outer = polynode->Contour; expolygons[cnt].holes.resize(polynode->ChildCount()); for (int i = 0; i < polynode->ChildCount(); ++i) { expolygons[cnt].holes[i] = polynode->Childs[i]->Contour; //Add outer polygons contained by (nested within) holes ... for (int j = 0; j < polynode->Childs[i]->ChildCount(); ++j) AddOuterPolyNodeToExPolygons(polynode->Childs[i]->Childs[j], expolygons); } }
void MotionPlanner::initialize() { if (this->initialized) return; if (this->islands.empty()) return; // prevent initialization of empty BoundingBox ExPolygons expp; for (ExPolygons::const_iterator island = this->islands.begin(); island != this->islands.end(); ++island) { island->simplify(SCALED_EPSILON, expp); } this->islands = expp; // loop through islands in order to create inner expolygons and collect their contours this->inner.reserve(this->islands.size()); Polygons outer_holes; for (ExPolygons::const_iterator island = this->islands.begin(); island != this->islands.end(); ++island) { this->inner.push_back(ExPolygonCollection()); offset(*island, &this->inner.back().expolygons, -MP_INNER_MARGIN); outer_holes.push_back(island->contour); } // grow island contours in order to prepare holes of the outer environment // This is actually wrong because it might merge contours that are close, // thus confusing the island check in shortest_path() below //offset(outer_holes, &outer_holes, +MP_OUTER_MARGIN); // generate outer contour as bounding box of everything Points points; for (Polygons::const_iterator contour = outer_holes.begin(); contour != outer_holes.end(); ++contour) points.insert(points.end(), contour->points.begin(), contour->points.end()); BoundingBox bb(points); // grow outer contour Polygons contour; offset(bb.polygon(), &contour, +MP_OUTER_MARGIN); assert(contour.size() == 1); // make expolygon for outer environment ExPolygons outer; diff(contour, outer_holes, &outer); assert(outer.size() == 1); this->outer = outer.front(); this->graphs.resize(this->islands.size() + 1, NULL); this->initialized = true; }
Surfaces offset(const Surface &surface, const float delta, double scale, ClipperLib::JoinType joinType, double miterLimit) { // perform offset ExPolygons expp = offset_ex(surface.expolygon, delta, scale, joinType, miterLimit); // clone the input surface for each expolygon we got Surfaces retval; retval.reserve(expp.size()); for (ExPolygons::iterator it = expp.begin(); it != expp.end(); ++it) { Surface s = surface; // clone s.expolygon = *it; retval.push_back(s); } return retval; }
void MotionPlanner::initialize() { if (this->initialized) return; if (this->islands.empty()) return; // prevent initialization of empty BoundingBox // loop through islands in order to create inner expolygons and collect their contours Polygons outer_holes; for (std::vector<MotionPlannerEnv>::iterator island = this->islands.begin(); island != this->islands.end(); ++island) { // generate the internal env boundaries by shrinking the island // we'll use these inner rings for motion planning (endpoints of the Voronoi-based // graph, visibility check) in order to avoid moving too close to the boundaries island->env = offset_ex(island->island, -MP_INNER_MARGIN); // island contours are holes of our external environment outer_holes.push_back(island->island.contour); } // generate outer contour as bounding box of everything BoundingBox bb; for (Polygons::const_iterator contour = outer_holes.begin(); contour != outer_holes.end(); ++contour) bb.merge(contour->bounding_box()); // grow outer contour Polygons contour = offset(bb.polygon(), +MP_OUTER_MARGIN*2); assert(contour.size() == 1); // make expolygon for outer environment ExPolygons outer = diff_ex(contour, outer_holes); assert(outer.size() == 1); this->outer.island = outer.front(); this->outer.env = ExPolygonCollection(diff_ex(contour, offset(outer_holes, +MP_OUTER_MARGIN))); this->graphs.resize(this->islands.size() + 1, NULL); this->initialized = true; }