Polylines PolylineCollection::_chained_path_from( const Polylines &src, Point start_near, bool no_reverse, bool move_from_src) { std::vector<Chaining> endpoints; endpoints.reserve(src.size()); for (size_t i = 0; i < src.size(); ++ i) { Chaining c; c.first = src[i].first_point(); if (! no_reverse) c.last = src[i].last_point(); c.idx = i; endpoints.push_back(c); } Polylines retval; while (! endpoints.empty()) { // find nearest point int endpoint_index = nearest_point_index<double>(endpoints, start_near, no_reverse); assert(endpoint_index >= 0 && endpoint_index < endpoints.size() * 2); if (move_from_src) { retval.push_back(std::move(src[endpoints[endpoint_index/2].idx])); } else { retval.push_back(src[endpoints[endpoint_index/2].idx]); } if (endpoint_index & 1) retval.back().reverse(); endpoints.erase(endpoints.begin() + endpoint_index/2); start_near = retval.back().last_point(); } return retval; }
Polylines _clipper_pl(ClipperLib::ClipType clipType, const Polygons &subject, const Polygons &clip, bool safety_offset_) { // transform input polygons into polylines Polylines polylines; polylines.reserve(subject.size()); for (Polygons::const_iterator polygon = subject.begin(); polygon != subject.end(); ++polygon) polylines.push_back(*polygon); // implicit call to split_at_first_point() // perform clipping Polylines retval = _clipper_pl(clipType, polylines, clip, safety_offset_); /* If the split_at_first_point() call above happens to split the polygon inside the clipping area we would get two consecutive polylines instead of a single one, so we go through them in order to recombine continuous polylines. */ for (size_t i = 0; i < retval.size(); ++i) { for (size_t j = i+1; j < retval.size(); ++j) { if (retval[i].points.back().coincides_with(retval[j].points.front())) { /* If last point of i coincides with first point of j, append points of j to i and delete j */ retval[i].points.insert(retval[i].points.end(), retval[j].points.begin()+1, retval[j].points.end()); retval.erase(retval.begin() + j); --j; } else if (retval[i].points.front().coincides_with(retval[j].points.back())) { /* If first point of i coincides with last point of j, prepend points of j to i and delete j */ retval[i].points.insert(retval[i].points.begin(), retval[j].points.begin(), retval[j].points.end()-1); retval.erase(retval.begin() + j); --j; } else if (retval[i].points.front().coincides_with(retval[j].points.front())) { /* Since Clipper does not preserve orientation of polylines, also check the case when first point of i coincides with first point of j. */ retval[j].reverse(); retval[i].points.insert(retval[i].points.begin(), retval[j].points.begin(), retval[j].points.end()-1); retval.erase(retval.begin() + j); --j; } else if (retval[i].points.back().coincides_with(retval[j].points.back())) { /* Since Clipper does not preserve orientation of polylines, also check the case when last point of i coincides with last point of j. */ retval[j].reverse(); retval[i].points.insert(retval[i].points.end(), retval[j].points.begin()+1, retval[j].points.end()); retval.erase(retval.begin() + j); --j; } } } return retval; }
inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height) { dst.reserve(dst.size() + polylines.size()); for (Polylines::const_iterator it_polyline = polylines.begin(); it_polyline != polylines.end(); ++ it_polyline) { ExtrusionPath *extrusion_path = new ExtrusionPath(role, mm3_per_mm, width, height); dst.push_back(extrusion_path); extrusion_path->polyline = *it_polyline; } }
inline Polylines to_polylines(Polygons &&polys) { Polylines polylines; polylines.assign(polys.size(), Polyline()); size_t idx = 0; for (Polygons::const_iterator it = polys.begin(); it != polys.end(); ++ it) { Polyline &pl = polylines[idx ++]; pl.points = std::move(it->points); pl.points.push_back(it->points.front()); } assert(idx == polylines.size()); return polylines; }
inline Polylines to_polylines(ExPolygon &&src) { Polylines polylines; polylines.assign(src.holes.size() + 1, Polyline()); size_t idx = 0; Polyline &pl = polylines[idx ++]; pl.points = std::move(src.contour.points); pl.points.push_back(pl.points.front()); for (Polygons::const_iterator ith = src.holes.begin(); ith != src.holes.end(); ++ith) { Polyline &pl = polylines[idx ++]; pl.points = std::move(ith->points); pl.points.push_back(ith->points.front()); } assert(idx == polylines.size()); return polylines; }
inline Polylines to_polylines(const ExPolygons &src) { Polylines polylines; polylines.assign(number_polygons(src), Polyline()); size_t idx = 0; for (ExPolygons::const_iterator it = src.begin(); it != src.end(); ++it) { Polyline &pl = polylines[idx ++]; pl.points = it->contour.points; pl.points.push_back(pl.points.front()); for (Polygons::const_iterator ith = it->holes.begin(); ith != it->holes.end(); ++ith) { Polyline &pl = polylines[idx ++]; pl.points = ith->points; pl.points.push_back(ith->points.front()); } } assert(idx == polylines.size()); return polylines; }