From 38bb7d2950bfc58df10909ccea2fc8f752c6eed5 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Thu, 22 Apr 2021 11:41:26 +0200 Subject: [PATCH] 1) New methods PrintObject::num_regions() and ::has_region() to make the code more readable and to highlight where PrintObject::region_volumes are actually set and consumed. 2) Replaced Slic3r::clamp() with std::clamp(). They differ in the order of their parameters, thus hopefully no new bugs were introduced. 3) Some refactoring of MultiMaterialSegmentation for efficiency. --- src/libslic3r/ClipperUtils.cpp | 2 +- src/libslic3r/ElephantFootCompensation.cpp | 2 +- src/libslic3r/ExtrusionSimulator.cpp | 28 ++--- src/libslic3r/Fill/Fill3DHoneycomb.cpp | 4 +- src/libslic3r/Fill/FillGyroid.cpp | 2 +- src/libslic3r/GCode.cpp | 2 +- .../GCode/AvoidCrossingPerimeters.cpp | 2 +- src/libslic3r/GCode/CoolingBuffer.cpp | 4 +- src/libslic3r/GCode/ToolOrdering.cpp | 6 +- src/libslic3r/MultiMaterialSegmentation.cpp | 117 ++++++++---------- src/libslic3r/Print.cpp | 8 +- src/libslic3r/Print.hpp | 3 + src/libslic3r/PrintObject.cpp | 66 +++++----- src/libslic3r/Slicing.cpp | 30 ++--- src/libslic3r/SupportMaterial.cpp | 4 +- src/libslic3r/VoronoiOffset.cpp | 4 +- src/libslic3r/libslic3r.h | 12 +- src/slic3r/GUI/GLCanvas3D.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 2 +- 19 files changed, 139 insertions(+), 161 deletions(-) diff --git a/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp index cd243dfb1..459560ce1 100644 --- a/src/libslic3r/ClipperUtils.cpp +++ b/src/libslic3r/ClipperUtils.cpp @@ -1039,7 +1039,7 @@ ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::v Vec2d nnext = perp(ptnext - pt).normalized(); double delta = deltas[i]; - double sin_a = clamp(-1., 1., cross2(nprev, nnext)); + double sin_a = std::clamp(cross2(nprev, nnext), -1., 1.); double convex = sin_a * delta; if (convex <= - sin_min_parallel) { // Concave corner. diff --git a/src/libslic3r/ElephantFootCompensation.cpp b/src/libslic3r/ElephantFootCompensation.cpp index 0895e16d6..0adff1ba4 100644 --- a/src/libslic3r/ElephantFootCompensation.cpp +++ b/src/libslic3r/ElephantFootCompensation.cpp @@ -270,7 +270,7 @@ std::vector contour_distance2(const EdgeGrid::Grid &grid, const size_t id const Vec2d v = (segment.second - segment.first).cast(); const Vec2d va = (this->point - segment.first).cast(); const double l2 = v.squaredNorm(); // avoid a sqrt - const double t = (l2 == 0.0) ? 0. : clamp(0., 1., va.dot(v) / l2); + const double t = (l2 == 0.0) ? 0. : std::clamp(va.dot(v) / l2, 0., 1.); // Closest point from this->point to the segment. const Vec2d foot = segment.first.cast() + t * v; const Vec2d bisector = foot - this->point.cast(); diff --git a/src/libslic3r/ExtrusionSimulator.cpp b/src/libslic3r/ExtrusionSimulator.cpp index 8c2ab037f..6b1f76abe 100644 --- a/src/libslic3r/ExtrusionSimulator.cpp +++ b/src/libslic3r/ExtrusionSimulator.cpp @@ -550,10 +550,10 @@ void gcode_paint_layer( boost::geometry::expand(bboxLine, rect[2]); boost::geometry::expand(bboxLine, rect[3]); B2i bboxLinei( - V2i(clamp(0, nc-1, int(floor(bboxLine.min_corner().x()))), - clamp(0, nr-1, int(floor(bboxLine.min_corner().y())))), - V2i(clamp(0, nc-1, int(ceil (bboxLine.max_corner().x()))), - clamp(0, nr-1, int(ceil (bboxLine.max_corner().y()))))); + V2i(std::clamp(int(floor(bboxLine.min_corner().x())), 0, nc-1), + std::clamp(int(floor(bboxLine.min_corner().y())), 0, nr-1)), + V2i(std::clamp(int(ceil(bboxLine.max_corner().x())), 0, nc-1), + std::clamp(int(ceil(bboxLine.max_corner().y())), 0, nr-1))); // printf("bboxLinei %d,%d %d,%d\n", bboxLinei.min_corner().x(), bboxLinei.min_corner().y(), bboxLinei.max_corner().x(), bboxLinei.max_corner().y()); #ifdef _DEBUG float area = polyArea(rect, 4); @@ -597,10 +597,10 @@ void gcode_paint_bitmap( boost::geometry::expand(bboxLine, rect[2]); boost::geometry::expand(bboxLine, rect[3]); B2i bboxLinei( - V2i(clamp(0, nc-1, int(floor(bboxLine.min_corner().x()))), - clamp(0, nr-1, int(floor(bboxLine.min_corner().y())))), - V2i(clamp(0, nc-1, int(ceil (bboxLine.max_corner().x()))), - clamp(0, nr-1, int(ceil (bboxLine.max_corner().y()))))); + V2i(std::clamp(int(floor(bboxLine.min_corner().x())), 0, nc-1), + std::clamp(int(floor(bboxLine.min_corner().y())), 0, nr-1)), + V2i(std::clamp(int(ceil(bboxLine.max_corner().x())), 0, nc-1), + std::clamp(int(ceil(bboxLine.max_corner().y())), 0, nr-1))); // printf("bboxLinei %d,%d %d,%d\n", bboxLinei.min_corner().x(), bboxLinei.min_corner().y(), bboxLinei.max_corner().x(), bboxLinei.max_corner().y()); for (int j = bboxLinei.min_corner().y(); j + 1 < bboxLinei.max_corner().y(); ++ j) { for (int i = bboxLinei.min_corner().x(); i + 1 < bboxLinei.max_corner().x(); ++i) { @@ -664,10 +664,10 @@ void gcode_spread_points( const float height_target = it->height; B2f bbox(center - V2f(radius, radius), center + V2f(radius, radius)); B2i bboxi( - V2i(clamp(0, nc-1, int(floor(bbox.min_corner().x()))), - clamp(0, nr-1, int(floor(bbox.min_corner().y())))), - V2i(clamp(0, nc-1, int(ceil (bbox.max_corner().x()))), - clamp(0, nr-1, int(ceil (bbox.max_corner().y()))))); + V2i(std::clamp(int(floor(bbox.min_corner().x())), 0, nc-1), + std::clamp(int(floor(bbox.min_corner().y())), 0, nr-1)), + V2i(std::clamp(int(ceil(bbox.max_corner().x())), 0, nc-1), + std::clamp(int(ceil(bbox.max_corner().y())), 0, nr-1))); /* // Fill in the spans, at which the circle intersects the rows. int row_first = bboxi.min_corner().y(); @@ -758,7 +758,7 @@ void gcode_spread_points( area_circle_total += area; if (cell.area < area) cell.area = area; - cell.fraction_covered = clamp(0.f, 1.f, (cell.area > 0) ? (area / cell.area) : 0); + cell.fraction_covered = std::clamp((cell.area > 0) ? (area / cell.area) : 0, 0.f, 1.f); if (cell.fraction_covered == 0) { -- n_cells; continue; @@ -1018,7 +1018,7 @@ void ExtrusionSimulator::evaluate_accumulator(ExtrusionSimulationType simulation float p = mask[r][c]; #endif int idx = int(floor(p * float(pimpl->color_gradient.size()) + 0.5f)); - V3uc clr = pimpl->color_gradient[clamp(0, int(pimpl->color_gradient.size()-1), idx)]; + V3uc clr = pimpl->color_gradient[std::clamp(idx, 0, int(pimpl->color_gradient.size()-1))]; *ptr ++ = clr.get<0>(); *ptr ++ = clr.get<1>(); *ptr ++ = clr.get<2>(); diff --git a/src/libslic3r/Fill/Fill3DHoneycomb.cpp b/src/libslic3r/Fill/Fill3DHoneycomb.cpp index 95c26fbad..9d4a34b6e 100644 --- a/src/libslic3r/Fill/Fill3DHoneycomb.cpp +++ b/src/libslic3r/Fill/Fill3DHoneycomb.cpp @@ -55,8 +55,8 @@ static std::vector perpendPoints(const coordf_t offset, const size_t b static inline void trim(Pointfs &pts, coordf_t minX, coordf_t minY, coordf_t maxX, coordf_t maxY) { for (Vec2d &pt : pts) { - pt(0) = clamp(minX, maxX, pt(0)); - pt(1) = clamp(minY, maxY, pt(1)); + pt.x() = std::clamp(pt.x(), minX, maxX); + pt.y() = std::clamp(pt.y(), minY, maxY); } } diff --git a/src/libslic3r/Fill/FillGyroid.cpp b/src/libslic3r/Fill/FillGyroid.cpp index ff2d049cf..6917c5d6e 100644 --- a/src/libslic3r/Fill/FillGyroid.cpp +++ b/src/libslic3r/Fill/FillGyroid.cpp @@ -53,7 +53,7 @@ static inline Polyline make_wave( polyline.points.reserve(points.size()); for (auto& point : points) { point(1) += offset; - point(1) = clamp(0., height, double(point(1))); + point(1) = std::clamp(double(point.y()), 0., height); if (vertical) std::swap(point(0), point(1)); polyline.points.emplace_back((point * scaleFactor).cast()); diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index a79940810..1108b71bd 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -796,7 +796,7 @@ namespace DoExport { // get the minimum cross-section used in the print std::vector mm3_per_mm; for (auto object : print.objects()) { - for (size_t region_id = 0; region_id < object->region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < object->num_regions(); ++ region_id) { const PrintRegion* region = print.regions()[region_id]; for (auto layer : object->layers()) { const LayerRegion* layerm = layer->regions()[region_id]; diff --git a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp index e00284fe1..49de854f2 100644 --- a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp +++ b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp @@ -620,7 +620,7 @@ static std::vector contour_distance(const EdgeGrid::Grid &grid, const Vec2d v = (segment.second - segment.first).cast(); const Vec2d va = (this->point - segment.first).cast(); const double l2 = v.squaredNorm(); // avoid a sqrt - const double t = (l2 == 0.0) ? 0. : clamp(0., 1., va.dot(v) / l2); + const double t = (l2 == 0.0) ? 0. : std::clamp(va.dot(v) / l2, 0., 1.); // Closest point from this->point to the segment. const Vec2d foot = segment.first.cast() + t * v; const Vec2d bisector = foot - this->point.cast(); diff --git a/src/libslic3r/GCode/CoolingBuffer.cpp b/src/libslic3r/GCode/CoolingBuffer.cpp index 7f48aae80..df2583875 100644 --- a/src/libslic3r/GCode/CoolingBuffer.cpp +++ b/src/libslic3r/GCode/CoolingBuffer.cpp @@ -722,8 +722,8 @@ std::string CoolingBuffer::apply_layer_cooldown( if (int(layer_id) >= disable_fan_first_layers && int(layer_id) + 1 < full_fan_speed_layer) { // Ramp up the fan speed from disable_fan_first_layers to full_fan_speed_layer. float factor = float(int(layer_id + 1) - disable_fan_first_layers) / float(full_fan_speed_layer - disable_fan_first_layers); - fan_speed_new = clamp(0, 255, int(float(fan_speed_new ) * factor + 0.5f)); - bridge_fan_speed = clamp(0, 255, int(float(bridge_fan_speed) * factor + 0.5f)); + fan_speed_new = std::clamp(int(float(fan_speed_new) * factor + 0.5f), 0, 255); + bridge_fan_speed = std::clamp(int(float(bridge_fan_speed) * factor + 0.5f), 0, 255); } #undef EXTRUDER_CONFIG bridge_fan_control = bridge_fan_speed > fan_speed_new; diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index c45e26015..aaa35aebe 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -223,7 +223,7 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto layer_tools.extruder_override = extruder_override; // What extruders are required to print this object layer? - for (size_t region_id = 0; region_id < object.region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < object.num_regions(); ++ region_id) { const LayerRegion *layerm = (region_id < layer->regions().size()) ? layer->regions()[region_id] : nullptr; if (layerm == nullptr) continue; @@ -689,7 +689,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int // iterate through copies (aka PrintObject instances) first, so that we mark neighbouring infills to minimize travel moves for (unsigned int copy = 0; copy < num_of_copies; ++copy) { - for (size_t region_id = 0; region_id < object->region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < object->num_regions(); ++ region_id) { const auto& region = *object->print()->regions()[region_id]; if (!region.config().wipe_into_infill && !object->config().wipe_into_objects) @@ -762,7 +762,7 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print) size_t num_of_copies = object->instances().size(); for (size_t copy = 0; copy < num_of_copies; ++copy) { // iterate through copies first, so that we mark neighbouring infills to minimize travel moves - for (size_t region_id = 0; region_id < object->region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < object->num_regions(); ++ region_id) { const auto& region = *object->print()->regions()[region_id]; if (!region.config().wipe_into_infill && !object->config().wipe_into_objects) diff --git a/src/libslic3r/MultiMaterialSegmentation.cpp b/src/libslic3r/MultiMaterialSegmentation.cpp index d4840a363..865e0aaa4 100644 --- a/src/libslic3r/MultiMaterialSegmentation.cpp +++ b/src/libslic3r/MultiMaterialSegmentation.cpp @@ -63,8 +63,8 @@ static bool project_line_on_line(const Line &projection_l, const Line &projected assert(t1 <= 1.); assert(t2 <= 1.); - Point p1 = (projection_l.a.cast() + t1 * v1).cast(); - Point p2 = (projection_l.a.cast() + t2 * v1).cast(); + Point p1 = projection_l.a + (t1 * v1).cast(); + Point p2 = projection_l.a + (t2 * v1).cast(); *new_projected = Line(p1, p2); return true; } @@ -74,7 +74,7 @@ struct PaintedLine size_t contour_idx; size_t line_idx; Line projected_line; - int color = 1; + int color; }; struct PaintedLineVisitor @@ -89,35 +89,31 @@ struct PaintedLineVisitor bool operator()(coord_t iy, coord_t ix) { // Called with a row and column of the grid cell, which is intersected by a line. - auto cell_data_range = grid.cell_data_range(iy, ix); + auto cell_data_range = grid.cell_data_range(iy, ix); + const Vec2d v1 = line_to_test.vector().cast(); for (auto it_contour_and_segment = cell_data_range.first; it_contour_and_segment != cell_data_range.second; ++it_contour_and_segment) { - Line grid_line = grid.line(*it_contour_and_segment); - - const Vec2d v1 = (line_to_test.b - line_to_test.a).cast().normalized(); - const Vec2d v2 = (grid_line.b - grid_line.a).cast().normalized(); - double angle = ::acos(clamp(-1.0, 1.0, v1.dot(v2))); - double angle_deg = Geometry::rad2deg(angle); + Line grid_line = grid.line(*it_contour_and_segment); + const Vec2d v2 = grid_line.vector().cast(); // When lines have too different length, it is necessary to normalize them - if ((angle_deg >= 0 && angle_deg <= 30) || (angle_deg >= 150)) { - Line line_to_test_projected; - project_line_on_line(grid_line, line_to_test, &line_to_test_projected); - + if (Slic3r::sqr(v1.dot(v2)) > cos_threshold2 * v1.squaredNorm() * v2.squaredNorm()) { + // The two vectors are nearly collinear (their mutual angle is lower than 30 degrees) if (painted_lines_set.find(*it_contour_and_segment) == painted_lines_set.end()) { - if (Line(grid_line.a, line_to_test_projected.a).length() > Line(grid_line.a, line_to_test_projected.b).length()) { - line_to_test_projected.reverse(); - } - double dist_1 = grid_line.distance_to(line_to_test.a); double dist_2 = grid_line.distance_to(line_to_test.b); double dist_3 = line_to_test.distance_to(grid_line.a); double dist_4 = line_to_test.distance_to(grid_line.b); double total_dist = std::min(std::min(dist_1, dist_2), std::min(dist_3, dist_4)); - if (total_dist > 50 * SCALED_EPSILON) - continue; + if (total_dist < 50 * SCALED_EPSILON) { + Line line_to_test_projected; + project_line_on_line(grid_line, line_to_test, &line_to_test_projected); - painted_lines.push_back({it_contour_and_segment->first, it_contour_and_segment->second, line_to_test_projected, this->color}); - painted_lines_set.insert(*it_contour_and_segment); + if (Line(grid_line.a, line_to_test_projected.a).length() > Line(grid_line.a, line_to_test_projected.b).length()) { + line_to_test_projected.reverse(); + } + painted_lines.push_back({it_contour_and_segment->first, it_contour_and_segment->second, line_to_test_projected, this->color}); + painted_lines_set.insert(*it_contour_and_segment); + } } } } @@ -130,13 +126,15 @@ struct PaintedLineVisitor Line line_to_test; std::unordered_set, boost::hash>> painted_lines_set; int color = -1; + + static inline const double cos_threshold2 = Slic3r::sqr(cos(M_PI * 30. / 180.)); }; static std::vector to_colored_lines(const Polygon &polygon, int color) { std::vector lines; - lines.reserve(polygon.points.size()); if (polygon.points.size() > 2) { + lines.reserve(polygon.points.size()); for (auto it = polygon.points.begin(); it != polygon.points.end() - 1; ++it) lines.push_back({Line(*it, *(it + 1)), color}); lines.push_back({Line(polygon.points.back(), polygon.points.front()), color}); @@ -146,10 +144,11 @@ static std::vector to_colored_lines(const Polygon &polygon, int col static Polygon colored_points_to_polygon(const std::vector &lines) { - Points out; + Polygon out; + out.points.reserve(lines.size()); for (const ColoredLine &l : lines) - out.emplace_back(l.line.a); - return Polygon(out); + out.points.emplace_back(l.line.a); + return out; } static Polygons colored_points_to_polygon(const std::vector> &lines) @@ -160,7 +159,8 @@ static Polygons colored_points_to_polygon(const std::vector to_lines(const std::vector> &c_lines) +// Flatten the vector of vectors into a vector. +static inline std::vector to_lines(const std::vector> &c_lines) { size_t n_lines = 0; for (const auto &c_line : c_lines) @@ -173,8 +173,7 @@ inline std::vector to_lines(const std::vector -inline bool vertex_equal_to_point(const VertexType &vertex, const Point &ipt) +static bool vertex_equal_to_point(const Voronoi::VD::vertex_type &vertex, const Point &ipt) { // Convert ipt to doubles, force the 80bit FPU temporary to 64bit and then compare. // This should work with any settings of math compiler switches and the C++ compiler @@ -186,7 +185,7 @@ inline bool vertex_equal_to_point(const VertexType &vertex, const Point &ipt) ulp_cmp(vertex.y(), double(ipt.y()), ULPS) == ulp_cmp_type::EQUAL; } -bool vertex_equal_to_point(const Voronoi::VD::vertex_type *vertex, const Point &ipt) { +static inline bool vertex_equal_to_point(const Voronoi::VD::vertex_type *vertex, const Point &ipt) { return vertex_equal_to_point(*vertex, ipt); } @@ -967,7 +966,7 @@ static std::vector> extract_colored_segments(MMU_Grap Vec2d process_line_vec_n = (process_line.a - process_line.b).cast().normalized(); Vec2d neighbour_line_vec_n = (graph.nodes[arc.to_idx].point - graph.nodes[arc.from_idx].point).cast().normalized(); - double angle = ::acos(clamp(-1.0, 1.0, neighbour_line_vec_n.dot(process_line_vec_n))); + double angle = ::acos(std::clamp(neighbour_line_vec_n.dot(process_line_vec_n), -1.0, 1.0)); if (Slic3r::cross2(neighbour_line_vec_n, process_line_vec_n) < 0.0) angle = 2.0 * (double) PI - angle; @@ -1050,7 +1049,7 @@ static inline double compute_edge_length(MMU_Graph &graph, size_t start_idx, MMU Vec2d second_line_vec = (second_line.b - second_line.a).cast(); Vec2d first_line_vec_n = first_line_vec.normalized(); Vec2d second_line_vec_n = second_line_vec.normalized(); - double angle = ::acos(clamp(-1.0, 1.0, first_line_vec_n.dot(second_line_vec_n))); + double angle = ::acos(std::clamp(first_line_vec_n.dot(second_line_vec_n), -1.0, 1.0)); if (Slic3r::cross2(first_line_vec_n, second_line_vec_n) < 0.0) angle = 2.0 * (double) PI - angle; @@ -1276,9 +1275,9 @@ static inline std::vector> mmu_segmentation_top_and_bott for (size_t layer_idx = 0; layer_idx < print_object.layers().size(); ++layer_idx) { BOOST_LOG_TRIVIAL(debug) << "MMU segmentation of bottom layer: " << layer_idx; - float extrusion_width = scale_(get_extrusion_width(layer_idx)); - int bottom_solid_layers = get_bottom_solid_layers(layer_idx); - ExPolygons bottom_expolygon = bottom_layers[layer_idx]; + float extrusion_width = scale_(get_extrusion_width(layer_idx)); + int bottom_solid_layers = get_bottom_solid_layers(layer_idx); + const ExPolygons &bottom_expolygon = bottom_layers[layer_idx]; if (bottom_expolygon.empty()) continue; @@ -1301,8 +1300,7 @@ static inline std::vector> mmu_segmentation_top_and_bott ExPolygons offset_e = offset_ex(layer_slices_trimmed, offset_value); ExPolygons intersection_poly_2 = intersection_ex(triangles_by_color_bottom[color_idx][layer_idx], offset_e); - triangles_by_color_bottom[color_idx][last_idx].insert(triangles_by_color_bottom[color_idx][last_idx].end(), intersection_poly_2.begin(), - intersection_poly_2.end()); + append(triangles_by_color_bottom[color_idx][last_idx], std::move(intersection_poly_2)); } } } @@ -1312,13 +1310,10 @@ static inline std::vector> mmu_segmentation_top_and_bott triangles_by_color_merged.assign(3, std::vector(layers.size())); for (size_t layer_idx = 0; layer_idx < layers.size(); ++layer_idx) { for (size_t color_idx = 0; color_idx < triangles_by_color_merged.size(); ++color_idx) { - triangles_by_color_merged[color_idx][layer_idx].insert(triangles_by_color_merged[color_idx][layer_idx].end(), - triangles_by_color_bottom[color_idx][layer_idx].begin(), - triangles_by_color_bottom[color_idx][layer_idx].end()); - triangles_by_color_merged[color_idx][layer_idx].insert(triangles_by_color_merged[color_idx][layer_idx].end(), - triangles_by_color_top[color_idx][layer_idx].begin(), - triangles_by_color_top[color_idx][layer_idx].end()); - triangles_by_color_merged[color_idx][layer_idx] = union_ex(triangles_by_color_merged[color_idx][layer_idx]); + auto &self = triangles_by_color_merged[color_idx][layer_idx]; + append(self, std::move(triangles_by_color_bottom[color_idx][layer_idx])); + append(self, std::move(triangles_by_color_top[color_idx][layer_idx])); + self = union_ex(self); } // Cut all colors for cases when two colors are overlapping @@ -1332,7 +1327,7 @@ static inline std::vector> mmu_segmentation_top_and_bott } static std::vector>> merge_segmented_layers( - const std::vector>> &segmented_regions, const std::vector> &top_and_bottom_layers) + const std::vector>> &segmented_regions, std::vector> &&top_and_bottom_layers) { std::vector>> segmented_regions_merged(segmented_regions.size()); @@ -1344,14 +1339,12 @@ static std::vector>> merge_segmented_la for (const std::vector &top_and_bottom_layer : top_and_bottom_layers) cut_colored_expoly = diff_ex(cut_colored_expoly, top_and_bottom_layer[layer_idx]); for (ExPolygon &ex_poly : cut_colored_expoly) - segmented_regions_merged[layer_idx].emplace_back(ex_poly, colored_expoly.second); - + segmented_regions_merged[layer_idx].emplace_back(std::move(ex_poly), colored_expoly.second); } - for (size_t color_idx = 0; color_idx < top_and_bottom_layers.size(); ++color_idx) { - ExPolygons top_and_bottom_expoly = top_and_bottom_layers[color_idx][layer_idx]; - for (const ExPolygon &expoly : top_and_bottom_expoly) { segmented_regions_merged[layer_idx].emplace_back(expoly, color_idx); } - } + for (size_t color_idx = 0; color_idx < top_and_bottom_layers.size(); ++color_idx) + for (ExPolygon &expoly : top_and_bottom_layers[color_idx][layer_idx]) + segmented_regions_merged[layer_idx].emplace_back(std::move(expoly), color_idx); } }); // end of parallel_for @@ -1385,7 +1378,6 @@ std::vector>> multi_material_segmentati float max_z = std::numeric_limits::lowest(); std::array facet; - Points projected_facet(3); for (int p_idx = 0; p_idx < 3; ++p_idx) { facet[p_idx] = tr * custom_facets.vertices[custom_facets.indices[facet_idx](p_idx)]; max_z = std::max(max_z, facet[p_idx].z()); @@ -1395,13 +1387,6 @@ std::vector>> multi_material_segmentati // Sort the vertices by z-axis for simplification of projected_facet on slices std::sort(facet.begin(), facet.end(), [](const Vec3f &p1, const Vec3f &p2) { return p1.z() < p2.z(); }); - for (int p_idx = 0; p_idx < 3; ++p_idx) { - projected_facet[p_idx] = Point(scale_(facet[p_idx].x()), scale_(facet[p_idx].y())); - projected_facet[p_idx] = projected_facet[p_idx] - print_object.center_offset(); - } - - ExPolygon triangle = ExPolygon(projected_facet); - // Find lowest slice not below the triangle. auto first_layer = std::upper_bound(print_object.layers().begin(), print_object.layers().end(), float(min_z - EPSILON), [](float z, const Layer *l1) { return z < l1->slice_z; }); @@ -1443,8 +1428,7 @@ std::vector>> multi_material_segmentati visitor.color = params.second; edge_grids[layer_idx].visit_cells_intersecting_line(line_start, line_end, visitor); - if (!painted_line_tmp.empty()) - painted_lines[layer_idx].insert(painted_lines[layer_idx].end(), painted_line_tmp.begin(), painted_line_tmp.end()); + append(painted_lines[layer_idx], std::move(painted_line_tmp)); } } } @@ -1454,7 +1438,7 @@ std::vector>> multi_material_segmentati for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { // for(size_t layer_idx = 0; layer_idx < print_object.layers().size(); ++layer_idx) { BOOST_LOG_TRIVIAL(debug) << "MMU segmentation of layer: " << layer_idx; - auto comp = [&edge_grids, &layer_idx](const PaintedLine &first, const PaintedLine &second) { + auto comp = [&edge_grids, layer_idx](const PaintedLine &first, const PaintedLine &second) { Point first_start_p = *(edge_grids[layer_idx].contours()[first.contour_idx].begin() + first.line_idx); return first.contour_idx < second.contour_idx || @@ -1469,11 +1453,8 @@ std::vector>> multi_material_segmentati if (!painted_lines_single.empty()) { Polygons original_polygons; - for (const Slic3r::EdgeGrid::Contour &contour : edge_grids[layer_idx].contours()) { - Points points; - for (const Point &point : contour) points.emplace_back(point); - original_polygons.emplace_back(points); - } + for (const Slic3r::EdgeGrid::Contour &contour : edge_grids[layer_idx].contours()) + original_polygons.emplace_back(Points(contour.begin(), contour.end())); std::vector> color_poly = colorize_polygons(original_polygons, painted_lines_single); MMU_Graph graph = build_graph(layer_idx, color_poly); @@ -1491,7 +1472,7 @@ std::vector>> multi_material_segmentati // return segmented_regions; std::vector> top_and_bottom_layers = mmu_segmentation_top_and_bottom_layers(print_object); - std::vector>> segmented_regions_merged = merge_segmented_layers(segmented_regions, top_and_bottom_layers); + std::vector>> segmented_regions_merged = merge_segmented_layers(segmented_regions, std::move(top_and_bottom_layers)); return segmented_regions_merged; } diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index c8ab9b2c2..66dc5de5d 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -1066,7 +1066,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ assert(it_status->status != ModelObjectStatus::Deleted); layer_ranges = &it_status->layer_ranges; } - if (region_id < print_object->region_volumes.size()) { + if (region_id < print_object->num_regions()) { for (const std::pair &volume_and_range : print_object->region_volumes[region_id]) { const ModelVolume &volume = *print_object->model_object()->volumes[volume_and_range.second]; const DynamicPrintConfig *layer_range_config = layer_ranges->config(volume_and_range.first); @@ -1106,7 +1106,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ if (! diff.empty()) { // Stop the background process before assigning new configuration to the regions. for (PrintObject *print_object : m_objects) - if (region_id < print_object->region_volumes.size() && ! print_object->region_volumes[region_id].empty()) + if (print_object->has_region(region_id)) update_apply_status(print_object->invalidate_state_by_config_options(region.config(), this_region_config, diff)); region.config_apply_only(this_region_config, diff, false); } @@ -1169,7 +1169,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ region_id = regions_in_object[idx_region_in_object ++]; // Assign volume to a region. if (fresh) { - if ((size_t)region_id >= print_object.region_volumes.size() || print_object.region_volumes[region_id].empty()) + if (! print_object.has_region(size_t(region_id))) ++ m_regions[region_id]->m_refcnt; print_object.add_region_volume(region_id, volume_id, it_range->first); } @@ -1506,7 +1506,7 @@ std::string Print::validate(std::string* warning) const if ((object->has_support() || object->has_raft()) && ! validate_extrusion_width(object->config(), "support_material_extrusion_width", layer_height, err_msg)) return err_msg; for (const char *opt_key : { "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", "top_infill_extrusion_width" }) - for (size_t i = 0; i < object->region_volumes.size(); ++ i) + for (size_t i = 0; i < object->num_regions(); ++ i) if (! object->region_volumes[i].empty() && ! validate_extrusion_width(this->get_region(i)->config(), opt_key, layer_height, err_msg)) return err_msg; } diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 91f86d010..70debefb6 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -177,6 +177,8 @@ public: bool has_brim() const { return this->config().brim_type != btNoBrim && this->config().brim_width.value > 0.; } + size_t num_regions() const { return this->region_volumes.size(); } + bool has_region(size_t i) const { return i < this->region_volumes.size() && ! this->region_volumes[i].empty(); } // adds region_id, too, if necessary void add_region_volume(unsigned int region_id, int volume_id, const t_layer_height_range &layer_range) { @@ -471,6 +473,7 @@ public: return (it == m_objects.end()) ? nullptr : *it; } ConstPrintRegionPtrsAdaptor regions() const { return ConstPrintRegionPtrsAdaptor(&m_regions); } + size_t num_regions() const { return m_regions.size(); } // How many of PrintObject::copies() over all print objects are there? // If zero, then the print is empty and the print shall not be executed. unsigned int num_object_instances() const; diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index f85568ba5..a1d8f65bf 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -174,7 +174,7 @@ void PrintObject::make_perimeters() // but we don't generate any extra perimeter if fill density is zero, as they would be floating // inside the object - infill_only_where_needed should be the method of choice for printing // hollow objects - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < this->num_regions(); ++ region_id) { const PrintRegion ®ion = *m_print->regions()[region_id]; if (! region.config().extra_perimeters || region.config().perimeters == 0 || region.config().fill_density == 0 || this->layer_count() < 2) continue; @@ -295,7 +295,7 @@ void PrintObject::prepare_infill() // Debugging output. #ifdef SLIC3R_DEBUG_SLICE_PROCESSING - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < this->num_regions(); ++ region_id) { for (const Layer *layer : m_layers) { LayerRegion *layerm = layer->m_regions[region_id]; layerm->export_region_slices_to_svg_debug("6_discover_vertical_shells-final"); @@ -314,7 +314,7 @@ void PrintObject::prepare_infill() m_print->throw_if_canceled(); #ifdef SLIC3R_DEBUG_SLICE_PROCESSING - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < this->num_regions(); ++ region_id) { for (const Layer *layer : m_layers) { LayerRegion *layerm = layer->m_regions[region_id]; layerm->export_region_slices_to_svg_debug("7_discover_horizontal_shells-final"); @@ -333,7 +333,7 @@ void PrintObject::prepare_infill() m_print->throw_if_canceled(); #ifdef SLIC3R_DEBUG_SLICE_PROCESSING - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < this->num_regions(); ++ region_id) { for (const Layer *layer : m_layers) { LayerRegion *layerm = layer->m_regions[region_id]; layerm->export_region_slices_to_svg_debug("8_clip_surfaces-final"); @@ -352,7 +352,7 @@ void PrintObject::prepare_infill() m_print->throw_if_canceled(); #ifdef SLIC3R_DEBUG_SLICE_PROCESSING - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < this->num_regions(); ++ region_id) { for (const Layer *layer : m_layers) { LayerRegion *layerm = layer->m_regions[region_id]; layerm->export_region_slices_to_svg_debug("9_prepare_infill-final"); @@ -744,7 +744,7 @@ bool PrintObject::invalidate_all_steps() static const PrintRegion* first_printing_region(const PrintObject &print_object) { - for (size_t idx_region = 0; idx_region < print_object.region_volumes.size(); ++ idx_region) + for (size_t idx_region = 0; idx_region < print_object.num_regions(); ++ idx_region) if (!print_object.region_volumes.empty()) return print_object.print()->regions()[idx_region]; return nullptr; @@ -772,7 +772,7 @@ void PrintObject::detect_surfaces_type() bool interface_shells = ! spiral_vase && m_config.interface_shells.value; size_t num_layers = spiral_vase ? std::min(size_t(first_printing_region(*this)->config().bottom_solid_layers), m_layers.size()) : m_layers.size(); - for (size_t idx_region = 0; idx_region < this->region_volumes.size(); ++ idx_region) { + for (size_t idx_region = 0; idx_region < this->num_regions(); ++ idx_region) { BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << idx_region << " in parallel - start"; #ifdef SLIC3R_DEBUG_SLICE_PROCESSING for (Layer *layer : m_layers) @@ -971,7 +971,7 @@ void PrintObject::process_external_surfaces() // Is there any printing region, that has zero infill? If so, then we don't want the expansion to be performed over the complete voids, but only // over voids, which are supported by the layer below. bool has_voids = false; - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) + for (size_t region_id = 0; region_id < this->num_regions(); ++ region_id) if (! this->region_volumes.empty() && this->print()->regions()[region_id]->config().fill_density == 0) { has_voids = true; break; @@ -1021,7 +1021,7 @@ void PrintObject::process_external_surfaces() BOOST_LOG_TRIVIAL(debug) << "Collecting surfaces covered with extrusions in parallel - end"; } - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++region_id) { + for (size_t region_id = 0; region_id < this->num_regions(); ++region_id) { BOOST_LOG_TRIVIAL(debug) << "Processing external surfaces for region " << region_id << " in parallel - start"; tbb::parallel_for( tbb::blocked_range(0, m_layers.size()), @@ -1069,13 +1069,13 @@ void PrintObject::discover_vertical_shells() num_extra_layers(config.bottom_solid_layers, config.bottom_solid_min_thickness) > 0; }; std::vector cache_top_botom_regions(num_layers, DiscoverVerticalShellsCacheEntry()); - bool top_bottom_surfaces_all_regions = this->region_volumes.size() > 1 && ! m_config.interface_shells.value; + bool top_bottom_surfaces_all_regions = this->num_regions() > 1 && ! m_config.interface_shells.value; if (top_bottom_surfaces_all_regions) { // This is a multi-material print and interface_shells are disabled, meaning that the vertical shell thickness // is calculated over all materials. // Is the "ensure vertical wall thickness" applicable to any region? bool has_extra_layers = false; - for (size_t idx_region = 0; idx_region < this->region_volumes.size(); ++idx_region) { + for (size_t idx_region = 0; idx_region < this->num_regions(); ++idx_region) { const PrintRegionConfig &config = m_print->get_region(idx_region)->config(); if (config.ensure_vertical_shell_thickness.value && has_extra_layers_fn(config)) { has_extra_layers = true; @@ -1092,7 +1092,7 @@ void PrintObject::discover_vertical_shells() tbb::blocked_range(0, num_layers, grain_size), [this, &cache_top_botom_regions](const tbb::blocked_range& range) { const SurfaceType surfaces_bottom[2] = { stBottom, stBottomBridge }; - const size_t num_regions = this->region_volumes.size(); + const size_t num_regions = this->num_regions(); for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) { m_print->throw_if_canceled(); const Layer &layer = *m_layers[idx_layer]; @@ -1153,7 +1153,7 @@ void PrintObject::discover_vertical_shells() BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells in parallel - end : cache top / bottom"; } - for (size_t idx_region = 0; idx_region < this->region_volumes.size(); ++ idx_region) { + for (size_t idx_region = 0; idx_region < this->num_regions(); ++ idx_region) { PROFILE_BLOCK(discover_vertical_shells_region); const PrintRegion ®ion = *m_print->get_region(idx_region); @@ -1458,7 +1458,7 @@ void PrintObject::bridge_over_infill() { BOOST_LOG_TRIVIAL(info) << "Bridge over infill..." << log_memory_info(); - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < this->num_regions(); ++ region_id) { const PrintRegion ®ion = *m_print->regions()[region_id]; // skip bridging in case there are no voids @@ -1685,9 +1685,9 @@ SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig& full std::vector PrintObject::object_extruders() const { std::vector extruders; - extruders.reserve(this->region_volumes.size() * 3); - for (size_t idx_region = 0; idx_region < this->region_volumes.size(); ++ idx_region) - if (! this->region_volumes[idx_region].empty()) + extruders.reserve(this->num_regions() * 3); + for (size_t idx_region = 0; idx_region < this->num_regions(); ++ idx_region) + if (this->has_region(idx_region)) m_print->get_region(idx_region)->collect_object_printing_extruders(extruders); sort_remove_duplicates(extruders); return extruders; @@ -1756,7 +1756,7 @@ void PrintObject::_slice(const std::vector &layer_height_profile) layer->lower_layer = prev; } // Make sure all layers contain layer region objects for all regions. - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) + for (size_t region_id = 0; region_id < this->num_regions(); ++ region_id) layer->add_region(this->print()->get_region(region_id)); prev = layer; } @@ -1767,7 +1767,7 @@ void PrintObject::_slice(const std::vector &layer_height_profile) bool has_z_ranges = false; size_t num_volumes = 0; size_t num_modifiers = 0; - for (int region_id = 0; region_id < (int)this->region_volumes.size(); ++ region_id) { + for (int region_id = 0; region_id < (int)this->num_regions(); ++ region_id) { int last_volume_id = -1; for (const std::pair &volume_and_range : this->region_volumes[region_id]) { const int volume_id = volume_and_range.second; @@ -1799,7 +1799,7 @@ void PrintObject::_slice(const std::vector &layer_height_profile) if (! has_z_ranges && (! m_config.clip_multipart_objects.value || all_volumes_single_region >= 0)) { // Cheap path: Slice regions without mutual clipping. // The cheap path is possible if no clipping is allowed or if slicing volumes of just a single region. - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < this->num_regions(); ++ region_id) { BOOST_LOG_TRIVIAL(debug) << "Slicing objects - region " << region_id; // slicing in parallel size_t slicing_mode_normal_below_layer = 0; @@ -1832,7 +1832,7 @@ void PrintObject::_slice(const std::vector &layer_height_profile) }; std::vector sliced_volumes; sliced_volumes.reserve(num_volumes); - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < this->num_regions(); ++ region_id) { const std::vector> &volumes_and_ranges = this->region_volumes[region_id]; for (size_t i = 0; i < volumes_and_ranges.size(); ) { int volume_id = volumes_and_ranges[i].second; @@ -1884,7 +1884,7 @@ void PrintObject::_slice(const std::vector &layer_height_profile) } } // Collect and union volumes of a single region. - for (int region_id = 0; region_id < (int)this->region_volumes.size(); ++ region_id) { + for (int region_id = 0; region_id < (int)this->num_regions(); ++ region_id) { ExPolygons expolygons; size_t num_volumes = 0; for (SlicedVolume &sliced_volume : sliced_volumes) @@ -1915,7 +1915,7 @@ void PrintObject::_slice(const std::vector &layer_height_profile) this->m_layers[layer_idx]->lslices = union_ex(ex_polygons); } - size_t region_count_before_change = this->region_volumes.size(); + size_t region_count_before_change = this->num_regions(); std::vector>> segmented_regions = multi_material_segmentation_by_painting(*this); // Skip region with default extruder for (size_t region_idx = 1; region_idx < 3; ++region_idx) { @@ -1944,15 +1944,15 @@ void PrintObject::_slice(const std::vector &layer_height_profile) for (size_t i_layer = 0; i_layer < m_layers.size(); i_layer += 1) { Layer *layer = m_layers[i_layer]; // Make sure all layers contain layer region objects for all regions. - for (size_t region_id = region_count_before_change; region_id < this->region_volumes.size(); ++ region_id) + for (size_t region_id = region_count_before_change; region_id < this->num_regions(); ++ region_id) layer->add_region(this->print()->get_region(region_id)); } // --------------------MMU_SEGMENTATION_END---------------------- // Slice all modifier volumes. - if (this->region_volumes.size() > 1) { - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { + if (this->num_regions() > 1) { + for (size_t region_id = 0; region_id < this->num_regions(); ++ region_id) { BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - region " << region_id; // slicing in parallel std::vector expolygons_by_layer = this->slice_modifiers(region_id, slice_zs); @@ -1965,7 +1965,7 @@ void PrintObject::_slice(const std::vector &layer_height_profile) tbb::blocked_range(0, m_layers.size()), [this, &expolygons_by_layer, region_id](const tbb::blocked_range& range) { for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) { - for (size_t other_region_id = 0; other_region_id < this->region_volumes.size(); ++ other_region_id) { + for (size_t other_region_id = 0; other_region_id < this->num_regions(); ++ other_region_id) { if (region_id == other_region_id) continue; Layer *layer = m_layers[layer_id]; @@ -2106,7 +2106,7 @@ end: std::vector PrintObject::slice_region(size_t region_id, const std::vector &z, SlicingMode mode, size_t slicing_mode_normal_below_layer, SlicingMode mode_below) const { std::vector volumes; - if (region_id < this->region_volumes.size()) { + if (region_id < this->num_regions()) { for (const std::pair &volume_and_range : this->region_volumes[region_id]) { const ModelVolume *volume = this->model_object()->volumes[volume_and_range.second]; if (volume->is_model_part()) @@ -2120,7 +2120,7 @@ std::vector PrintObject::slice_region(size_t region_id, const std::v std::vector PrintObject::slice_modifiers(size_t region_id, const std::vector &slice_zs) const { std::vector out; - if (region_id < this->region_volumes.size()) + if (region_id < this->num_regions()) { std::vector> volume_ranges; const std::vector> &volumes_and_ranges = this->region_volumes[region_id]; @@ -2174,7 +2174,7 @@ std::vector PrintObject::slice_modifiers(size_t region_id, const std } else { // Some modifier in this region was split to layer spans. std::vector merge; - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < this->num_regions(); ++ region_id) { const std::vector> &volumes_and_ranges = this->region_volumes[region_id]; for (size_t i = 0; i < volumes_and_ranges.size(); ) { int volume_id = volumes_and_ranges[i].second; @@ -2544,7 +2544,7 @@ void PrintObject::discover_horizontal_shells() { BOOST_LOG_TRIVIAL(trace) << "discover_horizontal_shells()"; - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < this->num_regions(); ++ region_id) { for (size_t i = 0; i < m_layers.size(); ++ i) { m_print->throw_if_canceled(); Layer *layer = m_layers[i]; @@ -2730,7 +2730,7 @@ void PrintObject::discover_horizontal_shells() } // for each region #ifdef SLIC3R_DEBUG_SLICE_PROCESSING - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < this->num_regions(); ++ region_id) { for (const Layer *layer : m_layers) { const LayerRegion *layerm = layer->m_regions[region_id]; layerm->export_region_slices_to_svg_debug("5_discover_horizontal_shells"); @@ -2746,7 +2746,7 @@ void PrintObject::discover_horizontal_shells() void PrintObject::combine_infill() { // Work on each region separately. - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < this->num_regions(); ++ region_id) { const PrintRegion *region = this->print()->regions()[region_id]; const size_t every = region->config().infill_every_layers.value; if (every < 2 || region->config().fill_density == 0.) diff --git a/src/libslic3r/Slicing.cpp b/src/libslic3r/Slicing.cpp index d0b1e9ce2..87ffdf850 100644 --- a/src/libslic3r/Slicing.cpp +++ b/src/libslic3r/Slicing.cpp @@ -298,7 +298,7 @@ std::vector layer_height_profile_adaptive(const SlicingParameters& slici if (z_gap > 0.0) { layer_height_profile.push_back(slicing_params.object_print_z_height()); - layer_height_profile.push_back(clamp(slicing_params.min_layer_height, slicing_params.max_layer_height, z_gap)); + layer_height_profile.push_back(std::clamp(z_gap, slicing_params.min_layer_height, slicing_params.max_layer_height)); } return layer_height_profile; @@ -376,7 +376,7 @@ std::vector smooth_height_profile(const std::vector& profile, co } } - height = clamp(slicing_params.min_layer_height, slicing_params.max_layer_height, (weight_total != 0.0) ? height /= weight_total : hi); + height = std::clamp((weight_total != 0.0) ? height /= weight_total : hi, slicing_params.min_layer_height, slicing_params.max_layer_height); if (smoothing_params.keep_min) height = std::min(height, hi); } @@ -502,7 +502,7 @@ void adjust_layer_height_profile( assert(false); break; } - height = clamp(slicing_params.min_layer_height, slicing_params.max_layer_height, height); + height = std::clamp(height, slicing_params.min_layer_height, slicing_params.max_layer_height); if (zz == z_span_variable.second) { // This is the last point of the profile. if (profile_new[profile_new.size() - 2] + EPSILON > zz) { @@ -670,11 +670,11 @@ int generate_layer_height_texture( assert(mid <= slicing_params.object_print_z_height()); coordf_t h = hi - lo; hi = std::min(hi, slicing_params.object_print_z_height()); - int cell_first = clamp(0, ncells-1, int(ceil(lo * z_to_cell))); - int cell_last = clamp(0, ncells-1, int(floor(hi * z_to_cell))); + int cell_first = std::clamp(int(ceil(lo * z_to_cell)), 0, ncells-1); + int cell_last = std::clamp(int(floor(hi * z_to_cell)), 0, ncells-1); for (int cell = cell_first; cell <= cell_last; ++ cell) { coordf_t idxf = (0.5 * hscale + (h - slicing_params.layer_height)) * coordf_t(palette_raw.size()-1) / hscale; - int idx1 = clamp(0, int(palette_raw.size() - 1), int(floor(idxf))); + int idx1 = std::clamp(int(floor(idxf)), 0, int(palette_raw.size() - 1)); int idx2 = std::min(int(palette_raw.size() - 1), idx1 + 1); coordf_t t = idxf - coordf_t(idx1); const Vec3crd &color1 = palette_raw[idx1]; @@ -693,9 +693,9 @@ int generate_layer_height_texture( assert(row >= 0 && row < rows); assert(col >= 0 && col < cols); unsigned char *ptr = (unsigned char*)data + (row * cols + col) * 4; - ptr[0] = (unsigned char)clamp(0, 255, int(floor(color(0) + 0.5))); - ptr[1] = (unsigned char)clamp(0, 255, int(floor(color(1) + 0.5))); - ptr[2] = (unsigned char)clamp(0, 255, int(floor(color(2) + 0.5))); + ptr[0] = (unsigned char)std::clamp(int(floor(color(0) + 0.5)), 0, 255); + ptr[1] = (unsigned char)std::clamp(int(floor(color(1) + 0.5)), 0, 255); + ptr[2] = (unsigned char)std::clamp(int(floor(color(2) + 0.5)), 0, 255); ptr[3] = 255; if (col == 0 && row > 0) { // Duplicate the first value in a row as a last value of the preceding row. @@ -706,11 +706,11 @@ int generate_layer_height_texture( } } if (level_of_detail_2nd_level) { - cell_first = clamp(0, ncells1-1, int(ceil(lo * z_to_cell1))); - cell_last = clamp(0, ncells1-1, int(floor(hi * z_to_cell1))); + cell_first = std::clamp(int(ceil(lo * z_to_cell1)), 0, ncells1-1); + cell_last = std::clamp(int(floor(hi * z_to_cell1)), 0, ncells1-1); for (int cell = cell_first; cell <= cell_last; ++ cell) { coordf_t idxf = (0.5 * hscale + (h - slicing_params.layer_height)) * coordf_t(palette_raw.size()-1) / hscale; - int idx1 = clamp(0, int(palette_raw.size() - 1), int(floor(idxf))); + int idx1 = std::clamp(int(floor(idxf)), 0, int(palette_raw.size() - 1)); int idx2 = std::min(int(palette_raw.size() - 1), idx1 + 1); coordf_t t = idxf - coordf_t(idx1); const Vec3crd &color1 = palette_raw[idx1]; @@ -725,9 +725,9 @@ int generate_layer_height_texture( assert(row >= 0 && row < rows/2); assert(col >= 0 && col < cols/2); unsigned char *ptr = data1 + (row * cols1 + col) * 4; - ptr[0] = (unsigned char)clamp(0, 255, int(floor(color(0) + 0.5))); - ptr[1] = (unsigned char)clamp(0, 255, int(floor(color(1) + 0.5))); - ptr[2] = (unsigned char)clamp(0, 255, int(floor(color(2) + 0.5))); + ptr[0] = (unsigned char)std::clamp(int(floor(color(0) + 0.5)), 0, 255); + ptr[1] = (unsigned char)std::clamp(int(floor(color(1) + 0.5)), 0, 255); + ptr[2] = (unsigned char)std::clamp(int(floor(color(2) + 0.5)), 0, 255); ptr[3] = 255; if (col == 0 && row > 0) { // Duplicate the first value in a row as a last value of the preceding row. diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index 08cd04b90..ca0b058f5 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -347,8 +347,8 @@ PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object coordf_t external_perimeter_width = 0.; size_t num_nonempty_regions = 0; coordf_t bridge_flow_ratio = 0; - for (size_t region_id = 0; region_id < object->region_volumes.size(); ++ region_id) - if (! object->region_volumes[region_id].empty()) { + for (size_t region_id = 0; region_id < object->num_regions(); ++ region_id) + if (object->has_region(region_id)) { ++ num_nonempty_regions; const PrintRegion ®ion = *object->print()->get_region(region_id); external_perimeter_width = std::max(external_perimeter_width, coordf_t(region.flow(*object, frExternalPerimeter, slicing_params.layer_height).width())); diff --git a/src/libslic3r/VoronoiOffset.cpp b/src/libslic3r/VoronoiOffset.cpp index 2108388f5..e8d13a6ad 100644 --- a/src/libslic3r/VoronoiOffset.cpp +++ b/src/libslic3r/VoronoiOffset.cpp @@ -41,7 +41,7 @@ namespace detail { // Degenerate to a single closest point. t = - b / (2. * a); assert(t >= - EPSILON && t <= 1. + EPSILON); - return Slic3r::clamp(0., 1., t); + return std::clamp(t, 0., 1.); } else { u = sqrt(u); out.first = 2; @@ -1142,7 +1142,7 @@ std::vector edge_offset_contour_intersections( #endif // NDEBUG if (! bisector || (dmin != dmax && offset_distance >= dmin)) { double t = (offset_distance - dmin) / (dmax - dmin); - t = clamp(0., 1., t); + t = std::clamp(t, 0., 1.); if (d1 < d0) { out[edge_idx2] = Slic3r::lerp(vertex_point(v1), vertex_point(v0), t); // mark visited diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index efdecbac8..5bea6d092 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -239,26 +239,20 @@ template inline bool one_of(const T& v, const std::initializer_list< { return contains(il, v); } template -static inline T sqr(T x) +constexpr inline T sqr(T x) { return x * x; } -template -static inline T clamp(const T low, const T high, const T value) -{ - return std::max(low, std::min(high, value)); -} - template -static inline T lerp(const T& a, const T& b, Number t) +constexpr inline T lerp(const T& a, const T& b, Number t) { assert((t >= Number(-EPSILON)) && (t <= Number(1) + Number(EPSILON))); return (Number(1) - t) * a + t * b; } template -static inline bool is_approx(Number value, Number test_value) +constexpr inline bool is_approx(Number value, Number test_value) { return std::fabs(double(value) - double(test_value)) < double(EPSILON); } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 105eeab06..3a9fc526d 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -271,7 +271,7 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const ImGui::SameLine(); float widget_align = ImGui::GetCursorPosX(); ImGui::PushItemWidth(imgui.get_style_scaling() * 120.0f); - m_adaptive_quality = clamp(0.0f, 1.f, m_adaptive_quality); + m_adaptive_quality = std::clamp(m_adaptive_quality, 0.0f, 1.f); ImGui::SliderFloat("", &m_adaptive_quality, 0.0f, 1.f, "%.2f"); ImGui::Separator(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 6b6905e4d..63cb051aa 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -110,7 +110,7 @@ void GLGizmoRotate::on_update(const UpdateData& data) Vec2d orig_dir = Vec2d::UnitX(); Vec2d new_dir = mouse_pos.normalized(); - double theta = ::acos(clamp(-1.0, 1.0, new_dir.dot(orig_dir))); + double theta = ::acos(std::clamp(new_dir.dot(orig_dir), -1.0, 1.0)); if (cross2(orig_dir, new_dir) < 0.0) theta = 2.0 * (double)PI - theta;