/*! * 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 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 generateZigZagIninfill_noEndPieces(const Polygons& in_outline, Polygons& result, int extrusionWidth, int lineSpacing, double infillOverlap, double rotation) { if (in_outline.size() == 0) return; Polygons outline = in_outline.offset(extrusionWidth * infillOverlap / 100 - extrusionWidth / 2); if (outline.size() == 0) return; PointMatrix matrix(rotation); outline.applyMatrix(matrix); auto addLine = [&](Point from, Point to) { PolygonRef p = result.newPoly(); p.add(matrix.unapply(from)); p.add(matrix.unapply(to)); }; 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 polyNr=0; polyNr < outline.size(); polyNr++) { std::vector<Point> firstBoundarySegment; std::vector<Point> boundarySegment; bool isFirstBoundarySegment = true; bool firstBoundarySegmentEndsInEven; bool isEvenScanSegment = false; Point p0 = outline[polyNr][outline[polyNr].size()-1]; for(unsigned int i=0; i < outline[polyNr].size(); i++) { Point p1 = outline[polyNr][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 if (isFirstBoundarySegment) firstBoundarySegment.push_back(p0); else boundarySegment.push_back(p0); 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); bool last_isEvenScanSegment = isEvenScanSegment; if (scanline_idx % 2 == 0) isEvenScanSegment = true; else isEvenScanSegment = false; if (!isFirstBoundarySegment) { if (last_isEvenScanSegment && !isEvenScanSegment) { // add whole boundarySegment (including the just obtained point) for (unsigned int p = 1; p < boundarySegment.size(); p++) { addLine(boundarySegment[p-1], boundarySegment[p]); } addLine(boundarySegment[boundarySegment.size()-1], Point(x,y)); boundarySegment.clear(); } else if (isEvenScanSegment) // we are either in an end piece or an uneven boundary segment { boundarySegment.clear(); boundarySegment.emplace_back(x,y); } else boundarySegment.clear(); } if (isFirstBoundarySegment) { firstBoundarySegment.emplace_back(x,y); firstBoundarySegmentEndsInEven = isEvenScanSegment; isFirstBoundarySegment = false; boundarySegment.emplace_back(x,y); } } if (!isFirstBoundarySegment && isEvenScanSegment) boundarySegment.push_back(p1); p0 = p1; } if (!isFirstBoundarySegment && isEvenScanSegment && !firstBoundarySegmentEndsInEven) { for (unsigned int i = 1; i < firstBoundarySegment.size() ; i++) addLine(firstBoundarySegment[i-1], firstBoundarySegment[i]); } } addLineInfill(result, matrix, scanline_min_idx, lineSpacing, boundary, cutList, extrusionWidth); }
/*! * adapted from generateLineInfill(.) * * generate lines within the area of [in_outline], at regular intervals of [lineSpacing] * idea: * intersect a regular grid of 'scanlines' with the area inside [in_outline] * sigzag: * include pieces of boundary, connecting the lines, forming an accordion like zigzag instead of separate lines |_|^|_| * * we call the areas between two consecutive scanlines a 'scansegment' * * 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 * * zigzag algorithm: * while walking around (each) polygon (1.) * if polygon intersects with even scanline * start boundary segment (add each following segment to the [result]) * when polygon intersects with a scanline again * stop boundary segment (stop adding segments to the [result]) * if polygon intersects with even scanline again (instead of odd) * dont add the last line segment to the boundary (unless [connect_zigzags]) * * * <-- * ___ * | | | * | | | * | |___| * --> * * ^ = even scanline * * start boundary from even scanline! :D * * * _____ * | | | , * | | | | * |_____| |__/ * * ^ ^ ^ scanlines * ^ disconnected end piece */ void generateZigZagIninfill_endPieces(const Polygons& in_outline, Polygons& result, int extrusionWidth, int lineSpacing, double infillOverlap, double rotation, bool connect_zigzags) { // if (in_outline.size() == 0) return; // Polygons outline = in_outline.offset(extrusionWidth * infillOverlap / 100 - extrusionWidth / 2); Polygons empty; Polygons outline = in_outline.difference(empty); // copy if (outline.size() == 0) return; PointMatrix matrix(rotation); outline.applyMatrix(matrix); auto addLine = [&](Point from, Point to) { PolygonRef p = result.newPoly(); p.add(matrix.unapply(from)); p.add(matrix.unapply(to)); }; 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 polyNr=0; polyNr < outline.size(); polyNr++) { std::vector<Point> firstBoundarySegment; std::vector<Point> unevenBoundarySegment; // stored cause for connected_zigzags a boundary segment which ends in an uneven scanline needs to be included bool isFirstBoundarySegment = true; bool firstBoundarySegmentEndsInEven; bool isEvenScanSegment = false; Point p0 = outline[polyNr][outline[polyNr].size()-1]; Point lastPoint = p0; for(unsigned int i=0; i < outline[polyNr].size(); i++) { Point p1 = outline[polyNr][i]; int64_t xMin = p1.X, xMax = p0.X; if (xMin == xMax) { lastPoint = p1; 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 if (isFirstBoundarySegment) firstBoundarySegment.push_back(p0); 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); bool last_isEvenScanSegment = isEvenScanSegment; if (scanline_idx % 2 == 0) isEvenScanSegment = true; else isEvenScanSegment = false; if (!isFirstBoundarySegment) { if (last_isEvenScanSegment && (connect_zigzags || !isEvenScanSegment)) addLine(lastPoint, Point(x,y)); else if (connect_zigzags && !last_isEvenScanSegment && !isEvenScanSegment) // if we end an uneven boundary in an uneven segment { // add whole unevenBoundarySegment (including the just obtained point) for (unsigned int p = 1; p < unevenBoundarySegment.size(); p++) { addLine(unevenBoundarySegment[p-1], unevenBoundarySegment[p]); } addLine(unevenBoundarySegment[unevenBoundarySegment.size()-1], Point(x,y)); unevenBoundarySegment.clear(); } if (connect_zigzags && last_isEvenScanSegment && !isEvenScanSegment) unevenBoundarySegment.push_back(Point(x,y)); else unevenBoundarySegment.clear(); } lastPoint = Point(x,y); if (isFirstBoundarySegment) { firstBoundarySegment.emplace_back(x,y); firstBoundarySegmentEndsInEven = isEvenScanSegment; isFirstBoundarySegment = false; } } if (!isFirstBoundarySegment) { if (isEvenScanSegment) addLine(lastPoint, p1); else if (connect_zigzags) unevenBoundarySegment.push_back(p1); } lastPoint = p1; p0 = p1; } if (isEvenScanSegment || isFirstBoundarySegment || connect_zigzags) { for (unsigned int i = 1; i < firstBoundarySegment.size() ; i++) { if (i < firstBoundarySegment.size() - 1 || !firstBoundarySegmentEndsInEven || connect_zigzags) // only add last element if connect_zigzags or boundary segment ends in uneven scanline addLine(firstBoundarySegment[i-1], firstBoundarySegment[i]); } } else if (!firstBoundarySegmentEndsInEven) addLine(firstBoundarySegment[firstBoundarySegment.size()-2], firstBoundarySegment[firstBoundarySegment.size()-1]); } if (cutList.size() == 0) return; if (connect_zigzags && cutList.size() == 1 && cutList[0].size() <= 2) return; // don't add connection if boundary already contains whole outline! addLineInfill(result, matrix, scanline_min_idx, lineSpacing, boundary, cutList, extrusionWidth); }
void generateTroctInfill(const Polygons& in_outline, Polygons& result, int extrusionWidth, int lineSpacing, int infillOverlap, double rotation, int posZ) { Polygons outline = in_outline.offset(extrusionWidth * infillOverlap / 100); PointMatrix matrix(rotation); outline.applyMatrix(matrix); AABB boundary(outline); // ignore infill for areas smaller than line spacing if((abs(boundary.min.X - boundary.max.X) + abs(boundary.min.Y - boundary.max.Y)) < lineSpacing){ return; } // fix to normalise against diagonal infill lineSpacing = lineSpacing * 2; uint64_t Zscale = SQRT2MUL(lineSpacing); int offset = abs(posZ % (Zscale) - (Zscale/2)) - (Zscale/4); boundary.min.X = ((boundary.min.X / lineSpacing) - 1) * lineSpacing; boundary.min.Y = ((boundary.min.Y / lineSpacing) - 1) * lineSpacing; unsigned int lineCountX = (boundary.max.X - boundary.min.X + (lineSpacing - 1)) / lineSpacing; unsigned int lineCountY = (boundary.max.Y - boundary.min.Y + (lineSpacing - 1)) / lineSpacing; int rtMod = int(rotation / 90) % 2; // with an odd number of lines, sides need to be swapped around if(rtMod == 1){ rtMod = (lineCountX + int(rotation / 90)) % 2; } // draw non-horizontal walls of octohedrons Polygons po; PolygonRef p = po.newPoly(); for(unsigned int ly=0; ly < lineCountY;){ for(size_t it = 0; it < 2; ly++, it++){ int side = (2*((ly + it + rtMod) % 2) - 1); int y = (ly * lineSpacing) + boundary.min.Y + lineSpacing / 2 - (offset/2 * side); int x = boundary.min.X-(offset/2); if(it == 1){ x = (lineCountX * (lineSpacing)) + boundary.min.X + lineSpacing / 2 - (offset/2); } p.add(Point(x,y)); for(unsigned int lx=0; lx < lineCountX; lx++){ if(it == 1){ side = (2*((lx + ly + it + rtMod + lineCountX) % 2) - 1); y = (ly * lineSpacing) + boundary.min.Y + lineSpacing / 2 + (offset/2 * side); x = ((lineCountX - lx - 1) * lineSpacing) + boundary.min.X + lineSpacing / 2; p.add(Point(x+lineSpacing-abs(offset/2), y)); p.add(Point(x+abs(offset/2), y)); } else { side = (2*((lx + ly + it + rtMod) % 2) - 1); y = (ly * lineSpacing) + boundary.min.Y + lineSpacing / 2 + (offset/2 * side); x = (lx * lineSpacing) + boundary.min.X + lineSpacing / 2; p.add(Point(x+abs(offset/2), y)); p.add(Point(x+lineSpacing-abs(offset/2), y)); } } x = (lineCountX * lineSpacing) + boundary.min.X + lineSpacing / 2 - (offset/2); if(it == 1){ x = boundary.min.X-(offset/2); } y = (ly * lineSpacing) + boundary.min.Y + lineSpacing / 2 - (offset/2 * side); p.add(Point(x,y)); } } // Generate tops / bottoms of octohedrons if(abs((abs(offset) - Zscale/4)) < (extrusionWidth/2)){ uint64_t startLine = (offset < 0) ? 0 : 1; uint64_t coverWidth = OCTSLEN(lineSpacing); vector<Point> points; for(size_t xi = 0; xi < (lineCountX+1); xi++){ for(size_t yi = 0; yi < (lineCountY); yi += 2){ points.push_back(Point(boundary.min.X + OCTDLEN(lineSpacing) + (xi - startLine + rtMod) * lineSpacing, boundary.min.Y + OCTDLEN(lineSpacing) + (yi + (xi%2)) * lineSpacing + extrusionWidth/2)); } } uint64_t order = 0; for(Point pp : points){ PolygonRef p = po.newPoly(); for(size_t yi = 0; yi <= coverWidth; yi += extrusionWidth) { if(order == 0){ p.add(Point(pp.X, pp.Y + yi)); p.add(Point(pp.X + coverWidth + extrusionWidth, pp.Y + yi)); } else { p.add(Point(pp.X + coverWidth + extrusionWidth, pp.Y + yi)); p.add(Point(pp.X, pp.Y + yi)); } order = (order + 1) % 2; } } } // intersect with outline polygon(s) Polygons pi = po.intersection(outline); // Hack to add intersection to result. There doesn't seem // to be a direct way to do this for(unsigned int polyNr=0; polyNr < pi.size(); polyNr++) { PolygonRef p = result.newPoly(); // = result.newPoly() for(unsigned int i=0; i < pi[polyNr].size(); i++) { Point p0 = pi[polyNr][i]; p.add(matrix.unapply(Point(p0.X,p0.Y))); } } }
/* * 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 * * rough explanation of the zigzag algorithm: * while walking around (each) polygon (1.) * if polygon intersects with even scanline * start boundary segment (add each following segment to the [result]) * when polygon intersects with a scanline again * stop boundary segment (stop adding segments to the [result]) * (see infill/ZigzagConnectorProcessor.h for actual implementation details) * * * we call the areas between two consecutive scanlines a 'scansegment'. * Scansegment x is the area between scanline x and scanline x+1 * Edit: the term scansegment is wrong, since I call a boundary segment leaving from an even scanline to the left as belonging to an even scansegment, * while I also call a boundary segment leaving from an even scanline toward the right as belonging to an even scansegment. */ void Infill::generateLinearBasedInfill(const int outline_offset, Polygons& result, const int line_distance, const PointMatrix& rotation_matrix, ZigzagConnectorProcessor& zigzag_connector_processor, const bool connected_zigzags, int64_t extra_shift) { if (line_distance == 0) { return; } if (in_outline.size() == 0) { return; } int shift = extra_shift + this->shift; Polygons outline; if (outline_offset != 0) { outline = in_outline.offset(outline_offset); if (perimeter_gaps) { perimeter_gaps->add(in_outline.difference(outline.offset(infill_line_width / 2 + perimeter_gaps_extra_offset))); } } else { outline = in_outline; } outline = outline.offset(infill_overlap); if (outline.size() == 0) { return; } outline.applyMatrix(rotation_matrix); if (shift < 0) { shift = line_distance - (-shift) % line_distance; } else { shift = shift % line_distance; } AABB boundary(outline); int scanline_min_idx = computeScanSegmentIdx(boundary.min.X - shift, line_distance); int line_count = computeScanSegmentIdx(boundary.max.X - shift, line_distance) + 1 - scanline_min_idx; std::vector<std::vector<int64_t> > cut_list; // mapping from scanline to all intersections with polygon segments for(int scanline_idx = 0; scanline_idx < line_count; scanline_idx++) { cut_list.push_back(std::vector<int64_t>()); } for(unsigned int poly_idx = 0; poly_idx < outline.size(); poly_idx++) { PolygonRef poly = outline[poly_idx]; Point p0 = poly.back(); zigzag_connector_processor.registerVertex(p0); // always adds the first point to ZigzagConnectorProcessorEndPieces::first_zigzag_connector when using a zigzag infill type for(unsigned int point_idx = 0; point_idx < poly.size(); point_idx++) { Point p1 = poly[point_idx]; if (p1.X == p0.X) { zigzag_connector_processor.registerVertex(p1); // TODO: how to make sure it always adds the shortest line? (in order to prevent overlap with the zigzag connectors) // note: this is already a problem for normal infill, but hasn't really cothered anyone so far. p0 = p1; continue; } int scanline_idx0; int scanline_idx1; // this way of handling the indices takes care of the case where a boundary line segment ends exactly on a scanline: // in case the next segment moves back from that scanline either 2 or 0 scanline-boundary intersections are created // otherwise only 1 will be created, counting as an actual intersection int direction = 1; if (p0.X < p1.X) { scanline_idx0 = computeScanSegmentIdx(p0.X - shift, line_distance) + 1; // + 1 cause we don't cross the scanline of the first scan segment scanline_idx1 = computeScanSegmentIdx(p1.X - shift, line_distance); // -1 cause the vertex point is handled in the next segment (or not in the case which looks like >) } else { direction = -1; scanline_idx0 = computeScanSegmentIdx(p0.X - shift, line_distance); // -1 cause the vertex point is handled in the previous segment (or not in the case which looks like >) scanline_idx1 = computeScanSegmentIdx(p1.X - shift, line_distance) + 1; // + 1 cause we don't cross the scanline of the first scan segment } for(int scanline_idx = scanline_idx0; scanline_idx != scanline_idx1 + direction; scanline_idx += direction) { int x = scanline_idx * line_distance + shift; int y = p1.Y + (p0.Y - p1.Y) * (x - p1.X) / (p0.X - p1.X); assert(scanline_idx - scanline_min_idx >= 0 && scanline_idx - scanline_min_idx < int(cut_list.size()) && "reading infill cutlist index out of bounds!"); cut_list[scanline_idx - scanline_min_idx].push_back(y); Point scanline_linesegment_intersection(x, y); zigzag_connector_processor.registerScanlineSegmentIntersection(scanline_linesegment_intersection, scanline_idx % 2 == 0); } zigzag_connector_processor.registerVertex(p1); p0 = p1; } zigzag_connector_processor.registerPolyFinished(); } if (cut_list.size() == 0) { return; } if (connected_zigzags && cut_list.size() == 1 && cut_list[0].size() <= 2) { return; // don't add connection if boundary already contains whole outline! } addLineInfill(result, rotation_matrix, scanline_min_idx, line_distance, boundary, cut_list, shift); }