mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-09 18:27:00 +00:00
Size a no-purge tower at the planners' idle depth
Smooth timelapse no longer charges a prime volume it does not purge. A tower printed with no tool change is exactly the idle depth: the stability minimum for Type2, the wrapping detection depth for Type1. Charging a full prime_volume on top made the previewed and arranged tower deeper than the one that is printed. The Type2 half of "a tool change reserves a tower whatever the purge volumes resolve to" arrives with the base commit; here it only has to survive the planner split, since Type1 already reserves per filament. The wipe tower filament only joins the tool ordering when there is a tower to join, which is the has_wipe_tower() half of the guard Print::extruders applies.
This commit is contained in:
@@ -96,12 +96,9 @@ WipeTowerFootprint estimate_wipe_tower_footprint(const ConfigBase &config, WipeT
|
|||||||
// normalize_fdm_2 clearing enable_prime_tower. Its mixed-filament case is not modelled.
|
// normalize_fdm_2 clearing enable_prime_tower. Its mixed-filament case is not modelled.
|
||||||
const bool need_wipe_tower = smooth_timelapse || wrapping;
|
const bool need_wipe_tower = smooth_timelapse || wrapping;
|
||||||
|
|
||||||
// No tool change, nothing to purge; smooth timelapse still primes once.
|
// A tower printed for one of the reasons above has no tool change to purge for; both
|
||||||
size_t purge_count = 0;
|
// planners give it the idle depth below and nothing more.
|
||||||
if (filaments_cnt > 1)
|
const size_t purge_count = filaments_cnt > 1 ? (dual_nozzle ? filaments_cnt : filaments_cnt - 1) : 0;
|
||||||
purge_count = dual_nozzle ? filaments_cnt : filaments_cnt - 1;
|
|
||||||
else if (smooth_timelapse)
|
|
||||||
purge_count = 1;
|
|
||||||
|
|
||||||
// Type2 purges one volume per tool change. Type1 plans per filament below; here the volume
|
// Type2 purges one volume per tool change. Type1 plans per filament below; here the volume
|
||||||
// only decides whether a tower exists.
|
// only decides whether a tower exists.
|
||||||
|
|||||||
@@ -2341,10 +2341,12 @@ WipeTowerFootprint PartPlate::estimate_wipe_tower_footprint(const DynamicPrintCo
|
|||||||
if (std::find(plate_extruders.begin(), plate_extruders.end(), id) == plate_extruders.end())
|
if (std::find(plate_extruders.begin(), plate_extruders.end(), id) == plate_extruders.end())
|
||||||
plate_extruders.push_back(id);
|
plate_extruders.push_back(id);
|
||||||
// The wipe tower filament joins the tool ordering even when unused (Print::extruders), so
|
// The wipe tower filament joins the tool ordering even when unused (Print::extruders), so
|
||||||
// validation counts it.
|
// validation counts it - but only where there is a tower to join, which is the
|
||||||
|
// has_wipe_tower() half of that guard.
|
||||||
const ConfigOption *wipe_tower_filament_opt = config.option("wipe_tower_filament");
|
const ConfigOption *wipe_tower_filament_opt = config.option("wipe_tower_filament");
|
||||||
|
const ConfigOption *enable_prime_tower_opt = config.option("enable_prime_tower");
|
||||||
const int wipe_tower_filament = wipe_tower_filament_opt != nullptr ? wipe_tower_filament_opt->getInt() : 0;
|
const int wipe_tower_filament = wipe_tower_filament_opt != nullptr ? wipe_tower_filament_opt->getInt() : 0;
|
||||||
if (plate_extruders.size() > 1 && wipe_tower_filament > 0 &&
|
if (enable_prime_tower_opt != nullptr && enable_prime_tower_opt->getBool() && plate_extruders.size() > 1 && wipe_tower_filament > 0 &&
|
||||||
std::find(plate_extruders.begin(), plate_extruders.end(), wipe_tower_filament) == plate_extruders.end())
|
std::find(plate_extruders.begin(), plate_extruders.end(), wipe_tower_filament) == plate_extruders.end())
|
||||||
plate_extruders.push_back(wipe_tower_filament);
|
plate_extruders.push_back(wipe_tower_filament);
|
||||||
if (plate_extruders.empty())
|
if (plate_extruders.empty())
|
||||||
|
|||||||
@@ -171,22 +171,28 @@ TEST_CASE("A single filament only gets a tower when one is printed anyway", "[Wi
|
|||||||
config.set_key_value("raft_layers", new ConfigOptionInt(0));
|
config.set_key_value("raft_layers", new ConfigOptionInt(0));
|
||||||
|
|
||||||
config.set_deserialize_strict("timelapse_type", "1");
|
config.set_deserialize_strict("timelapse_type", "1");
|
||||||
// Smooth timelapse primes the single filament once: 10 mm, lifted to the floor.
|
// A tower printed with no tool change is exactly the planner's idle depth: there is
|
||||||
|
// nothing to purge, and WipeTower2 sizes it at the stability floor.
|
||||||
CHECK_THAT(estimate(config, 1, 0.2, 100.).depth, WithinAbs(20., 1e-9));
|
CHECK_THAT(estimate(config, 1, 0.2, 100.).depth, WithinAbs(20., 1e-9));
|
||||||
CHECK_THAT(estimate(config, 1, 0.2, 5.).depth, WithinAbs(10., 1e-9));
|
CHECK_THAT(estimate(config, 1, 0.2, 5.).depth, WithinAbs(WipeTower::get_limit_depth_by_height(5.f), 1e-9));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("A tool change reserves the stability floor even with nothing to purge", "[WipeTowerEstimate]") {
|
TEST_CASE("A tool change reserves a tower even with nothing to purge", "[WipeTowerEstimate]") {
|
||||||
// The purge volumes are configurable down to zero, but the tool changes are still printed on
|
// The purge volumes are configurable down to zero, but the tool changes are still printed
|
||||||
// the tower and the generator still floors it, so the estimate has to floor it too.
|
// on the tower and both planners still floor it - so the estimate has to floor it too.
|
||||||
const double height = GENERATE(5., 100.);
|
// Type1 plans per filament and already reserves one; Type2 has only the volume to go on.
|
||||||
const float floor = WipeTower::get_limit_depth_by_height(float(height));
|
const double height = GENERATE(5., 100.);
|
||||||
DynamicPrintConfig config = make_config(GENERATE("rectangle", "rib"));
|
const float floor = WipeTower::get_limit_depth_by_height(float(height));
|
||||||
|
const char *wall = GENERATE("rectangle", "rib");
|
||||||
|
DynamicPrintConfig config = make_config(wall);
|
||||||
config.set_key_value("prime_volume", new ConfigOptionFloat(0.));
|
config.set_key_value("prime_volume", new ConfigOptionFloat(0.));
|
||||||
|
config.set_key_value("filament_prime_volume", new ConfigOptionFloats({0.}));
|
||||||
|
|
||||||
CHECK(estimate(config, 3, 0.2, height).depth >= floor);
|
CHECK(estimate(config, 3, 0.2, height, WipeTowerType::Type2).depth >= floor);
|
||||||
|
CHECK(estimate(config, 3, 0.2, height, WipeTowerType::Type1).depth >= floor);
|
||||||
// Still nothing for a lone filament with no other reason.
|
// Still nothing for a lone filament with no other reason.
|
||||||
CHECK_THAT(estimate(config, 1, 0.2, height).depth, WithinAbs(0., 1e-9));
|
CHECK_THAT(estimate(config, 1, 0.2, height, WipeTowerType::Type2).depth, WithinAbs(0., 1e-9));
|
||||||
|
CHECK_THAT(estimate(config, 1, 0.2, height, WipeTowerType::Type1).depth, WithinAbs(0., 1e-9));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Both wall types agree on whether there is a tower at all", "[WipeTowerEstimate]") {
|
TEST_CASE("Both wall types agree on whether there is a tower at all", "[WipeTowerEstimate]") {
|
||||||
|
|||||||
Reference in New Issue
Block a user