void Polygon::simplify(double tolerance, Polygons &polygons) const { Polygons pp = this->simplify(tolerance); polygons.reserve(polygons.size() + pp.size()); polygons.insert(polygons.end(), pp.begin(), pp.end()); }
ClosestPolygonPoint findClosest(Point from, Polygons& polygons) { Polygon emptyPoly; ClosestPolygonPoint none(from, -1, emptyPoly); if (polygons.size() == 0) return none; PolygonRef aPolygon = polygons[0]; if (aPolygon.size() == 0) return none; Point aPoint = aPolygon[0]; ClosestPolygonPoint best(aPoint, 0, aPolygon); int64_t closestDist = vSize2(from - best.location); for (unsigned int ply = 0; ply < polygons.size(); ply++) { PolygonRef poly = polygons[ply]; if (poly.size() == 0) continue; ClosestPolygonPoint closestHere = findClosest(from, poly); int64_t dist = vSize2(from - closestHere.location); if (dist < closestDist) { best = closestHere; closestDist = dist; } } return best; }
void Weaver::chainify_polygons(Polygons& parts1, Point start_close_to, Polygons& result, bool include_last) { for (unsigned int prt = 0 ; prt < parts1.size(); prt++) { const PolygonRef upperPart = parts1[prt]; ClosestPolygonPoint closestInPoly = PolygonUtils::findClosest(start_close_to, upperPart); PolygonRef part_top = result.newPoly(); GivenDistPoint next_upper; bool found = true; int idx = 0; for (Point upper_point = upperPart[closestInPoly.point_idx]; found; upper_point = next_upper.location) { found = PolygonUtils::getNextPointWithDistance(upper_point, nozzle_top_diameter, upperPart, idx, closestInPoly.point_idx, next_upper); if (!found) { break; } part_top.add(upper_point); idx = next_upper.pos; } if (part_top.size() > 0) start_close_to = part_top.back(); else result.remove(result.size()-1); } }
void Weaver::connect(Polygons& parts0, int z0, Polygons& parts1, int z1, WeaveConnection& result, bool include_last) { // TODO: convert polygons (with outset + difference) such that after printing the first polygon, we can't be in the way of the printed stuff // something like: // for (m > n) // parts[m] = parts[m].difference(parts[n].offset(nozzle_top_diameter)) // according to the printing order! // // OR! : // // unify different parts if gap is too small Polygons& supported = result.supported; if (parts1.size() == 0) return; Point& start_close_to = (parts0.size() > 0)? parts0.back().back() : parts1.back().back(); chainify_polygons(parts1, start_close_to, supported, include_last); if (parts0.size() == 0) return; connect_polygons(parts0, z0, supported, z1, result); }
void Slice::drawPolygon(Polygons &pgs, int layer){ glColor4f(0.0f, 1.0f, 0.0f, 0.25f); GLUtesselator* tess = gluNewTess(); gluTessCallback(tess, GLU_TESS_BEGIN, (GLvoid (__stdcall *) ())&BeginCallback); gluTessCallback(tess, GLU_TESS_VERTEX, (GLvoid (__stdcall *) ())&VertexCallback); gluTessCallback(tess, GLU_TESS_END, (GLvoid (__stdcall *) ())&EndCallback); gluTessCallback(tess, GLU_TESS_COMBINE, (GLvoid (__stdcall *) ())&CombineCallback); gluTessCallback(tess, GLU_TESS_ERROR, (GLvoid (__stdcall *) ())&ErrorCallback); gluTessNormal(tess, 0.0, 0.0, 1.0); gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); gluTessProperty(tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE); //GL_FALSE gluTessBeginPolygon(tess, NULL); glPushMatrix(); glTranslated(0.0,0.0,this->layerHeight*layer); for (Polygons::size_type i = 0; i < pgs.size(); ++i) { gluTessBeginContour(tess); for (ClipperLib::Polygon::size_type j = 0; j < pgs[i].size(); ++j) { GLdouble *vert = NewVector((GLdouble)pgs[i][j].X/1000, (GLdouble)pgs[i][j].Y/1000); gluTessVertex(tess, vert, vert); } gluTessEndContour(tess); } gluTessEndPolygon(tess); ClearVectors(); glColor4f(0.0f, 0.6f, 1.0f, 0.5f); glLineWidth(1.8f); gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); gluTessProperty(tess, GLU_TESS_BOUNDARY_ONLY, GL_TRUE); for (Polygons::size_type i = 0; i < pgs.size(); ++i) { gluTessBeginPolygon(tess, NULL); gluTessBeginContour(tess); for (ClipperLib::Polygon::size_type j = 0; j < pgs[i].size(); ++j) { GLdouble *vert = NewVector((GLdouble)pgs[i][j].X/1000, (GLdouble)pgs[i][j].Y/1000); gluTessVertex(tess, vert, vert); } glColor4f(0.0f, 0.0f, 0.8f, 0.5f); gluTessEndContour(tess); gluTessEndPolygon(tess); } //final cleanup ... gluDeleteTess(tess); ClearVectors(); glPopMatrix(); }
/*! * generate lines within the area of \p in_outline, at regular intervals of \p lineSpacing * * idea: * intersect a regular grid of 'scanlines' with the area inside \p in_outline * * we call the areas between two consecutive scanlines a 'scansegment'. * Scansegment x is the area between scanline x and scanline x+1 * * algorithm: * 1) for each line segment of each polygon: * store the intersections of that line segment with all scanlines in a mapping (vector of vectors) from scanline to intersections * (zigzag): add boundary segments to result * 2) for each scanline: * sort the associated intersections * and connect them using the even-odd rule * */ void generateLineInfill(const Polygons& in_outline, int outlineOffset, Polygons& result, int extrusionWidth, int lineSpacing, double infillOverlap, double rotation) { if (lineSpacing == 0) return; if (in_outline.size() == 0) return; Polygons outline = ((outlineOffset)? in_outline.offset(outlineOffset) : in_outline).offset(extrusionWidth * infillOverlap / 100); if (outline.size() == 0) return; PointMatrix matrix(rotation); outline.applyMatrix(matrix); AABB boundary(outline); int scanline_min_idx = boundary.min.X / lineSpacing; int lineCount = (boundary.max.X + (lineSpacing - 1)) / lineSpacing - scanline_min_idx; std::vector<std::vector<int64_t> > cutList; // mapping from scanline to all intersections with polygon segments for(int n=0; n<lineCount; n++) cutList.push_back(std::vector<int64_t>()); for(unsigned int poly_idx=0; poly_idx < outline.size(); poly_idx++) { Point p0 = outline[poly_idx][outline[poly_idx].size()-1]; for(unsigned int i=0; i < outline[poly_idx].size(); i++) { Point p1 = outline[poly_idx][i]; int64_t xMin = p1.X, xMax = p0.X; if (xMin == xMax) { p0 = p1; continue; } if (xMin > xMax) { xMin = p0.X; xMax = p1.X; } int scanline_idx0 = (p0.X + ((p0.X > 0)? -1 : -lineSpacing)) / lineSpacing; // -1 cause a linesegment on scanline x counts as belonging to scansegment x-1 ... int scanline_idx1 = (p1.X + ((p1.X > 0)? -1 : -lineSpacing)) / lineSpacing; // -linespacing because a line between scanline -n and -n-1 belongs to scansegment -n-1 (for n=positive natural number) int direction = 1; if (p0.X > p1.X) { direction = -1; scanline_idx1 += 1; // only consider the scanlines in between the scansegments } else scanline_idx0 += 1; // only consider the scanlines in between the scansegments for(int scanline_idx = scanline_idx0; scanline_idx != scanline_idx1+direction; scanline_idx+=direction) { int x = scanline_idx * lineSpacing; int y = p1.Y + (p0.Y - p1.Y) * (x - p1.X) / (p0.X - p1.X); cutList[scanline_idx - scanline_min_idx].push_back(y); } p0 = p1; } } addLineInfill(result, matrix, scanline_min_idx, lineSpacing, boundary, cutList, extrusionWidth); }
void Weaver::fillFloors(Polygons& supporting, Polygons& to_be_supported, int direction, int z, WeaveRoof& horizontals) { std::vector<WeaveRoofPart>& outsets = horizontals.roof_insets; if (to_be_supported.size() == 0) return; // no parts to start the floor from! if (supporting.size() == 0) return; // no parts to start the floor from! Polygons floors = to_be_supported.difference(supporting); const coord_t roof_inset = Application::getInstance().current_slice->scene.current_mesh_group->settings.get<coord_t>("wireframe_roof_inset"); floors = floors.offset(-roof_inset).offset(roof_inset); if (floors.size() == 0) return; std::vector<PolygonsPart> floor_parts = floors.splitIntoParts(); Polygons floor_outlines; Polygons floor_holes; for (PolygonsPart& floor_part : floor_parts) { floor_outlines.add(floor_part[0]); for (unsigned int hole_idx = 1; hole_idx < floor_part.size(); hole_idx++) { floor_holes.add(floor_part[hole_idx]); //floor_holes.back().reverse(); } } Polygons outset1; Polygons last_supported = supporting; for (Polygons outset0 = supporting; outset0.size() > 0; outset0 = outset1) { outset1 = outset0.offset(roof_inset * direction, ClipperLib::jtRound).intersection(floors); outset1 = outset1.remove(floor_holes); // throw away holes which appear in every intersection outset1 = outset1.remove(floor_outlines); // throw away holes which appear in every intersection outsets.emplace_back(); connect(last_supported, z, outset1, z, outsets.back()); outset1 = outset1.remove(floor_outlines);// throw away fully filled regions last_supported = outsets.back().supported; // chainified } horizontals.roof_outlines.add(floors); }
void generateConcentricInfill(Polygons outline, Polygons& result, int inset_value) { while(outline.size() > 0) { for (unsigned int polyNr = 0; polyNr < outline.size(); polyNr++) { PolygonRef r = outline[polyNr]; result.add(r); } outline = outline.offset(-inset_value); } }
int bridgeAngle(Polygons outline, const SliceLayer* prevLayer, Polygons& supportedRegions) { AABB boundaryBox(outline); //To detect if we have a bridge, first calculate the intersection of the current layer with the previous layer. // This gives us the islands that the layer rests on. Polygons islands; for(auto prevLayerPart : prevLayer->parts) { if (!boundaryBox.hit(prevLayerPart.boundaryBox)) continue; islands.add(outline.intersection(prevLayerPart.outline)); } supportedRegions = islands; if (islands.size() > 5 || islands.size() < 1) return -1; //Next find the 2 largest islands that we rest on. double area1 = 0; double area2 = 0; int idx1 = -1; int idx2 = -1; for(unsigned int n=0; n<islands.size(); n++) { //Skip internal holes if (!islands[n].orientation()) continue; double area = fabs(islands[n].area()); if (area > area1) { if (area1 > area2) { area2 = area1; idx2 = idx1; } area1 = area; idx1 = n; }else if (area > area2) { area2 = area; idx2 = n; } } if (idx1 < 0 || idx2 < 0) return -1; Point center1 = islands[idx1].centerOfMass(); Point center2 = islands[idx2].centerOfMass(); return angle(center2 - center1); }
void generateConcentricInfill(Polygons outline, Polygons& result, int offsets[], int offsetsSize) { int step = 0; while(1) { for(unsigned int polygonNr=0; polygonNr<outline.size(); polygonNr++) result.add(outline[polygonNr]); outline = outline.offset(-offsets[step]); if (outline.size() < 1) break; step = (step + 1) % offsetsSize; } }
int bridgeAngle(SliceLayerPart* part, SliceLayer* prevLayer) { //To detect if we have a bridge, first calculate the intersection of the current layer with the previous layer. // This gives us the islands that the layer rests on. Polygons islands; for(unsigned int n=0; n<prevLayer->parts.size(); n++) { if (!part->boundaryBox.hit(prevLayer->parts[n].boundaryBox)) continue; islands.add(part->outline.intersection(prevLayer->parts[n].outline)); } if (islands.size() > 5) return -1; //Next find the 2 largest islands that we rest on. double area1 = 0; double area2 = 0; int idx1 = -1; int idx2 = -1; for(unsigned int n=0; n<islands.size(); n++) { //Skip internal holes if (!ClipperLib::Orientation(islands[n])) continue; double area = fabs(ClipperLib::Area(islands[n])); if (area > area1) { if (area1 > area2) { area2 = area1; idx2 = idx1; } area1 = area; idx1 = n; }else if (area > area2) { area2 = area; idx2 = n; } } if (idx1 < 0 || idx2 < 0) return -1; Point center1 = centerOfMass(islands[idx1]); Point center2 = centerOfMass(islands[idx2]); double angle = atan2(center2.X - center1.X, center2.Y - center1.Y) / M_PI * 180; if (angle < 0) angle += 360; return angle; }
void Weaver::connect_polygons(Polygons& supporting, int z0, Polygons& supported, int z1, WeaveConnection& result) { if (supporting.size() < 1) { DEBUG_PRINTLN("lower layer has zero parts!"); return; } result.z0 = z0; result.z1 = z1; std::vector<WeaveConnectionPart>& parts = result.connections; for (unsigned int prt = 0 ; prt < supported.size(); prt++) { const PolygonRef upperPart = supported[prt]; parts.emplace_back(prt); WeaveConnectionPart& part = parts.back(); PolyLine3& connection = part.connection; Point3 last_upper; bool firstIter = true; for (const Point& upper_point : upperPart) { ClosestPolygonPoint lowerPolyPoint = findClosest(upper_point, supporting); Point& lower = lowerPolyPoint.location; Point3 lower3 = Point3(lower.X, lower.Y, z0); Point3 upper3 = Point3(upper_point.X, upper_point.Y, z1); if (firstIter) connection.from = lower3; else connection.segments.emplace_back<>(lower3, WeaveSegmentType::DOWN); connection.segments.emplace_back<>(upper3, WeaveSegmentType::UP); last_upper = upper3; firstIter = false; } } }
inline Lines to_lines(const Polygons &polys) { size_t n_lines = 0; for (size_t i = 0; i < polys.size(); ++ i) n_lines += polys[i].points.size(); Lines lines; lines.reserve(n_lines); for (size_t i = 0; i < polys.size(); ++ i) { const Polygon &poly = polys[i]; for (Points::const_iterator it = poly.points.begin(); it != poly.points.end()-1; ++it) lines.push_back(Line(*it, *(it + 1))); lines.push_back(Line(poly.points.back(), poly.points.front())); } return lines; }
void generateConcentricInfillDense(Polygons outline, Polygons& result, Polygons* in_between, int extrusionWidth, bool avoidOverlappingPerimeters) { while(outline.size() > 0) { for (unsigned int polyNr = 0; polyNr < outline.size(); polyNr++) { PolygonRef r = outline[polyNr]; result.add(r); } Polygons next_outline; PolygonUtils::offsetExtrusionWidth(outline, true, extrusionWidth, next_outline, in_between, avoidOverlappingPerimeters); outline = next_outline; } }
void GCodePlanner::addLinesByOptimizer(Polygons& polygons, GCodePathConfig* config, int wipe_dist) { LineOrderOptimizer orderOptimizer(lastPosition); for(unsigned int i=0;i<polygons.size();i++) orderOptimizer.addPolygon(polygons[i]); orderOptimizer.optimize(); for(unsigned int i=0;i<orderOptimizer.polyOrder.size();i++) { int nr = orderOptimizer.polyOrder[i]; // addPolygon(polygons[nr], orderOptimizer.polyStart[nr], config); PolygonRef polygon = polygons[nr]; int start = orderOptimizer.polyStart[nr]; int end = 1 - start; Point& p0 = polygon[start]; addTravel(p0); Point& p1 = polygon[end]; addExtrusionMove(p1, config); if (wipe_dist != 0) { int line_width = config->getLineWidth(); if (vSize2(p1-p0) > line_width * line_width * 4) { // otherwise line will get optimized by combining multiple into a single extrusion move addExtrusionMove(p1 + normal(p1-p0, wipe_dist), config, 0.0); } } } }
inline void polygons_append(Polygons &dst, const ExPolygons &src) { dst.reserve(dst.size() + number_polygons(src)); for (ExPolygons::const_iterator it = src.begin(); it != src.end(); ++ it) { dst.push_back(it->contour); dst.insert(dst.end(), it->holes.begin(), it->holes.end()); } }
void Polygons::splitIntoPartsView_processPolyTreeNode(PartsView& partsView, Polygons& reordered, ClipperLib::PolyNode* node) { for(int n=0; n<node->ChildCount(); n++) { ClipperLib::PolyNode* child = node->Childs[n]; partsView.emplace_back(); unsigned int pos = partsView.size() - 1; partsView[pos].push_back(reordered.size()); reordered.add(child->Contour); for(int i = 0; i < child->ChildCount(); i++) { partsView[pos].push_back(reordered.size()); reordered.add(child->Childs[i]->Contour); splitIntoPartsView_processPolyTreeNode(partsView, reordered, child->Childs[i]); } } }
// Append a vector of Surfaces at the end of another vector of polygons. inline void polygons_append(Polygons &dst, const SurfacesPtr &src) { dst.reserve(dst.size() + number_polygons(src)); for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++ it) { dst.push_back((*it)->expolygon.contour); dst.insert(dst.end(), (*it)->expolygon.holes.begin(), (*it)->expolygon.holes.end()); } }
void ListPolyIt::convertListPolygonsToPolygons(ListPolygons& list_polygons, Polygons& polygons) { for (unsigned int poly_idx = 0; poly_idx < polygons.size(); poly_idx++) { polygons[poly_idx].clear(); convertListPolygonToPolygon(list_polygons[poly_idx], polygons[poly_idx]); } }
inline void polygons_append(Polygons &dst, ExPolygons &&src) { dst.reserve(dst.size() + number_polygons(src)); for (ExPolygons::const_iterator it = src.begin(); it != src.end(); ++ it) { dst.push_back(std::move(it->contour)); std::move(std::begin(it->holes), std::end(it->holes), std::back_inserter(dst)); } }
inline void polygons_append(Polygons &dst, SurfacesPtr &&src) { dst.reserve(dst.size() + number_polygons(src)); for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++ it) { dst.push_back(std::move((*it)->expolygon.contour)); std::move(std::begin((*it)->expolygon.holes), std::end((*it)->expolygon.holes), std::back_inserter(dst)); (*it)->expolygon.holes.clear(); } }
void CommandSocket::sendPolygons(PrintFeatureType type, int layer_nr, Polygons& polygons, int line_width) { #ifdef ARCUS if (polygons.size() == 0) return; std::shared_ptr<cura::proto::Layer> proto_layer = private_data->getLayerById(layer_nr); for (unsigned int i = 0; i < polygons.size(); ++i) { cura::proto::Polygon* p = proto_layer->add_polygons(); p->set_type(static_cast<cura::proto::Polygon_Type>(type)); std::string polydata; polydata.append(reinterpret_cast<const char*>(polygons[i].data()), polygons[i].size() * sizeof(Point)); p->set_points(polydata); p->set_line_width(line_width); } #endif }
void Weaver::chainify_polygons(Polygons& parts1, Point start_close_to, Polygons& result) { const Settings& mesh_group_settings = Application::getInstance().current_slice->scene.current_mesh_group->settings; const coord_t connection_height = mesh_group_settings.get<coord_t>("wireframe_height"); const coord_t nozzle_outer_diameter = mesh_group_settings.get<coord_t>("machine_nozzle_tip_outer_diameter"); // ___ ___ const AngleRadians nozzle_expansion_angle = mesh_group_settings.get<AngleRadians>("machine_nozzle_expansion_angle"); // \_U_/ const coord_t nozzle_clearance = mesh_group_settings.get<coord_t>("wireframe_nozzle_clearance"); // at least line width const coord_t nozzle_top_diameter = tan(nozzle_expansion_angle) * connection_height + nozzle_outer_diameter + nozzle_clearance; for (unsigned int prt = 0 ; prt < parts1.size(); prt++) { ConstPolygonRef upperPart = parts1[prt]; ClosestPolygonPoint closestInPoly = PolygonUtils::findClosest(start_close_to, upperPart); PolygonRef part_top = result.newPoly(); GivenDistPoint next_upper; bool found = true; int idx = 0; for (Point upper_point = upperPart[closestInPoly.point_idx]; found; upper_point = next_upper.location) { found = PolygonUtils::getNextPointWithDistance(upper_point, nozzle_top_diameter, upperPart, idx, closestInPoly.point_idx, next_upper); if (!found) { break; } part_top.add(upper_point); idx = next_upper.pos; } if (part_top.size() > 0) start_close_to = part_top.back(); else result.remove(result.size()-1); } }
void CommandSocket::sendPolygons(PolygonType type, int layer_nr, Polygons& polygons, int line_width) { if(!d->current_sliced_object) return; if (polygons.size() == 0) return; cura::proto::Layer* layer = d->getLayerById(layer_nr); for(unsigned int i = 0; i < polygons.size(); ++i) { cura::proto::Polygon* p = layer->add_polygons(); p->set_type(static_cast<cura::proto::Polygon_Type>(type)); std::string polydata; polydata.append(reinterpret_cast<const char*>(polygons[i].data()), polygons[i].size() * sizeof(Point)); p->set_points(polydata); p->set_line_width(line_width); } }
void optimizePolygons(Polygons& polys) { for(unsigned int n=0;n<polys.size();n++) { optimizePolygon(polys[n]); if (polys[n].size() < 3) { polys.remove(n); n--; } } }
void AABB::calculate(const Polygons& polys) { min = Point(POINT_MAX, POINT_MAX); max = Point(POINT_MIN, POINT_MIN); for(unsigned int i=0; i<polys.size(); i++) { for(unsigned int j=0; j<polys[i].size(); j++) { include(polys[i][j]); } } }
void generateLineInfill(const Polygons& in_outline, Polygons& result, int extrusionWidth, int lineSpacing, int infillOverlap, double rotation) { Polygons outline = in_outline.offset(extrusionWidth * infillOverlap / 100); PointMatrix matrix(rotation); outline.applyMatrix(matrix); AABB boundary(outline); boundary.min.X = ((boundary.min.X / lineSpacing) - 1) * lineSpacing; int lineCount = (boundary.max.X - boundary.min.X + (lineSpacing - 1)) / lineSpacing; vector<vector<int64_t> > cutList; for(int n=0; n<lineCount; n++) cutList.push_back(vector<int64_t>()); for(unsigned int polyNr=0; polyNr < outline.size(); polyNr++) { Point p1 = outline[polyNr][outline[polyNr].size()-1]; for(unsigned int i=0; i < outline[polyNr].size(); i++) { Point p0 = outline[polyNr][i]; int idx0 = (p0.X - boundary.min.X) / lineSpacing; int idx1 = (p1.X - boundary.min.X) / lineSpacing; int64_t xMin = p0.X, xMax = p1.X; if (p0.X > p1.X) { xMin = p1.X; xMax = p0.X; } if (idx0 > idx1) { int tmp = idx0; idx0 = idx1; idx1 = tmp; } for(int idx = idx0; idx<=idx1; idx++) { int x = (idx * lineSpacing) + boundary.min.X + lineSpacing / 2; if (x < xMin) continue; if (x >= xMax) continue; int y = p0.Y + (p1.Y - p0.Y) * (x - p0.X) / (p1.X - p0.X); cutList[idx].push_back(y); } p1 = p0; } } int idx = 0; for(int64_t x = boundary.min.X + lineSpacing / 2; x < boundary.max.X; x += lineSpacing) { std::sort(cutList[idx].begin(), cutList[idx].end()); for(unsigned int i = 0; i + 1 < cutList[idx].size(); i+=2) { if (cutList[idx][i+1] - cutList[idx][i] < extrusionWidth / 5) continue; PolygonRef p = result.newPoly(); p.add(matrix.unapply(Point(x, cutList[idx][i]))); p.add(matrix.unapply(Point(x, cutList[idx][i+1]))); } idx += 1; } }
void GCodePlanner::addPolygonsByOptimizer(Polygons& polygons, GCodePathConfig* config) { PathOrderOptimizer orderOptimizer(lastPosition); for(unsigned int i=0;i<polygons.size();i++) orderOptimizer.addPolygon(polygons[i]); orderOptimizer.optimize(); for(unsigned int i=0;i<orderOptimizer.polyOrder.size();i++) { int nr = orderOptimizer.polyOrder[i]; addPolygon(polygons[nr], orderOptimizer.polyStart[nr], config); } }
void GCodePlanner::addPolygonsByOptimizer(Polygons& polygons, GCodePathConfig* config, WallOverlapComputation* wall_overlap_computation, EZSeamType z_seam_type) { PathOrderOptimizer orderOptimizer(lastPosition, z_seam_type); for(unsigned int i=0;i<polygons.size();i++) orderOptimizer.addPolygon(polygons[i]); orderOptimizer.optimize(); for(unsigned int i=0;i<orderOptimizer.polyOrder.size();i++) { int nr = orderOptimizer.polyOrder[i]; addPolygon(polygons[nr], orderOptimizer.polyStart[nr], config, wall_overlap_computation); } }
inline Polylines to_polylines(const 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 = it->points; pl.points.push_back(it->points.front()); } assert(idx == polylines.size()); return polylines; }