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.
This commit is contained in:
Vojtech Bubnik 2021-04-22 11:41:26 +02:00
parent 4f950343c8
commit 38bb7d2950
19 changed files with 139 additions and 161 deletions

View file

@ -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.

View file

@ -270,7 +270,7 @@ std::vector<float> contour_distance2(const EdgeGrid::Grid &grid, const size_t id
const Vec2d v = (segment.second - segment.first).cast<double>();
const Vec2d va = (this->point - segment.first).cast<double>();
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<double>() + t * v;
const Vec2d bisector = foot - this->point.cast<double>();

View file

@ -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>();

View file

@ -55,8 +55,8 @@ static std::vector<coordf_t> 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);
}
}

View file

@ -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<coord_t>());

View file

@ -796,7 +796,7 @@ namespace DoExport {
// get the minimum cross-section used in the print
std::vector<double> 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];

View file

@ -620,7 +620,7 @@ static std::vector<float> contour_distance(const EdgeGrid::Grid &grid,
const Vec2d v = (segment.second - segment.first).cast<double>();
const Vec2d va = (this->point - segment.first).cast<double>();
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<double>() + t * v;
const Vec2d bisector = foot - this->point.cast<double>();

View file

@ -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;

View file

@ -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)

View file

@ -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<double>() + t1 * v1).cast<coord_t>();
Point p2 = (projection_l.a.cast<double>() + t2 * v1).cast<coord_t>();
Point p1 = projection_l.a + (t1 * v1).cast<coord_t>();
Point p2 = projection_l.a + (t2 * v1).cast<coord_t>();
*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
@ -90,37 +90,33 @@ struct PaintedLineVisitor
{
// 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);
const Vec2d v1 = line_to_test.vector().cast<double>();
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<double>().normalized();
const Vec2d v2 = (grid_line.b - grid_line.a).cast<double>().normalized();
double angle = ::acos(clamp(-1.0, 1.0, v1.dot(v2)));
double angle_deg = Geometry::rad2deg(angle);
const Vec2d v2 = grid_line.vector().cast<double>();
// 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);
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);
}
}
}
}
// Continue traversing the grid along the edge.
return true;
}
@ -130,13 +126,15 @@ struct PaintedLineVisitor
Line line_to_test;
std::unordered_set<std::pair<size_t, size_t>, boost::hash<std::pair<size_t, size_t>>> painted_lines_set;
int color = -1;
static inline const double cos_threshold2 = Slic3r::sqr(cos(M_PI * 30. / 180.));
};
static std::vector<ColoredLine> to_colored_lines(const Polygon &polygon, int color)
{
std::vector<ColoredLine> 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<ColoredLine> to_colored_lines(const Polygon &polygon, int col
static Polygon colored_points_to_polygon(const std::vector<ColoredLine> &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<std::vector<ColoredLine>> &lines)
@ -160,7 +159,8 @@ static Polygons colored_points_to_polygon(const std::vector<std::vector<ColoredL
return out;
}
inline std::vector<ColoredLine> to_lines(const std::vector<std::vector<ColoredLine>> &c_lines)
// Flatten the vector of vectors into a vector.
static inline std::vector<ColoredLine> to_lines(const std::vector<std::vector<ColoredLine>> &c_lines)
{
size_t n_lines = 0;
for (const auto &c_line : c_lines)
@ -173,8 +173,7 @@ inline std::vector<ColoredLine> to_lines(const std::vector<std::vector<ColoredLi
}
// Double vertex equal to a coord_t point after conversion to double.
template<typename VertexType>
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<std::pair<Polygon, size_t>> extract_colored_segments(MMU_Grap
Vec2d process_line_vec_n = (process_line.a - process_line.b).cast<double>().normalized();
Vec2d neighbour_line_vec_n = (graph.nodes[arc.to_idx].point - graph.nodes[arc.from_idx].point).cast<double>().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<double>();
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;
@ -1278,7 +1277,7 @@ static inline std::vector<std::vector<ExPolygons>> mmu_segmentation_top_and_bott
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];
const ExPolygons &bottom_expolygon = bottom_layers[layer_idx];
if (bottom_expolygon.empty())
continue;
@ -1301,8 +1300,7 @@ static inline std::vector<std::vector<ExPolygons>> 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<std::vector<ExPolygons>> mmu_segmentation_top_and_bott
triangles_by_color_merged.assign(3, std::vector<ExPolygons>(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<std::vector<ExPolygons>> mmu_segmentation_top_and_bott
}
static std::vector<std::vector<std::pair<ExPolygon, size_t>>> merge_segmented_layers(
const std::vector<std::vector<std::pair<ExPolygon, size_t>>> &segmented_regions, const std::vector<std::vector<ExPolygons>> &top_and_bottom_layers)
const std::vector<std::vector<std::pair<ExPolygon, size_t>>> &segmented_regions, std::vector<std::vector<ExPolygons>> &&top_and_bottom_layers)
{
std::vector<std::vector<std::pair<ExPolygon, size_t>>> segmented_regions_merged(segmented_regions.size());
@ -1344,14 +1339,12 @@ static std::vector<std::vector<std::pair<ExPolygon, size_t>>> merge_segmented_la
for (const std::vector<ExPolygons> &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<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentati
float max_z = std::numeric_limits<float>::lowest();
std::array<Vec3f, 3> 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<std::vector<std::pair<ExPolygon, size_t>>> 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<std::vector<std::pair<ExPolygon, size_t>>> 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<std::vector<std::pair<ExPolygon, size_t>>> 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<std::vector<std::pair<ExPolygon, size_t>>> 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<std::vector<ColoredLine>> color_poly = colorize_polygons(original_polygons, painted_lines_single);
MMU_Graph graph = build_graph(layer_idx, color_poly);
@ -1491,7 +1472,7 @@ std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentati
// return segmented_regions;
std::vector<std::vector<ExPolygons>> top_and_bottom_layers = mmu_segmentation_top_and_bottom_layers(print_object);
std::vector<std::vector<std::pair<ExPolygon, size_t>>> segmented_regions_merged = merge_segmented_layers(segmented_regions, top_and_bottom_layers);
std::vector<std::vector<std::pair<ExPolygon, size_t>>> segmented_regions_merged = merge_segmented_layers(segmented_regions, std::move(top_and_bottom_layers));
return segmented_regions_merged;
}

View file

@ -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<t_layer_height_range, int> &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;
}

View file

@ -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;

View file

@ -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 &region = *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<size_t>(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<DiscoverVerticalShellsCacheEntry> 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<size_t>(0, num_layers, grain_size),
[this, &cache_top_botom_regions](const tbb::blocked_range<size_t>& 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 &region = *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 &region = *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<unsigned int> PrintObject::object_extruders() const
{
std::vector<unsigned int> 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<coordf_t> &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<coordf_t> &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<t_layer_height_range, int> &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<coordf_t> &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<coordf_t> &layer_height_profile)
};
std::vector<SlicedVolume> 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<std::pair<t_layer_height_range, int>> &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<coordf_t> &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<coordf_t> &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<std::vector<std::pair<ExPolygon, size_t>>> 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<coordf_t> &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> expolygons_by_layer = this->slice_modifiers(region_id, slice_zs);
@ -1965,7 +1965,7 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
tbb::blocked_range<size_t>(0, m_layers.size()),
[this, &expolygons_by_layer, region_id](const tbb::blocked_range<size_t>& 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<ExPolygons> PrintObject::slice_region(size_t region_id, const std::vector<float> &z, SlicingMode mode, size_t slicing_mode_normal_below_layer, SlicingMode mode_below) const
{
std::vector<const ModelVolume*> volumes;
if (region_id < this->region_volumes.size()) {
if (region_id < this->num_regions()) {
for (const std::pair<t_layer_height_range, int> &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<ExPolygons> PrintObject::slice_region(size_t region_id, const std::v
std::vector<ExPolygons> PrintObject::slice_modifiers(size_t region_id, const std::vector<float> &slice_zs) const
{
std::vector<ExPolygons> out;
if (region_id < this->region_volumes.size())
if (region_id < this->num_regions())
{
std::vector<std::vector<t_layer_height_range>> volume_ranges;
const std::vector<std::pair<t_layer_height_range, int>> &volumes_and_ranges = this->region_volumes[region_id];
@ -2174,7 +2174,7 @@ std::vector<ExPolygons> PrintObject::slice_modifiers(size_t region_id, const std
} else {
// Some modifier in this region was split to layer spans.
std::vector<char> 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<std::pair<t_layer_height_range, int>> &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.)

View file

@ -298,7 +298,7 @@ std::vector<double> 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<double> smooth_height_profile(const std::vector<double>& 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<int>(0, 255, int(floor(color(0) + 0.5)));
ptr[1] = (unsigned char)clamp<int>(0, 255, int(floor(color(1) + 0.5)));
ptr[2] = (unsigned char)clamp<int>(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<int>(0, 255, int(floor(color(0) + 0.5)));
ptr[1] = (unsigned char)clamp<int>(0, 255, int(floor(color(1) + 0.5)));
ptr[2] = (unsigned char)clamp<int>(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.

View file

@ -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 &region = *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()));

View file

@ -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<Vec2d> 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

View file

@ -239,26 +239,20 @@ template<typename T> inline bool one_of(const T& v, const std::initializer_list<
{ return contains(il, v); }
template<typename T>
static inline T sqr(T x)
constexpr inline T sqr(T x)
{
return x * x;
}
template <typename T>
static inline T clamp(const T low, const T high, const T value)
{
return std::max(low, std::min(high, value));
}
template <typename T, typename Number>
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 <typename Number>
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);
}

View file

@ -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();

View file

@ -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;