mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-12-26 17:48:35 -07:00
ENH: dual_extruder: add logic to process extruder_printable_area
JIRA: STUDIO-7498 Change-Id: I1cf53db93acf41b06cb1b9569a0679487c9f1e41 (cherry picked from commit e5be69dedd1ba6dc289a14b89598c9a6101dacb3)
This commit is contained in:
parent
e433e49e2f
commit
f702ad9fd2
20 changed files with 339 additions and 76 deletions
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
BuildVolume::BuildVolume(const std::vector<Vec2d> &printable_area, const double printable_height) : m_bed_shape(printable_area), m_max_print_height(printable_height)
|
||||
BuildVolume::BuildVolume(const std::vector<Vec2d> &printable_area, const double printable_height, const std::vector<std::vector<Vec2d>> &extruder_areas) : m_bed_shape(printable_area), m_max_print_height(printable_height), m_extruder_shapes(extruder_areas)
|
||||
{
|
||||
assert(printable_height >= 0);
|
||||
|
||||
|
|
@ -77,6 +77,69 @@ BuildVolume::BuildVolume(const std::vector<Vec2d> &printable_area, const double
|
|||
m_top_bottom_convex_hull_decomposition_bed = convex_decomposition(m_convex_hull, BedEpsilon);
|
||||
}
|
||||
|
||||
if (m_extruder_shapes.size() > 0)
|
||||
{
|
||||
for (unsigned int index = 0; index < m_extruder_shapes.size(); index++)
|
||||
{
|
||||
std::vector<Vec2d>& extruder_shape = m_extruder_shapes[index];
|
||||
BuildExtruderVolume extruder_volume;
|
||||
|
||||
if (extruder_shape == printable_area) {
|
||||
extruder_volume.same_with_bed = true;
|
||||
extruder_volume.type = m_type;
|
||||
extruder_volume.bbox = m_bbox;
|
||||
extruder_volume.bboxf = m_bboxf;
|
||||
extruder_volume.circle = m_circle;
|
||||
}
|
||||
else {
|
||||
Polygon poly = Polygon::new_scale(extruder_shape);
|
||||
|
||||
double poly_area = poly.area();
|
||||
extruder_volume.bbox = get_extents(poly);
|
||||
BoundingBoxf temp_bboxf = get_extents(extruder_shape);
|
||||
extruder_volume.bboxf = BoundingBoxf3{ to_3d(temp_bboxf.min, 0.), to_3d(temp_bboxf.max, printable_height) };
|
||||
|
||||
if (extruder_shape.size() >= 4 && std::abs((poly_area - double(extruder_volume.bbox.size().x()) * double(extruder_volume.bbox.size().y()))) < sqr(SCALED_EPSILON))
|
||||
{
|
||||
extruder_volume.type = Type::Rectangle;
|
||||
extruder_volume.circle.center = 0.5 * (extruder_volume.bbox.min.cast<double>() + extruder_volume.bbox.max.cast<double>());
|
||||
extruder_volume.circle.radius = 0.5 * extruder_volume.bbox.size().cast<double>().norm();
|
||||
}
|
||||
else if (extruder_shape.size() > 3) {
|
||||
extruder_volume.circle = Geometry::circle_ransac(extruder_shape);
|
||||
bool is_circle = true;
|
||||
|
||||
Vec2d prev = extruder_shape.back();
|
||||
for (const Vec2d &p : extruder_shape) {
|
||||
if (// Polygon vertices must lie very close the circle.
|
||||
std::abs((p - extruder_volume.circle.center).norm() - extruder_volume.circle.radius) > 0.005 ||
|
||||
// Midpoints of polygon edges must not undercat more than 3mm. This corresponds to 72 edges per circle generated by BedShapePanel::update_shape().
|
||||
extruder_volume.circle.radius - (0.5 * (prev + p) -extruder_volume.circle.center).norm() > 3.) {
|
||||
is_circle = false;
|
||||
break;
|
||||
}
|
||||
prev = p;
|
||||
}
|
||||
if (is_circle) {
|
||||
extruder_volume.type = Type::Circle;
|
||||
extruder_volume.circle.center = scaled<double>(extruder_volume.circle.center);
|
||||
extruder_volume.circle.radius = scaled<double>(extruder_volume.circle.radius);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_type == Type::Invalid) {
|
||||
//not supported currently, use the same as bed
|
||||
extruder_volume.same_with_bed = true;
|
||||
extruder_volume.type = m_type;
|
||||
extruder_volume.bbox = m_bbox;
|
||||
extruder_volume.bboxf = m_bboxf;
|
||||
extruder_volume.circle = m_circle;
|
||||
}
|
||||
m_extruder_volumes.push_back(std::move(extruder_volume));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "BuildVolume printable_area clasified as: " << this->type_name();
|
||||
}
|
||||
|
||||
|
|
@ -197,7 +260,7 @@ BuildVolume::ObjectState object_state_templ(const indexed_triangle_set &its, con
|
|||
bool outside = false;
|
||||
static constexpr const auto world_min_z = float(-BuildVolume::SceneEpsilon);
|
||||
|
||||
if (may_be_below_bed)
|
||||
if (may_be_below_bed)
|
||||
{
|
||||
// Slower test, needs to clip the object edges with the print bed plane.
|
||||
// 1) Allocate transformed vertices with their position with respect to print bed surface.
|
||||
|
|
@ -260,7 +323,7 @@ BuildVolume::ObjectState object_state_templ(const indexed_triangle_set &its, con
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
// Much simpler and faster code, not clipping the object with the print bed.
|
||||
assert(! may_be_below_bed);
|
||||
|
|
@ -297,14 +360,14 @@ BuildVolume::ObjectState BuildVolume::object_state(const indexed_triangle_set& i
|
|||
case BuildVolume_Type::Circle:
|
||||
{
|
||||
Geometry::Circlef circle { unscaled<float>(m_circle.center), unscaled<float>(m_circle.radius + SceneEpsilon) };
|
||||
return m_max_print_height == 0.0 ?
|
||||
return m_max_print_height == 0.0 ?
|
||||
object_state_templ(its, trafo, may_be_below_bed, true, [circle](const Vec3f& pt) { return circle.contains(to_2d(pt)); }) :
|
||||
object_state_templ(its, trafo, may_be_below_bed, true, [circle, z = m_max_print_height + SceneEpsilon](const Vec3f &pt) { return pt.z() < z && circle.contains(to_2d(pt)); });
|
||||
}
|
||||
case BuildVolume_Type::Convex:
|
||||
//FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently.
|
||||
case BuildVolume_Type::Custom:
|
||||
return m_max_print_height == 0.0 ?
|
||||
return m_max_print_height == 0.0 ?
|
||||
object_state_templ(its, trafo, may_be_below_bed, m_type == BuildVolume_Type::Convex, [this](const Vec3f &pt) { return Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_scene, to_2d(pt).cast<double>()); }) :
|
||||
object_state_templ(its, trafo, may_be_below_bed, m_type == BuildVolume_Type::Convex, [this, z = m_max_print_height + SceneEpsilon](const Vec3f &pt) { return pt.z() < z && Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_scene, to_2d(pt).cast<double>()); });
|
||||
case BuildVolume_Type::Invalid:
|
||||
|
|
@ -322,10 +385,100 @@ BuildVolume::ObjectState BuildVolume::volume_state_bbox(const BoundingBoxf3& vol
|
|||
if (ignore_bottom)
|
||||
build_volume.min.z() = -std::numeric_limits<double>::max();
|
||||
return build_volume.max.z() <= - SceneEpsilon ? ObjectState::Below :
|
||||
build_volume.contains(volume_bbox) ? ObjectState::Inside :
|
||||
build_volume.contains(volume_bbox) ? ObjectState::Inside :
|
||||
build_volume.intersects(volume_bbox) ? ObjectState::Colliding : ObjectState::Outside;
|
||||
}
|
||||
|
||||
const BuildVolume::BuildExtruderVolume& BuildVolume::get_extruder_area_volume(int index) const
|
||||
{
|
||||
assert(index >= 0 && index < m_extruder_volumes.size());
|
||||
return m_extruder_volumes[index];
|
||||
}
|
||||
|
||||
BuildVolume::ObjectState BuildVolume::check_object_state_with_extruder_area(const indexed_triangle_set &its, const Transform3f &trafo, int index) const
|
||||
{
|
||||
const BuildExtruderVolume& extruder_volume = get_extruder_area_volume(index);
|
||||
ObjectState return_state = ObjectState::Inside;
|
||||
|
||||
if (!extruder_volume.same_with_bed) {
|
||||
switch (extruder_volume.type) {
|
||||
case Type::Rectangle:
|
||||
{
|
||||
BoundingBox3Base<Vec3d> build_volume = extruder_volume.bboxf.inflated(SceneEpsilon);
|
||||
if (m_max_print_height == 0.0)
|
||||
build_volume.max.z() = std::numeric_limits<double>::max();
|
||||
BoundingBox3Base<Vec3f> build_volumef(build_volume.min.cast<float>(), build_volume.max.cast<float>());
|
||||
|
||||
return_state = object_state_templ(its, trafo, false, [build_volumef](const Vec3f &pt) { return build_volumef.contains(pt); });
|
||||
break;
|
||||
}
|
||||
case Type::Circle:
|
||||
{
|
||||
Geometry::Circlef circle { unscaled<float>(extruder_volume.circle.center), unscaled<float>(extruder_volume.circle.radius + SceneEpsilon) };
|
||||
return_state = (m_max_print_height == 0.0) ?
|
||||
object_state_templ(its, trafo, false, [circle](const Vec3f &pt) { return circle.contains(to_2d(pt)); }) :
|
||||
object_state_templ(its, trafo, false, [circle, z = m_max_print_height + SceneEpsilon](const Vec3f &pt) { return pt.z() < z && circle.contains(to_2d(pt)); });
|
||||
break;
|
||||
}
|
||||
case Type::Invalid:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (return_state != ObjectState::Inside)
|
||||
return_state = ObjectState::Limited;
|
||||
|
||||
return return_state;
|
||||
}
|
||||
|
||||
BuildVolume::ObjectState BuildVolume::check_object_state_with_extruder_areas(const indexed_triangle_set &its, const Transform3f &trafo, std::vector<bool>& inside_extruders) const
|
||||
{
|
||||
ObjectState result = ObjectState::Inside;
|
||||
int extruder_area_count = get_extruder_area_count();
|
||||
inside_extruders.resize(extruder_area_count, true);
|
||||
for (int index = 0; index < extruder_area_count; index++)
|
||||
{
|
||||
ObjectState state = check_object_state_with_extruder_area(its, trafo, index);
|
||||
|
||||
if (state == ObjectState::Limited) {
|
||||
inside_extruders[index] = false;
|
||||
result = ObjectState::Limited;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BuildVolume::ObjectState BuildVolume::check_volume_bbox_state_with_extruder_area(const BoundingBoxf3& volume_bbox, int index) const
|
||||
{
|
||||
const BuildExtruderVolume& extruder_volume = get_extruder_area_volume(index);
|
||||
|
||||
if (extruder_volume.same_with_bed || extruder_volume.bboxf.contains(volume_bbox))
|
||||
return ObjectState::Inside;
|
||||
else
|
||||
return ObjectState::Limited;
|
||||
}
|
||||
|
||||
BuildVolume::ObjectState BuildVolume::check_volume_bbox_state_with_extruder_areas(const BoundingBoxf3& volume_bbox, std::vector<bool>& inside_extruders) const
|
||||
{
|
||||
ObjectState result = ObjectState::Inside;
|
||||
int extruder_area_count = get_extruder_area_count();
|
||||
inside_extruders.resize(extruder_area_count, true);
|
||||
for (int index = 0; index < extruder_area_count; index++)
|
||||
{
|
||||
ObjectState state = check_volume_bbox_state_with_extruder_area(volume_bbox, index);
|
||||
|
||||
if (state == ObjectState::Limited) {
|
||||
inside_extruders[index] = false;
|
||||
result = ObjectState::Limited;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool BuildVolume::all_paths_inside(const GCodeProcessorResult& paths, const BoundingBoxf3& paths_bbox, bool ignore_bottom) const
|
||||
{
|
||||
auto move_valid = [](const GCodeProcessorResult::MoveVertex &move) {
|
||||
|
|
@ -348,7 +501,7 @@ bool BuildVolume::all_paths_inside(const GCodeProcessorResult& paths, const Boun
|
|||
const Vec2f c = unscaled<float>(m_circle.center);
|
||||
const float r = unscaled<double>(m_circle.radius) + epsilon;
|
||||
const float r2 = sqr(r);
|
||||
return m_max_print_height == 0.0 ?
|
||||
return m_max_print_height == 0.0 ?
|
||||
std::all_of(paths.moves.begin(), paths.moves.end(), [move_valid, c, r2](const GCodeProcessorResult::MoveVertex &move)
|
||||
{ return ! move_valid(move) || (to_2d(move.position) - c).squaredNorm() <= r2; }) :
|
||||
std::all_of(paths.moves.begin(), paths.moves.end(), [move_valid, c, r2, z = m_max_print_height + epsilon](const GCodeProcessorResult::MoveVertex& move)
|
||||
|
|
@ -358,7 +511,7 @@ bool BuildVolume::all_paths_inside(const GCodeProcessorResult& paths, const Boun
|
|||
//FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently.
|
||||
case BuildVolume_Type::Custom:
|
||||
return m_max_print_height == 0.0 ?
|
||||
std::all_of(paths.moves.begin(), paths.moves.end(), [move_valid, this](const GCodeProcessorResult::MoveVertex &move)
|
||||
std::all_of(paths.moves.begin(), paths.moves.end(), [move_valid, this](const GCodeProcessorResult::MoveVertex &move)
|
||||
{ return ! move_valid(move) || Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_bed, to_2d(move.position).cast<double>()); }) :
|
||||
std::all_of(paths.moves.begin(), paths.moves.end(), [move_valid, this, z = m_max_print_height + epsilon](const GCodeProcessorResult::MoveVertex &move)
|
||||
{ return ! move_valid(move) || (Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_bed, to_2d(move.position).cast<double>()) && move.position.z() <= z); });
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue