diff --git a/include/utils/SVG.h b/include/utils/SVG.h index 96bcfa0a45..7105468f10 100644 --- a/include/utils/SVG.h +++ b/include/utils/SVG.h @@ -62,6 +62,7 @@ class SVG : NoCopy private: std::string toString(const Color color) const; std::string toString(const ColorObject& color) const; + void handleFlush(const bool flush) const; FILE* out_; // the output file const AABB aabb_; // the boundary box to display @@ -122,7 +123,7 @@ class SVG : NoCopy */ void writeLines(const std::vector& polyline, const ColorObject color = Color::BLACK) const; - void writeLine(const Point2LL& a, const Point2LL& b, const ColorObject color = Color::BLACK, const double stroke_width = 1.0) const; + void writeLine(const Point2LL& a, const Point2LL& b, const ColorObject color = Color::BLACK, const double stroke_width = 1.0, const bool flush = true) const; void writeArrow(const Point2LL& a, const Point2LL& b, const ColorObject color = Color::BLACK, const double stroke_width = 1.0, const double head_size = 5.0) const; @@ -148,10 +149,12 @@ class SVG : NoCopy void writePolygon(Polygon poly, const ColorObject color = Color::BLACK, const double stroke_width = 1.0, const bool flush = true) const; - void writePolylines(const Shape& polys, const ColorObject color = Color::BLACK, const double stroke_width = 1.0) const; + void writePolylines(const Shape& polys, const ColorObject color = Color::BLACK, const double stroke_width = 1.0, const bool flush = true) const; void writePolyline(const Polygon& poly, const ColorObject color = Color::BLACK, const double stroke_width = 1.0) const; + void writePolyline(const Polyline& poly, const ColorObject color = Color::BLACK, const double stroke_width = 1.0, const bool flush = true) const; + /*! * Draw variable-width paths into the image. * @@ -183,7 +186,7 @@ class SVG : NoCopy * \param color The color to draw the line with. * \param width_factor A multiplicative factor on the line width. */ - void writeLine(const ExtrusionLine& line, const ColorObject color = Color::BLACK, const double width_factor = 1.0) const; + void writeLine(const ExtrusionLine& line, const ColorObject color = Color::BLACK, const double width_factor = 1.0, const bool flush = true) const; /*! * Draws a grid across the image and writes down coordinates. diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index 9a7f26a410..5877d6732c 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -2064,14 +2064,10 @@ void getBestAngledLinesToSupportPoints(OpenLinesSet& result_lines, const Shape& // We do this because supporting lines are hanging over air, // and therefore print best as part of a continuous print move, // rather than having a travel move before and after them. -// -// We also double-insert most lines, since that allows the -// elimination of all travel moves, and overlap isn't an issue -// because the lines are hanging. void integrateSupportingLine(OpenLinesSet& infill_lines, const OpenPolyline& line_to_add) { // Returns the line index and the index of the point within an infill_line, null for no match found. - const auto findMatchingSegment = [&](Point2LL p) -> std::optional> + const auto findMatchingSegment = [&](Point2LL p) -> std::optional> { for (size_t i = 0; i < infill_lines.size(); ++i) { @@ -2101,59 +2097,76 @@ void integrateSupportingLine(OpenLinesSet& infill_lines, const OpenPolyline& lin { /* both ends intersect with the same line. * If the inserted line has ends x, y - * and the original line was A--(x)--B---C--(y)--D - * Then the new line will be A--x--y--C---B--x--y--D - * Note that the middle part of the line is reversed. + * and the original line was ...--A--(x)--B--...--C--(y)--D--... + * Then the new lines will be ...--A--x--y--C--...--B--x + * And line y--D--... + * Note that some parts of the line are reversed, + * and the last one is completly split apart. */ OpenPolyline& old_line = infill_lines[front_line_index]; - OpenPolyline new_line; + OpenPolyline new_line_start; + OpenPolyline new_line_end; Point2LL x, y; - size_t x_index, y_index; + std::ptrdiff_t x_index, y_index; if (front_point_index < back_point_index) { x = line_to_add.front(); y = line_to_add.back(); - x_index = front_point_index; - y_index = back_point_index; + x_index = static_cast(front_point_index); + y_index = static_cast(back_point_index); } else { y = line_to_add.front(); x = line_to_add.back(); - y_index = front_point_index; - x_index = back_point_index; + y_index = static_cast(front_point_index); + x_index = static_cast(back_point_index); } - new_line.insert(new_line.end(), old_line.begin(), old_line.begin() + x_index); - new_line.push_back(x); - new_line.push_back(y); - new_line.insert(new_line.end(), old_line.rend() - y_index, old_line.rend() - x_index); - new_line.push_back(x); - new_line.push_back(y); - new_line.insert(new_line.end(), old_line.begin() + y_index, old_line.end()); - old_line.setPoints(std::move(new_line.getPoints())); + + new_line_start.insert(new_line_start.end(), old_line.begin(), old_line.begin() + x_index); + new_line_start.push_back(x); + new_line_start.push_back(y); + new_line_start.insert(new_line_start.end(), old_line.rend() - y_index, old_line.rend() - x_index); + new_line_start.push_back(x); + + new_line_end.push_back(y); + new_line_end.insert(new_line_end.end(), old_line.begin() + y_index, old_line.end()); + + old_line.setPoints(std::move(new_line_start.getPoints())); + infill_lines.push_back(new_line_end); } else { /* Different lines * If the line_to_add has ends [front, back] - * Existing line (intersects front): A B front C D E - * Other existing line (intersects back): M N back O P Q - * Result is Line: A B front back O P Q - * And line: M N back front C D E + * Existing line (intersects front): ...--A--(x)--B--... + * Other existing line (intersects back): ...--C--(y)--D--... + * Result is Line: ...--A--x--y--D--... + * And line: x--B--... + * And line: ...--C--y */ OpenPolyline& old_front = infill_lines[front_line_index]; OpenPolyline& old_back = infill_lines[back_line_index]; - OpenPolyline new_front, new_back; - new_front.insert(new_front.end(), old_front.begin(), old_front.begin() + front_point_index); - new_front.push_back(line_to_add.front()); - new_front.push_back(line_to_add.back()); - new_front.insert(new_front.end(), old_back.begin() + back_point_index, old_back.end()); - new_back.insert(new_back.end(), old_back.begin(), old_back.begin() + back_point_index); - new_back.push_back(line_to_add.back()); - new_back.push_back(line_to_add.front()); - new_back.insert(new_back.end(), old_front.begin() + front_point_index, old_front.end()); + OpenPolyline full_line, new_front, new_back; + const Point2LL x = line_to_add.front(); + const Point2LL y = line_to_add.back(); + const auto x_index = static_cast(front_point_index); + const auto y_index = static_cast(back_point_index); + + new_front.push_back(x); + new_front.insert(new_front.end(), old_front.begin() + x_index, old_front.end()); + + new_back.insert(new_back.end(), old_back.begin(), old_back.begin() + y_index); + new_back.push_back(y); + + full_line.insert(full_line.end(), old_front.begin(), old_front.begin() + x_index); + full_line.push_back(x); + full_line.push_back(y); + full_line.insert(full_line.end(), old_back.begin() + y_index, old_back.end()); + old_front.setPoints(std::move(new_front.getPoints())); old_back.setPoints(std::move(new_back.getPoints())); + infill_lines.push_back(full_line); } } else diff --git a/src/utils/SVG.cpp b/src/utils/SVG.cpp index 69a115d9d4..83f223e9b1 100644 --- a/src/utils/SVG.cpp +++ b/src/utils/SVG.cpp @@ -59,6 +59,14 @@ std::string SVG::toString(const ColorObject& color) const } } +void SVG::handleFlush(const bool flush) const +{ + if (flush) + { + fflush(out_); + } +} + SVG::SVG(std::string filename, AABB aabb, Point2LL canvas_size, ColorObject background) : SVG( @@ -249,7 +257,7 @@ void SVG::writeLines(const std::vector& polyline, const ColorObject co fprintf(out_, "\" />\n"); // Write the end of the tag. } -void SVG::writeLine(const Point2LL& a, const Point2LL& b, const ColorObject color, const double stroke_width) const +void SVG::writeLine(const Point2LL& a, const Point2LL& b, const ColorObject color, const double stroke_width, const bool flush) const { Point3D fa = transformF(a); Point3D fb = transformF(b); @@ -262,6 +270,8 @@ void SVG::writeLine(const Point2LL& a, const Point2LL& b, const ColorObject colo static_cast(fb.y_), toString(color).c_str(), static_cast(stroke_width)); + + handleFlush(flush); } void SVG::writeArrow(const Point2LL& a, const Point2LL& b, const ColorObject color, const double stroke_width, const double head_size) const @@ -342,10 +352,7 @@ void SVG::writePolygons(const Shape& polys, const ColorObject color, const doubl writePolygon(poly, color, stroke_width, false); } - if (flush) - { - fflush(out_); - } + handleFlush(flush); } void SVG::writePolygon(const Polygon poly, const ColorObject color, const double stroke_width, const bool flush) const @@ -381,19 +388,18 @@ void SVG::writePolygon(const Polygon poly, const ColorObject color, const double i++; } - if (flush) - { - fflush(out_); - } + handleFlush(flush); } -void SVG::writePolylines(const Shape& polys, const ColorObject color, const double stroke_width) const +void SVG::writePolylines(const Shape& polys, const ColorObject color, const double stroke_width, const bool flush) const { for (const Polygon& poly : polys) { - writePolyline(poly, color, stroke_width); + writePolyline(poly, color, stroke_width, false); } + + handleFlush(flush); } void SVG::writePolyline(const Polygon& poly, const ColorObject color, const double stroke_width) const @@ -427,6 +433,16 @@ void SVG::writePolyline(const Polygon& poly, const ColorObject color, const doub } } +void SVG::writePolyline(const Polyline& poly, const ColorObject color, const double stroke_width, const bool flush) const +{ + for (auto iterator = poly.beginSegments(); iterator != poly.endSegments(); ++iterator) + { + writeLine((*iterator).start, (*iterator).end, color, stroke_width, false); + } + + handleFlush(flush); +} + void SVG::writePaths(const std::vector& paths, const ColorObject color, const double width_factor) const { for (const VariableWidthLines& lines : paths) @@ -443,7 +459,7 @@ void SVG::writeLines(const VariableWidthLines& lines, const ColorObject color, c } } -void SVG::writeLine(const ExtrusionLine& line, const ColorObject color, const double width_factor) const +void SVG::writeLine(const ExtrusionLine& line, const ColorObject color, const double width_factor, const bool flush) const { constexpr double minimum_line_width = 10; // Always have some width, otherwise some lines become completely invisible. if (line.junctions_.empty()) // Only draw lines that have at least 2 junctions, otherwise they are degenerate. @@ -481,6 +497,11 @@ void SVG::writeLine(const ExtrusionLine& line, const ColorObject color, const do start_vertex = end_vertex; // For the next line segment. } + + if (flush) + { + fflush(out_); + } } void SVG::writeCoordinateGrid(const coord_t grid_size, const Color color, const double stroke_width, const double font_size) const