diff --git a/src/dev-utils/OrcaSlicer_profile_validator.cpp b/src/dev-utils/OrcaSlicer_profile_validator.cpp index 56acbaa732..557dda7eec 100644 --- a/src/dev-utils/OrcaSlicer_profile_validator.cpp +++ b/src/dev-utils/OrcaSlicer_profile_validator.cpp @@ -122,17 +122,19 @@ Vec2d printable_area_center(const DynamicPrintConfig &cfg) // Put the prime tower where the GUI and CLI would before slicing. The config default (x 15, y 220) // lies off any bed shallower than the tower, and generation rejects an off-plate tower instead of -// exporting it. Beside the centred cube, clear of the edge exclusion strips some beds carry, then -// pulled inside the printable outline by the tower's own estimated footprint, with a few mm of -// clearance so the conflict checker never sees the two touch. -void place_wipe_tower(DynamicPrintConfig &cfg, const Vec2d ¢er) +// exporting it. Beside the cube at the bed centre, clear of the edge exclusion strips some beds +// carry, with a few mm of clearance so the conflict checker never sees the two touch. The cube and +// the tower's estimated footprint are then pulled inside the printable outline as one rigid pair: +// moving the tower alone would push it back onto the cube on a narrow bed. Returns that move for +// the cube. +Vec2d place_wipe_tower(DynamicPrintConfig &cfg, const Vec2d ¢er) { const auto *area = cfg.option("printable_area"); if (area == nullptr || area->values.size() < 3) - return; + return Vec2d::Zero(); const WipeTowerFootprint footprint = estimate_wipe_tower_footprint(cfg, resolve_wipe_tower_type(cfg), {0, 1}, cfg.opt_float("layer_height"), 10.); if (footprint.depth < EPSILON) - return; + return Vec2d::Zero(); const double margin = WIPE_TOWER_MARGIN + footprint.brim_width; // The position is the tower's own origin; a rotated tower extends from it in another // direction, so place the rotated box's extents rather than the origin. @@ -143,13 +145,22 @@ void place_wipe_tower(DynamicPrintConfig &cfg, const Vec2d ¢er) const Vec2d size = unscale(local.max) - lo; Vec2d pos(center.x() + 5. + margin + 5. - lo.x(), center.y() - size.y() / 2. - lo.y()); box.translate(Point::new_scale(pos.x(), pos.y())); - const Vec2f move = WipeTower::move_box_inside_polygon(get_extents(box), Polygons{Polygon::new_scale(area->values)}, scaled(margin)); - pos += move.cast(); + // A bed too small for the pair keeps the cube at its centre and places the tower alone. + const Polygons bed{Polygon::new_scale(area->values)}; + const BoundingBox tower = get_extents(box); + BoundingBox pair = tower; + pair.merge(Point::new_scale(center.x() - 5., center.y() - 5.)); + pair.merge(Point::new_scale(center.x() + 5., center.y() + 5.)); + const Point room = get_extents(bed).size() - Point::new_scale(2. * margin, 2. * margin); + const bool rigid = pair.size().x() < room.x() && pair.size().y() < room.y(); + const Vec2d move = WipeTower::move_box_inside_polygon(rigid ? pair : tower, bed, scaled(margin)).cast(); + pos += move; cfg.option("wipe_tower_x", true)->values = {pos.x()}; cfg.option("wipe_tower_y", true)->values = {pos.y()}; + return rigid ? move : Vec2d::Zero(); } -// Slice one centered cube that switches from filament 1 to filament 2 partway up, so exactly one +// Slice one cube that switches from filament 1 to filament 2 partway up, so exactly one // filament change fires, then export. The change drives the printer's own change_filament_gcode: on a // single-nozzle machine it rides the AMS prime tower (append_tcr), on a multi-nozzle machine it routes // through the nozzle swap (set_extruder / append_tcr2) - the engine picks the path from the printer's @@ -157,10 +168,10 @@ void place_wipe_tower(DynamicPrintConfig &cfg, const Vec2d ¢er) // Slic3r::PlaceholderParserError from export. std::string slice_two_color_cube_and_export(DynamicPrintConfig cfg, bool is_bbl) { - const Vec2d center = printable_area_center(cfg); - place_wipe_tower(cfg, center); + const Vec2d center = printable_area_center(cfg); + const Vec2d cube_min = center - Vec2d(5., 5.) + place_wipe_tower(cfg, center); TriangleMesh m = make_cube(10, 10, 10); - m.translate(float(center.x() - 5.), float(center.y() - 5.), 0.f); + m.translate(static_cast(cube_min.x()), static_cast(cube_min.y()), 0.f); Model model; Print print;