mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-17 05:52:39 +00:00
Belt printers: brim laid onto the tilted belt, with a leading apron
A belt printer slices in a rotated frame, so the belt surface is a tilted
plane rather than the Z=0 bed plane. Each slicing layer touches the belt
only along a narrow strip at its leading edge - about 0.2mm at 45 degrees -
so a part's first layer is really a first line, with almost no contact patch
to hold it down while the belt drags it forward. Brim was hard-disabled on
belt printers, leaving no remedy at all.
Generate the brim on the belt plane instead. The object's belt footprint is
the union over layers of each slice clipped to that layer's contact band; the
brim is offset from it in a "flattened" frame where the shear axis is
stretched by 1/cos(tilt), so ordinary Clipper offsets measure true on-belt
distance. It is emitted as cross-belt lines, one per layer band, anchored to
a fixed fraction of the band so every line shares a nozzle-to-belt clearance
and therefore comes out the same width; flow is matched to the resulting band
pitch, keeping the sheet uniform and gap-free.
Three new controls, all belt-only:
* Leading brim length - extends the brim ahead of the part along the belt,
on every downhill-facing edge of its contact area. This apron necessarily
prints BELOW the object's first layer, since layer 0 is the part's leading
contact, so it needs brim-only bands of its own.
* Extra brim width - widens the brim sideways across the belt only.
* Brim type "Leading edge only" - brim at the part's first belt contact and
nothing after it. Appended last in BrimType so no existing value shifts;
degrades to an outer brim off belt printers, with a warning.
The apron bands are lightweight records rather than a Layer subclass, so no
fabricated Layer::id() can leak into initial-layer temperature selection, the
spiral vase probe, cooling or gradual interpolation. They are generated in
posSupportMaterial because their print_z values must exist before ToolOrdering
is built at psWipeTower, and they are emitted from a short dedicated branch in
process_layer that runs before any layer pointer is dereferenced.
The footprint is closed before offsetting outwards: a belt contact patch is
often a broken-up strip, and the merged offset rings of two islands closer
than 2 x brim_width would otherwise fill the space between them - space that
lies under the part.
Also fixes a pre-existing bug where PrintObject::get_first_layer_bbox()
overwrote a valid bbox with an unassigned one on any belt printer with a brim
configured, because has_brim() was true while make_brim() returned early.
Belt brim is refused alongside the prime tower and spiral vase, and requires
one instance per PrintObject - translating an instance along the belt axis
changes its physical belt-floor Z. Untilted belt printers are unchanged: they
still get no brim, since the plate brim is emitted out of skirt_brim_groups(),
which _make_skirt() never builds for a belt printer.
This commit is contained in:
@@ -969,6 +969,13 @@ void PrintObject::generate_support_material()
|
||||
this->_generate_support_material();
|
||||
m_print->throw_if_canceled();
|
||||
}
|
||||
// Belt brim rides here rather than in the brim step because its apron
|
||||
// prologue introduces print_z values below the object's first layer, and
|
||||
// those must exist before ToolOrdering is built at psWipeTower - one step
|
||||
// ahead of psSkirtBrim. The brim options already invalidate
|
||||
// posSupportMaterial, so this needs no extra invalidation edges.
|
||||
make_belt_brim(*this);
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(trace) << "[BELTRACE] generate_support_material EXIT tid=" << std::this_thread::get_id() << " obj=" << this;
|
||||
this->set_done(posSupportMaterial);
|
||||
} else {
|
||||
@@ -1142,6 +1149,52 @@ void PrintObject::clear_support_layers()
|
||||
l->cantilevers.clear();
|
||||
}
|
||||
}
|
||||
// Belt brim is owned by the same step, so it must die with it or an
|
||||
// invalidate-without-rerun would leave stale bands (and stale prologue Zs)
|
||||
// behind. Unconditional: unlike support layers it is never shared.
|
||||
this->clear_belt_brim();
|
||||
}
|
||||
|
||||
// Belt brim ------------------------------------------------------------------
|
||||
//
|
||||
// The tilt test is answered from the print CONFIG, not from SlicingParameters:
|
||||
// invalidating posSupportMaterial clears m_slicing_params.valid, and this is
|
||||
// queried from Print::process() dispatch, Brim.cpp and the G-code emitter, where
|
||||
// a stale zero shear factor would silently drop the brim. BeltBrim.cpp itself
|
||||
// reads the real belt floor through BeltFloorContext, where the parameters are
|
||||
// guaranteed current.
|
||||
bool PrintObject::has_belt_brim() const
|
||||
{
|
||||
if (! m_print->has_tilted_belt())
|
||||
return false;
|
||||
// Translating an instance along the belt axis changes its physical belt-floor
|
||||
// Z, so one set of bands cannot serve several instances sharing a PrintObject.
|
||||
// belt_force_separate() in PrintApply.cpp gives one instance per object
|
||||
// whenever a global belt flag is set, which the shipped belt profiles do.
|
||||
if (m_instances.size() > 1)
|
||||
return false;
|
||||
if (m_config.brim_type == btNoBrim)
|
||||
return false;
|
||||
if (m_config.brim_width.value <= 0. && m_config.leading_brim_length.value <= 0.
|
||||
&& m_config.extra_brim_width.value <= 0.)
|
||||
return false;
|
||||
return ! this->has_raft();
|
||||
}
|
||||
|
||||
void PrintObject::clear_belt_brim()
|
||||
{
|
||||
m_belt_brim_by_layer.clear();
|
||||
m_belt_brim_areas_by_layer.clear();
|
||||
m_belt_brim_prologue.clear();
|
||||
}
|
||||
|
||||
void PrintObject::set_belt_brim(std::vector<ExtrusionEntityCollection> &&by_layer,
|
||||
std::vector<ExPolygons> &&areas,
|
||||
std::vector<BeltBrimBand> &&prologue)
|
||||
{
|
||||
m_belt_brim_by_layer = std::move(by_layer);
|
||||
m_belt_brim_areas_by_layer = std::move(areas);
|
||||
m_belt_brim_prologue = std::move(prologue);
|
||||
}
|
||||
|
||||
std::shared_ptr<TreeSupportData> PrintObject::alloc_tree_support_preview_cache()
|
||||
@@ -1184,6 +1237,8 @@ bool PrintObject::invalidate_state_by_config_options(
|
||||
bool invalidated = false;
|
||||
for (const t_config_option_key &opt_key : opt_keys) {
|
||||
if ( opt_key == "brim_width"
|
||||
|| opt_key == "leading_brim_length"
|
||||
|| opt_key == "extra_brim_width"
|
||||
|| opt_key == "brim_object_gap"
|
||||
|| opt_key == "brim_use_efc_outline"
|
||||
|| opt_key == "brim_type"
|
||||
|
||||
Reference in New Issue
Block a user