diff --git a/src/libslic3r/AABBTreeLines.hpp b/src/libslic3r/AABBTreeLines.hpp index 55cf328f57..97ad1bdf44 100644 --- a/src/libslic3r/AABBTreeLines.hpp +++ b/src/libslic3r/AABBTreeLines.hpp @@ -161,10 +161,11 @@ namespace AABBTreeLines { // on centroids of the lines. // Epsilon is applied to the bounding boxes of the AABB Tree to cope with numeric inaccuracies // during tree traversal. - template - inline AABBTreeIndirect::Tree<2, typename LineType::Scalar> build_aabb_tree_over_indexed_lines(const std::vector& lines) + template + inline AABBTreeIndirect::Tree build_aabb_tree_over_indexed_lines( + const std::vector& lines) { - using TreeType = AABBTreeIndirect::Tree<2, typename LineType::Scalar>; + using TreeType = AABBTreeIndirect::Tree; // using CoordType = typename TreeType::CoordType; using VectorType = typename TreeType::VectorType; using BoundingBox = typename TreeType::BoundingBox; @@ -303,7 +304,7 @@ namespace AABBTreeLines { private: std::vector lines; - AABBTreeIndirect::Tree<2, Scalar> tree; + AABBTreeIndirect::Tree tree; public: explicit LinesDistancer(const std::vector& lines) @@ -321,15 +322,15 @@ namespace AABBTreeLines { LinesDistancer() = default; // 1 true, -1 false, 0 cannot determine - int outside(const Vec<2, Scalar>& point) const { return point_outside_closed_contours(lines, tree, point); } + int outside(const Vec& point) const { return point_outside_closed_contours(lines, tree, point); } // negative sign means inside - template - std::tuple> distance_from_lines_extra(const Vec<2, Scalar>& point) const + template + std::tuple> distance_from_lines_extra(const Vec& point) const { size_t nearest_line_index_out = size_t(-1); - Vec<2, Floating> nearest_point_out = Vec<2, Floating>::Zero(); - Vec<2, Floating> p = point.template cast(); + Vec nearest_point_out = Vec::Zero(); + Vec p = point.template cast(); auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, nearest_line_index_out, nearest_point_out); if (distance < 0) { @@ -344,22 +345,20 @@ namespace AABBTreeLines { return { distance, nearest_line_index_out, nearest_point_out }; } - template - Floating distance_from_lines(const Vec<2, typename LineType::Scalar>& point) const + template Floating distance_from_lines(const Vec& point) const { auto [dist, idx, np] = distance_from_lines_extra(point); return dist; } - std::vector all_lines_in_radius(const Vec<2, Scalar> &point, Floating radius) - { - return AABBTreeLines::all_lines_in_radius(this->lines, this->tree, point.template cast(), radius * radius); - } - - template - std::vector, size_t>> intersections_with_line(const LineType& line) const + std::vector all_lines_in_radius(const Vec& point, Floating radius) { - return get_intersections_with_line>(lines, tree, line); + return AABBTreeLines::all_lines_in_radius(this->lines, this->tree, point.template cast(), radius * radius); + } + + template std::vector, size_t>> intersections_with_line(const LineType& line) const + { + return get_intersections_with_line>(lines, tree, line); } const LineType& get_line(size_t line_idx) const { return lines[line_idx]; } diff --git a/src/libslic3r/ContourZ.cpp b/src/libslic3r/ContourZ.cpp index 48a3da13c3..49c28dca07 100644 --- a/src/libslic3r/ContourZ.cpp +++ b/src/libslic3r/ContourZ.cpp @@ -225,8 +225,8 @@ static void handle_extrusion_collection(LayerRegion *region, const sla::IndexedM void Layer::make_contour_z(const sla::IndexedMesh &mesh) { for (LayerRegion *region : this->regions()) { - handle_extrusion_collection(region, mesh, region->fills, {erTopSolidInfill, erIroning, erExternalPerimeter, erMixed}); - handle_extrusion_collection(region, mesh, region->perimeters, {erExternalPerimeter, erMixed}); - } + handle_extrusion_collection(region, mesh, region->fills, {erTopSolidInfill, erIroning, erPerimeter, erExternalPerimeter, erMixed}); + handle_extrusion_collection(region, mesh, region->perimeters, {erPerimeter, erExternalPerimeter, erMixed}); + } } } // namespace Slic3r diff --git a/src/libslic3r/ExPolygon.hpp b/src/libslic3r/ExPolygon.hpp index 87a1146d41..ce7ebe892f 100644 --- a/src/libslic3r/ExPolygon.hpp +++ b/src/libslic3r/ExPolygon.hpp @@ -192,6 +192,25 @@ inline Linesf to_unscaled_linesf(const ExPolygons &src) return lines; } +inline Linesf3 to_unscaled_linesf3(const ExPolygons& src) +{ + Linesf3 lines; + lines.reserve(count_points(src)); + for (ExPolygons::const_iterator it_expoly = src.begin(); it_expoly != src.end(); ++it_expoly) { + for (size_t i = 0; i <= it_expoly->holes.size(); ++i) { + const Points& points = ((i == 0) ? it_expoly->contour : it_expoly->holes[i - 1]).points; + Vec2d unscaled_a = unscaled(points.front()); + Vec2d unscaled_b = unscaled_a; + for (Points::const_iterator it = points.begin() + 1; it != points.end(); ++it) { + unscaled_b = unscaled(*(it)); + lines.push_back(Linef3(unscaled_a, unscaled_b, 0)); + unscaled_a = unscaled_b; + } + lines.push_back(Linef3(unscaled_a, unscaled(points.front()), 0)); + } + } + return lines; +} inline Points to_points(const ExPolygons &src) { diff --git a/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp index 68df506d31..36955a19bd 100644 --- a/src/libslic3r/ExtrusionEntity.cpp +++ b/src/libslic3r/ExtrusionEntity.cpp @@ -286,6 +286,7 @@ void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang, const const ExtrusionPath &path = this->paths[path_idx]; ExtrusionPath p1(path.role(), path.mm3_per_mm, path.width, path.height); ExtrusionPath p2(path.role(), path.mm3_per_mm, path.width, path.height); + p1.z_contoured = p2.z_contoured = path.z_contoured; path.polyline.split_at(p, &p1.polyline, &p2.polyline); if (this->paths.size() == 1) { diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 39ac5b4d83..831d30ac42 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1,5 +1,6 @@ #include "BoundingBox.hpp" #include "Config.hpp" +#include "GCodeWriter.hpp" #include "Polygon.hpp" #include "PrintConfig.hpp" #include "libslic3r.h" @@ -5817,7 +5818,7 @@ std::string GCode::extrude_loop(const ExtrusionLoop& loop_ref, const Point3 ¢er3 = paths.front().polyline.points.front(); pt.rotate(angle, Point(center3.x(), center3.y())); // generate the travel move - gcode += m_writer.extrude_to_xy(this->point_to_gcode(pt), 0,"move inwards before travel",true); + gcode += m_writer.extrude_to_xy(this->point_to_gcode(pt), 0, "move inwards before travel", true); } return gcode; @@ -6150,19 +6151,13 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, // Move to first point of extrusion path // path is 2D. But in slope lift case, lift z is done in travel_to function. // Add m_need_change_layer_lift_z when change_layer in case of no lift if m_last_pos is equal to path.first_point() by chance - Point3 first_point = path.first_point3(); - if (!m_last_pos_defined || m_last_pos != first_point || m_need_change_layer_lift_z || slope_need_z_travel) { + Point first_point = path.first_point(); + if (!m_last_pos_defined || m_last_pos.to_point() != first_point || m_need_change_layer_lift_z || slope_need_z_travel) { const bool _last_pos_undefined = !m_last_pos_defined; - double z = DBL_MAX; - if (sloped != nullptr) { - z = get_sloped_z(sloped->slope_begin.z_ratio); - } else if ((!m_last_pos_defined && first_point.z() != 0) || m_last_pos.z() != first_point.z()) { - z = m_nominal_z + unscale_(first_point.z()); - if (z < 0.1) { - throw RuntimeError("GCode: very low z"); - } - } - gcode += this->travel_to(path.first_point(), path.role(), "move to first " + description + " point", z); + + gcode += this->travel_to(path.first_point(), path.role(), "move to first " + description + " point", + sloped == nullptr ? DBL_MAX : get_sloped_z(sloped->slope_begin.z_ratio)); + m_need_change_layer_lift_z = false; // Orca: ensure Z matches planned layer height if (_last_pos_undefined && !slope_need_z_travel) { @@ -6170,6 +6165,20 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, } } + if (path.z_contoured && !path.polyline.lines().empty()) { + double current_z = m_writer.get_position().z(); + ; + double first_z = unscale_(path.polyline.lines().begin()->a.z()) + m_nominal_z; + if (GCodeFormatter::quantize_xyzf(first_z) != GCodeFormatter::quantize_xyzf(current_z)) { + gcode += m_writer.travel_to_z(first_z, "set Z for contouring", true); + } + } + if (!path.z_contoured) { + double current_z = m_writer.get_position().z(); + if (GCodeFormatter::quantize_xyzf(current_z) != GCodeFormatter::quantize_xyzf(m_nominal_z)) { + gcode += this->writer().travel_to_z(m_nominal_z, "reset Z after contouring", true); + } + } // if needed, write the gcode_label_objects_end then gcode_label_objects_start // should be already done by travel_to, but just in case @@ -6729,6 +6738,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, if (!m_config.enable_arc_fitting || path.polyline.fitting_result.empty() || m_config.spiral_mode || sloped != nullptr || path.z_contoured) { double path_length = 0.; double total_length = sloped == nullptr ? 0. : path.polyline.length() * SCALING_FACTOR; + double saved_z = m_writer.get_position().z(); + for (const Line3& line : path.polyline.lines()) { std::string tempDescription = description; const double line_length = line.length() * SCALING_FACTOR; @@ -6849,14 +6860,14 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, double total_length = 0; if (sloped != nullptr) { // Calculate total extrusion length - Points p; + Points3 p; p.reserve(new_points.size()); std::transform(new_points.begin(), new_points.end(), std::back_inserter(p), [](const ProcessedPoint& pp) { return pp.p; }); - Polyline l(p); + Polyline3 l(p); total_length = l.length() * SCALING_FACTOR; } gcode += m_writer.set_speed(last_set_speed, "", comment); - Vec2d prev = this->point_to_gcode_quantized(new_points[0].p); + Vec3d prev = this->point_to_gcode_quantized(new_points[0].p); bool pre_fan_enabled = false; bool cur_fan_enabled = false; if( m_enable_cooling_markers && enable_overhang_bridge_fan) @@ -6870,7 +6881,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, std::string tempDescription = description; const ProcessedPoint &processed_point = new_points[i]; const ProcessedPoint &pre_processed_point = new_points[i-1]; - Vec2d p = this->point_to_gcode_quantized(processed_point.p); + Vec3d p = this->point_to_gcode_quantized(processed_point.p); if (m_enable_cooling_markers) { if (enable_overhang_bridge_fan) { cur_fan_enabled = check_overhang_fan(processed_point.overlap, path.role()); @@ -6952,9 +6963,26 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, tempDescription += Slic3r::format(" | Old Flow Value: %0.5f Length: %0.5f",oldE, line_length); } } - if (sloped == nullptr) { + if (path.z_contoured) { + Vec2d dest2d = p.head<2>(); + coordf_t z_diff = unscale_(processed_point.p.z()); + + double extrusion_ratio = 1; + if (path.role() != erIroning) { + extrusion_ratio = (path.height + z_diff) / path.height; + } + + double e = dE * extrusion_ratio; + + double z = m_nominal_z + z_diff; + if (z < 0.1) { + throw RuntimeError("GCode: very low z"); + } + gcode += m_writer.extrude_to_xyz(Vec3d(dest2d.x(), dest2d.y(), z), e, + GCodeWriter::full_gcode_comment ? tempDescription : ""); + } else if (sloped == nullptr) { // Normal extrusion - gcode += m_writer.extrude_to_xy(p, dE, GCodeWriter::full_gcode_comment ? tempDescription : ""); + gcode += m_writer.extrude_to_xy(p.head<2>(), dE, GCodeWriter::full_gcode_comment ? tempDescription : ""); } else { // Sloped extrusion const auto [z_ratio, e_ratio] = sloped->interpolate(path_length / total_length); @@ -7811,6 +7839,13 @@ Vec2d GCode::point_to_gcode(const Point &point) const return unscale(point) + m_origin - extruder_offset; } +Vec3d GCode::point_to_gcode(const Point3& point) const +{ + Vec2d extruder_offset = EXTRUDER_CONFIG(extruder_offset); + Vec2d xy = unscale(point.to_point()) + m_origin - extruder_offset; + return Vec3d(xy.x(), xy.y(), unscale_(point.z())); +} + // convert a model-space scaled point into G-code coordinates Point GCode::gcode_to_point(const Vec2d &point) const { @@ -7828,6 +7863,11 @@ Vec2d GCode::point_to_gcode_quantized(const Point& point) const return { GCodeFormatter::quantize_xyzf(p.x()), GCodeFormatter::quantize_xyzf(p.y()) }; } +Vec3d GCode::point_to_gcode_quantized(const Point3& point) const +{ + Vec3d p = this->point_to_gcode(point); + return {GCodeFormatter::quantize_xyzf(p.x()), GCodeFormatter::quantize_xyzf(p.y()), GCodeFormatter::quantize_xyzf(p.z())}; +} // Goes through by_region std::vector and returns reference to a subvector of entities, that are to be printed // during infill/perimeter wiping, or normally (depends on wiping_entities parameter) diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index cdc0698642..2133d97b9b 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -223,8 +223,10 @@ public: void set_origin(const coordf_t x, const coordf_t y) { this->set_origin(Vec2d(x, y)); } Point last_pos() const { return m_last_pos.to_point(); } Vec2d point_to_gcode(const Point &point) const; + Vec3d point_to_gcode(const Point3& point) const; Point gcode_to_point(const Vec2d &point) const; Vec2d point_to_gcode_quantized(const Point& point) const; + Vec3d point_to_gcode_quantized(const Point3& point) const; const FullPrintConfig &config() const { return m_config; } const Layer* layer() const { return m_layer; } GCodeWriter& writer() { return m_writer; } diff --git a/src/libslic3r/GCode/ExtrusionProcessor.hpp b/src/libslic3r/GCode/ExtrusionProcessor.hpp index dad88a7485..b282af8f4e 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.hpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.hpp @@ -27,19 +27,19 @@ namespace Slic3r { -struct ExtendedPoint +template struct ExtendedPoint { - Vec2d position; + Eigen::Matrix position; float distance; float curvature; }; template -std::vector estimate_points_properties(const POINTS &input_points, - const AABBTreeLines::LinesDistancer &unscaled_prev_layer, - float flow_width, - float max_line_length = -1.0f, - float min_distance = -1.0f) +std::vector> estimate_points_properties(const POINTS& input_points, + const AABBTreeLines::LinesDistancer& unscaled_prev_layer, + float flow_width, + float max_line_length = -1.0f, + float min_distance = -1.0f) { bool looped = input_points.front() == input_points.back(); std::function get_prev_index = [](size_t idx, size_t count) { @@ -78,47 +78,36 @@ std::vector estimate_points_properties(const POINTS double min_spacing = flow_width*0.25; using AABBScalar = typename AABBTreeLines::LinesDistancer::Scalar; + using Vec = Eigen::Matrix; if (input_points.empty()) return {}; float boundary_offset = PREV_LAYER_BOUNDARY_OFFSET ? 0.5 * flow_width : 0.0f; - auto maybe_unscale = [](const P &p) -> Vec2d { - if constexpr (P::RowsAtCompileTime == 3) { - // 3D point - extract XY only - if constexpr (SCALED_INPUT) { - return unscaled(p).template head<2>(); - } else { - return p.template head<2>().template cast(); - } - } else { - // 2D point - use as is - return SCALED_INPUT ? unscaled(p) : p.template cast(); - } - }; + auto maybe_unscale = [](const P& p) -> Vec { return SCALED_INPUT ? unscaled(p) : p.template cast(); }; - std::vector points; + std::vector> points; points.reserve(input_points.size() * (ADD_INTERSECTIONS ? 1.5 : 1)); { - ExtendedPoint start_point{maybe_unscale(input_points.front())}; - auto [distance, nearest_line, - x] = unscaled_prev_layer.template distance_from_lines_extra(start_point.position.cast()); + ExtendedPoint start_point{maybe_unscale(input_points.front())}; + auto [distance, nearest_line, x] = unscaled_prev_layer.template distance_from_lines_extra( + start_point.position.template cast()); start_point.distance = distance + boundary_offset; points.push_back(start_point); } for (size_t i = 1; i < input_points.size(); i++) { - ExtendedPoint next_point{maybe_unscale(input_points[i])}; + ExtendedPoint next_point{maybe_unscale(input_points[i])}; auto [distance, nearest_line, - x] = unscaled_prev_layer.template distance_from_lines_extra(next_point.position.cast()); + x] = unscaled_prev_layer.template distance_from_lines_extra(next_point.position.template cast()); next_point.distance = distance + boundary_offset; // Intersection handling if (ADD_INTERSECTIONS && ((points.back().distance > boundary_offset + EPSILON) != (next_point.distance > boundary_offset + EPSILON))) { - const ExtendedPoint &prev_point = points.back(); - auto intersections = unscaled_prev_layer.template intersections_with_line( - L{prev_point.position.cast(), next_point.position.cast()}); + const ExtendedPoint& prev_point = points.back(); + auto intersections = unscaled_prev_layer.template intersections_with_line( + L{prev_point.position.template cast(), next_point.position.template cast()}); for (const auto &intersection : intersections) { - ExtendedPoint p{}; + ExtendedPoint p{}; p.position = intersection.first.template cast(); p.distance = boundary_offset; // ORCA: Filter out points that are introduced at intersections if their distance from the previous or next point is not meaningful @@ -133,12 +122,12 @@ std::vector estimate_points_properties(const POINTS // Segmentation handling if (PREV_LAYER_BOUNDARY_OFFSET && ADD_INTERSECTIONS) { - std::vector new_points; + std::vector> new_points; new_points.reserve(points.size() * 2); new_points.push_back(points.front()); for (int point_idx = 0; point_idx < int(points.size()) - 1; ++point_idx) { - const ExtendedPoint &curr = points[point_idx]; - const ExtendedPoint &next = points[point_idx + 1]; + const ExtendedPoint& curr = points[point_idx]; + const ExtendedPoint& next = points[point_idx + 1]; if ((curr.distance > -boundary_offset && curr.distance < boundary_offset + 2.0f) || (next.distance > -boundary_offset && next.distance < boundary_offset + 2.0f)) { @@ -156,10 +145,10 @@ std::vector estimate_points_properties(const POINTS double t1 = std::max(a0, a1); if (t0 < 1.0) { - Vec2d p0 = curr.position + t0 * (next.position - curr.position); - auto [p0_dist, p0_near_l, - p0_x] = unscaled_prev_layer.template distance_from_lines_extra(p0.cast()); - ExtendedPoint new_p{}; + Vec p0 = curr.position + t0 * (next.position - curr.position); + auto [p0_dist, p0_near_l, p0_x] = unscaled_prev_layer.template distance_from_lines_extra( + p0.template cast()); + ExtendedPoint new_p{}; new_p.position = p0; new_p.distance = float(p0_dist + boundary_offset); // ORCA: only create a new point in the path if the new point overhang distance will be used to generate a speed change @@ -173,10 +162,10 @@ std::vector estimate_points_properties(const POINTS } } if (t1 > 0.0) { - Vec2d p1 = curr.position + t1 * (next.position - curr.position); - auto [p1_dist, p1_near_l, - p1_x] = unscaled_prev_layer.template distance_from_lines_extra(p1.cast()); - ExtendedPoint new_p{}; + Vec p1 = curr.position + t1 * (next.position - curr.position); + auto [p1_dist, p1_near_l, p1_x] = unscaled_prev_layer.template distance_from_lines_extra( + p1.template cast()); + ExtendedPoint new_p{}; new_p.position = p1; new_p.distance = float(p1_dist + boundary_offset); // ORCA: only create a new point in the path if the new point overhang distance will be used to generate a speed change @@ -198,21 +187,21 @@ std::vector estimate_points_properties(const POINTS // Maximum line length handling if (max_line_length > 0) { - std::vector new_points; + std::vector> new_points; new_points.reserve(points.size() * 2); { for (size_t i = 0; i + 1 < points.size(); i++) { - const ExtendedPoint &curr = points[i]; - const ExtendedPoint &next = points[i + 1]; + const ExtendedPoint& curr = points[i]; + const ExtendedPoint& next = points[i + 1]; new_points.push_back(curr); double len = (next.position - curr.position).squaredNorm(); double t = sqrt((max_line_length * max_line_length) / len); size_t new_point_count = 1.0 / t; for (size_t j = 1; j < new_point_count + 1; j++) { - Vec2d pos = curr.position * (1.0 - j * t) + next.position * (j * t); + Vec pos = curr.position * (1.0 - j * t) + next.position * (j * t); auto [p_dist, p_near_l, - p_x] = unscaled_prev_layer.template distance_from_lines_extra(pos.cast()); - ExtendedPoint new_p{}; + p_x] = unscaled_prev_layer.template distance_from_lines_extra(pos.template cast()); + ExtendedPoint new_p{}; new_p.position = pos; new_p.distance = float(p_dist + boundary_offset); @@ -231,8 +220,8 @@ std::vector estimate_points_properties(const POINTS float accumulated_distance = 0; std::vector distances_for_curvature(points.size()); for (size_t point_idx = 0; point_idx < points.size(); ++point_idx) { - const ExtendedPoint &a = points[point_idx]; - const ExtendedPoint &b = points[get_prev_index(point_idx, points.size())]; + const ExtendedPoint& a = points[point_idx]; + const ExtendedPoint& b = points[get_prev_index(point_idx, points.size())]; distances_for_curvature[point_idx] = (b.position - a.position).norm(); accumulated_distance += distances_for_curvature[point_idx]; @@ -241,9 +230,9 @@ std::vector estimate_points_properties(const POINTS if (accumulated_distance > EPSILON) for (float window_size : {3.0f, 9.0f, 16.0f}) { for (int point_idx = 0; point_idx < int(points.size()); ++point_idx) { - ExtendedPoint ¤t = points[point_idx]; + ExtendedPoint& current = points[point_idx]; - Vec2d back_position = current.position; + Vec back_position = current.position; { size_t back_point_index = point_idx; float dist_backwards = 0; @@ -263,7 +252,7 @@ std::vector estimate_points_properties(const POINTS } } - Vec2d front_position = current.position; + Vec front_position = current.position; { size_t front_point_index = point_idx; float dist_forwards = 0; @@ -283,7 +272,9 @@ std::vector estimate_points_properties(const POINTS } } - float new_curvature = angle(current.position - back_position, front_position - current.position) / window_size; + float new_curvature = angle((current.position - back_position).template head<2>(), + (front_position - current.position).template head<2>()) / + window_size; if (abs(current.curvature) < abs(new_curvature)) { current.curvature = new_curvature; } @@ -295,15 +286,15 @@ std::vector estimate_points_properties(const POINTS struct ProcessedPoint { - Point p; + Point3 p; float speed = 1.0f; float overlap = 1.0f; }; class ExtrusionQualityEstimator { - std::unordered_map> prev_layer_boundaries; - std::unordered_map> next_layer_boundaries; + std::unordered_map> prev_layer_boundaries; + std::unordered_map> next_layer_boundaries; std::unordered_map> prev_curled_extrusions; std::unordered_map> next_curled_extrusions; const PrintObject *current_object; @@ -316,7 +307,7 @@ public: if (layer == nullptr) return; const PrintObject *object = obj; prev_layer_boundaries[object] = next_layer_boundaries[object]; - next_layer_boundaries[object] = AABBTreeLines::LinesDistancer{to_unscaled_linesf(layer->lslices)}; + next_layer_boundaries[object] = AABBTreeLines::LinesDistancer{to_unscaled_linesf3(layer->lslices)}; prev_curled_extrusions[object] = next_curled_extrusions[object]; next_curled_extrusions[object] = AABBTreeLines::LinesDistancer{layer->curled_lines}; } @@ -371,56 +362,54 @@ public: smallest_distance_with_lower_speed=-1.f; // Orca: Pass to the point properties estimator the smallest ovehang distance that triggers a slowdown (smallest_distance_with_lower_speed) - std::vector extended_points = estimate_points_properties - (path.polyline.points, - prev_layer_boundaries[current_object], - path.width, - -1, - smallest_distance_with_lower_speed); + std::vector> extended_points = + estimate_points_properties(path.polyline.points, prev_layer_boundaries[current_object], path.width, -1, + smallest_distance_with_lower_speed); const auto width_inv = 1.0f / path.width; std::vector processed_points; processed_points.reserve(extended_points.size()); for (size_t i = 0; i < extended_points.size(); i++) { - const ExtendedPoint &curr = extended_points[i]; - const ExtendedPoint &next = extended_points[i + 1 < extended_points.size() ? i + 1 : i]; - + const ExtendedPoint<3>& curr = extended_points[i]; + const ExtendedPoint<3>& next = extended_points[i + 1 < extended_points.size() ? i + 1 : i]; + float artificial_distance_to_curled_lines = 0.0; if(slowdown_for_curled_edges) { // The following code artifically increases the distance to provide slowdown for extrusions that are over curled lines const double dist_limit = 10.0 * path.width; { - Vec2d middle = 0.5 * (curr.position + next.position); - auto line_indices = prev_curled_extrusions[current_object].all_lines_in_radius(Point::new_scale(middle), scale_(dist_limit)); - if (!line_indices.empty()) { - double len = (next.position - curr.position).norm(); - // For long lines, there is a problem with the additional slowdown. If by accident, there is small curled line near the middle of this long line + Vec3d middle = 0.5 * (curr.position + next.position); + auto line_indices = prev_curled_extrusions[current_object].all_lines_in_radius(Point::new_scale(middle), + scale_(dist_limit)); + if (!line_indices.empty()) { + double len = (next.position - curr.position).norm(); + // For long lines, there is a problem with the additional slowdown. If by accident, there is small curled line near the middle of this long line // The whole segment gets slower unnecesarily. For these long lines, we do additional check whether it is worth slowing down. // NOTE that this is still quite rough approximation, e.g. we are still checking lines only near the middle point // TODO maybe split the lines into smaller segments before running this alg? but can be demanding, and GCode will be huge if (len > 2) { - Vec2d dir = Vec2d(next.position - curr.position) / len; - Vec2d right = Vec2d(-dir.y(), dir.x()); + Vec2d dir = Vec2d(next.position.head<2>() - curr.position.head<2>()) / len; + Vec2d right = Vec2d(-dir.y(), dir.x()); - Polygon box_of_influence = { - scaled(Vec2d(curr.position + right * dist_limit)), - scaled(Vec2d(next.position + right * dist_limit)), - scaled(Vec2d(next.position - right * dist_limit)), - scaled(Vec2d(curr.position - right * dist_limit)), - }; + Polygon box_of_influence = { + scaled(Vec2d(curr.position.head<2>() + right * dist_limit)), + scaled(Vec2d(next.position.head<2>() + right * dist_limit)), + scaled(Vec2d(next.position.head<2>() - right * dist_limit)), + scaled(Vec2d(curr.position.head<2>() - right * dist_limit)), + }; - double projected_lengths_sum = 0; - for (size_t idx : line_indices) { - const CurledLine &line = prev_curled_extrusions[current_object].get_line(idx); - Lines inside = intersection_ln({{line.a, line.b}}, {box_of_influence}); + double projected_lengths_sum = 0; + for (size_t idx : line_indices) { + const CurledLine& line = prev_curled_extrusions[current_object].get_line(idx); + Lines inside = intersection_ln({{line.a, line.b}}, {box_of_influence}); if (inside.empty()) continue; double projected_length = abs(dir.dot(unscaled(Vec2d((inside.back().b - inside.back().a).cast())))); projected_lengths_sum += projected_length; - } - if (projected_lengths_sum < 0.4 * len) { - line_indices.clear(); - } - } + } + if (projected_lengths_sum < 0.4 * len) { + line_indices.clear(); + } + } for (size_t idx : line_indices) { const CurledLine &line = prev_curled_extrusions[current_object].get_line(idx); @@ -430,9 +419,9 @@ public: (line.curled_height / (path.height * 10.0f)); // max_curled_height_factor from SupportSpotGenerator artificial_distance_to_curled_lines = std::max(artificial_distance_to_curled_lines, dist); } - } - } - } + } + } + } auto calculate_speed = [&speed_sections, &original_speed](float distance) { float final_speed; @@ -464,8 +453,8 @@ public: } float overlap = std::min(1 - (curr.distance+artificial_distance_to_curled_lines) * width_inv, 1 - (next.distance+artificial_distance_to_curled_lines) * width_inv); - - processed_points.push_back({ scaled(curr.position), extrusion_speed, overlap }); + + processed_points.push_back({Point3(scaled(curr.position)), extrusion_speed, overlap}); } return processed_points; } diff --git a/src/libslic3r/Line.hpp b/src/libslic3r/Line.hpp index 99935b1fc4..d8240702b2 100644 --- a/src/libslic3r/Line.hpp +++ b/src/libslic3r/Line.hpp @@ -271,6 +271,7 @@ class Linef3 public: Linef3() : a(Vec3d::Zero()), b(Vec3d::Zero()) {} Linef3(const Vec3d& _a, const Vec3d& _b) : a(_a), b(_b) {} + Linef3(const Vec2d& _a, const Vec2d& _b, double z) : a(Vec3d(_a.x(), _a.y(), z)), b(Vec3d(_b.x(), _b.y(), z)) {} Vec3d intersect_plane(double z) const; void scale(double factor) { this->a *= factor; this->b *= factor; } @@ -311,6 +312,8 @@ public: using Scalar = Vec3d::Scalar; }; +using Linesf3 = std::vector; + BoundingBox get_extents(const Lines &lines); } // namespace Slic3r diff --git a/src/libslic3r/Point.hpp b/src/libslic3r/Point.hpp index 83945d73ce..039f361eaa 100644 --- a/src/libslic3r/Point.hpp +++ b/src/libslic3r/Point.hpp @@ -279,7 +279,7 @@ public: Point3(int64_t x, int64_t y, int64_t z = 0) : Vec3crd(coord_t(x), coord_t(y), coord_t(z)) {} Point3(double x, double y, double z = 0.0) : Vec3crd(coord_t(std::round(x)), coord_t(std::round(y)), coord_t(std::round(z))) {} Point3(const Point3 &rhs) { *this = rhs; } - explicit Point3(const Point &rhs, coord_t z = 0) : Vec3crd(rhs.x(), rhs.y(), z) {} + explicit Point3(const Vec2crd& vec2crd, coord_t z = 0) : Vec3crd(vec2crd.x(), vec2crd.y(), z) {} explicit Point3(const Vec3crd &vec3crd) : Vec3crd(vec3crd) {} // This constructor allows you to construct Point from Eigen expressions template diff --git a/src/libslic3r/Support/SupportSpotsGenerator.cpp b/src/libslic3r/Support/SupportSpotsGenerator.cpp index 057a64b0f8..6fb4908e67 100644 --- a/src/libslic3r/Support/SupportSpotsGenerator.cpp +++ b/src/libslic3r/Support/SupportSpotsGenerator.cpp @@ -165,8 +165,8 @@ void estimate_malformations(LayerPtrs &layers, const Params ¶ms) flow_width, params.bridge_distance); for (size_t i = 0; i < annotated_points.size(); ++i) { - const ExtendedPoint &a = i > 0 ? annotated_points[i - 1] : annotated_points[i]; - const ExtendedPoint &b = annotated_points[i]; + const ExtendedPoint<2>& a = i > 0 ? annotated_points[i - 1] : annotated_points[i]; + const ExtendedPoint<2>& b = annotated_points[i]; ExtrusionLine line_out{a.position.cast(), b.position.cast(), float((a.position - b.position).norm()), extrusion};