//----------------------------------------------------------- // legacy code from Clipper documentation void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPolygons& expolygons) { size_t cnt = expolygons.size(); expolygons.resize(cnt + 1); ClipperPath_to_Slic3rMultiPoint(polynode.Contour, expolygons[cnt].contour); expolygons[cnt].holes.resize(polynode.ChildCount()); for (int i = 0; i < polynode.ChildCount(); ++i) { ClipperPath_to_Slic3rMultiPoint(polynode.Childs[i]->Contour, expolygons[cnt].holes[i]); //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); } }
static void traverse_pt(ClipperLib::PolyNodes &nodes, Slic3r::Polygons &retval) { /* use a nearest neighbor search to order these children TODO: supply start_near to chained_path() too? */ // collect ordering points Points ordering_points; ordering_points.reserve(nodes.size()); for (ClipperLib::PolyNodes::const_iterator it = nodes.begin(); it != nodes.end(); ++it) { Point p((*it)->Contour.front().X, (*it)->Contour.front().Y); ordering_points.push_back(p); } // perform the ordering ClipperLib::PolyNodes ordered_nodes; Slic3r::Geometry::chained_path_items(ordering_points, nodes, ordered_nodes); // push results recursively for (ClipperLib::PolyNodes::iterator it = ordered_nodes.begin(); it != ordered_nodes.end(); ++it) { // traverse the next depth traverse_pt((*it)->Childs, retval); Polygon p; ClipperPath_to_Slic3rMultiPoint((*it)->Contour, p); retval.push_back(p); if ((*it)->IsHole()) retval.back().reverse(); // ccw } }
void ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input, T &output) { output.clear(); for (ClipperLib::Paths::const_iterator it = input.begin(); it != input.end(); ++it) { typename T::value_type p; ClipperPath_to_Slic3rMultiPoint(*it, p); output.push_back(p); } }
void ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input, T* output) { PROFILE_FUNC(); output->clear(); output->reserve(input.size()); for (ClipperLib::Paths::const_iterator it = input.begin(); it != input.end(); ++it) { typename T::value_type p; ClipperPath_to_Slic3rMultiPoint(*it, &p); output->push_back(p); } }
SV* polynode2perl(const ClipperLib::PolyNode& node) { HV* hv = newHV(); Slic3r::Polygon p; ClipperPath_to_Slic3rMultiPoint(node.Contour, p); if (node.IsHole()) { (void)hv_stores( hv, "hole", p.to_SV_clone_ref() ); } else { (void)hv_stores( hv, "outer", p.to_SV_clone_ref() ); } (void)hv_stores( hv, "children", polynode_children_2_perl(node) ); return (SV*)newRV_noinc((SV*)hv); }
Polygons top_level_islands(const Slic3r::Polygons &polygons) { ClipperLib::Paths input; Slic3rMultiPoints_to_ClipperPaths(polygons, &input); // init Clipper ClipperLib::Clipper clipper; clipper.Clear(); // perform union clipper.AddPaths(input, ClipperLib::ptSubject, true); ClipperLib::PolyTree polytree; clipper.Execute(ClipperLib::ctUnion, polytree, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd); // Convert only the top level islands to the output. Polygons out; out.reserve(polytree.ChildCount()); for (int i = 0; i < polytree.ChildCount(); ++i) { out.push_back(Polygon()); ClipperPath_to_Slic3rMultiPoint(polytree.Childs[i]->Contour, &out.back()); } return out; }