ENH: dual_extruder: add logic to process extruder_printable_area

JIRA: STUDIO-7498
Change-Id: I1cf53db93acf41b06cb1b9569a0679487c9f1e41
This commit is contained in:
lane.wei 2024-08-30 21:13:16 +08:00
parent 2ebd14667e
commit e5be69dedd
20 changed files with 341 additions and 76 deletions

View File

@ -3356,6 +3356,7 @@ int CLI::run(int argc, char **argv)
//use Pointfs insteadof Points
Pointfs current_printable_area = m_print_config.opt<ConfigOptionPoints>("printable_area")->values;
Pointfs current_exclude_area = m_print_config.opt<ConfigOptionPoints>("bed_exclude_area")->values;
std::vector<Pointfs> current_extruder_areas;
//update part plate's size
double print_height = m_print_config.opt_float("printable_height");
double height_to_lid = m_print_config.opt_float("extruder_clearance_height_to_lid");
@ -3364,6 +3365,9 @@ int CLI::run(int argc, char **argv)
//double plate_stride;
std::string bed_texture;
if (m_print_config.opt<ConfigOptionPointsGroups>("extruder_printable_area")) {
current_extruder_areas = m_print_config.opt<ConfigOptionPointsGroups>("extruder_printable_area")->values;
}
current_printable_width = current_printable_area[2].x() - current_printable_area[0].x();
current_printable_depth = current_printable_area[2].y() - current_printable_area[0].y();
current_printable_height = print_height;
@ -3414,7 +3418,7 @@ int CLI::run(int argc, char **argv)
else {
partplate_list.reset_size(old_printable_width, old_printable_depth, old_printable_height, false);
}
partplate_list.set_shapes(current_printable_area, current_exclude_area, bed_texture, height_to_lid, height_to_rod);
partplate_list.set_shapes(current_printable_area, current_exclude_area, current_extruder_areas, bed_texture, height_to_lid, height_to_rod);
//plate_stride = partplate_list.plate_stride_x();
}
@ -5324,7 +5328,7 @@ int CLI::run(int argc, char **argv)
BOOST_LOG_TRIVIAL(info) << boost::format("print_volume {%1%,%2%,%3%}->{%4%, %5%, %6%}") % print_volume.min(0) % print_volume.min(1)
% print_volume.min(2) % print_volume.max(0) % print_volume.max(1) % print_volume.max(2) << std::endl;
#else
BuildVolume build_volume(part_plate->get_shape(), print_height);
BuildVolume build_volume(part_plate->get_shape(), print_height, part_plate->get_extruder_areas());
//model.update_print_volume_state(build_volume);
unsigned int count = model.update_print_volume_state(build_volume);

View File

@ -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);
@ -76,6 +76,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();
}
@ -196,7 +259,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.
@ -252,7 +315,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);
@ -289,14 +352,14 @@ BuildVolume::ObjectState BuildVolume::object_state(const indexed_triangle_set& i
case 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, [circle](const Vec3f &pt) { return circle.contains(to_2d(pt)); }) :
object_state_templ(its, trafo, may_be_below_bed, [circle, z = m_max_print_height + SceneEpsilon](const Vec3f &pt) { return pt.z() < z && circle.contains(to_2d(pt)); });
}
case Type::Convex:
//FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently.
case 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, [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, [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 Type::Invalid:
@ -314,10 +377,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) {
@ -340,7 +493,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)
@ -350,7 +503,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 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); });

View File

@ -31,15 +31,24 @@ public:
Custom
};
struct BuildExtruderVolume {
bool same_with_bed{false};
Type type{Type::Invalid};
BoundingBox bbox;
BoundingBoxf3 bboxf;
Geometry::Circled circle;
};
// Initialized to empty, all zeros, Invalid.
BuildVolume() {}
// Initialize from PrintConfig::printable_area and PrintConfig::printable_height
BuildVolume(const std::vector<Vec2d> &printable_area, const double printable_height);
BuildVolume(const std::vector<Vec2d> &printable_area, const double printable_height, const std::vector<std::vector<Vec2d>> &extruder_areas);
// Source data, unscaled coordinates.
const std::vector<Vec2d>& printable_area() const { return m_bed_shape; }
double printable_height() const { return m_max_print_height; }
const std::vector<std::vector<Vec2d>>& extruder_areas() const { return m_extruder_shapes; }
// Derived data
Type type() const { return m_type; }
// Format the type for console output.
@ -70,9 +79,11 @@ public:
Colliding,
// Outside of the build volume means the object is ignored: Not printed and no error is shown.
Outside,
// Completely below the print bed. The same as Outside, but an object with one printable part below the print bed
// Completely below the print bed. The same as Outside, but an object with one printable part below the print bed
// and at least one part above the print bed is still printable.
Below,
//in Limited area
Limited
};
// 1) Tests called on the plater.
@ -95,9 +106,19 @@ public:
// Called on initial G-code preview on OpenGL vertex buffer interleaved normals and vertices.
bool all_paths_inside_vertices_and_normals_interleaved(const std::vector<float>& paths, const Eigen::AlignedBox<float, 3>& bbox, bool ignore_bottom = true) const;
int get_extruder_area_count() const { return m_extruder_volumes.size(); }
const BuildExtruderVolume& get_extruder_area_volume(int index) const;
ObjectState check_object_state_with_extruder_area(const indexed_triangle_set &its, const Transform3f &trafo, int index) const;
ObjectState check_object_state_with_extruder_areas(const indexed_triangle_set &its, const Transform3f &trafo, std::vector<bool>& inside_extruders) const;
ObjectState check_volume_bbox_state_with_extruder_area(const BoundingBoxf3& volume_bbox, int index) const;
ObjectState check_volume_bbox_state_with_extruder_areas(const BoundingBoxf3& volume_bbox, std::vector<bool>& inside_extruders) const;
private:
// Source definition of the print bed geometry (PrintConfig::printable_area)
std::vector<Vec2d> m_bed_shape;
//BBS: extruder shapes
std::vector<std::vector<Vec2d>> m_extruder_shapes;
std::vector<BuildExtruderVolume> m_extruder_volumes;
// Source definition of the print volume height (PrintConfig::printable_height)
double m_max_print_height { 0.f };

View File

@ -199,6 +199,7 @@ namespace Slic3r {
Pointfs printable_area;
//BBS: add bed exclude area
Pointfs bed_exclude_area;
std::vector<Pointfs> extruder_areas;
//BBS: add toolpath_outside
bool toolpath_outside;
//BBS: add object_label_enabled

View File

@ -2830,7 +2830,23 @@ unsigned int ModelObject::update_instances_print_volume_state(const BuildVolume
}
const Transform3d matrix = model_instance->get_matrix() * vol->get_matrix();
BuildVolume::ObjectState state = build_volume.object_state(vol->mesh().its, matrix.cast<float>(), true /* may be below print bed */);
BuildVolume::ObjectState state;
switch(build_volume.type())
{
case BuildVolume::Type::Rectangle:
{
BoundingBoxf3 transformed_bb = bb.transformed(matrix);
state = build_volume.volume_state_bbox(transformed_bb);
break;
}
case BuildVolume::Type::Circle:
case BuildVolume::Type::Convex:
case BuildVolume::Type::Custom:
default:
state = build_volume.object_state(vol->mesh().its, matrix.cast<float>(), true /* may be below print bed */);
break;
}
if (state == BuildVolume::ObjectState::Inside)
// Volume is completely inside.
inside_outside |= INSIDE;

View File

@ -1264,6 +1264,7 @@ inline const ModelVolume* model_volume_find_by_id(const ModelVolumePtrs &model_v
enum ModelInstanceEPrintVolumeState : unsigned char
{
ModelInstancePVS_Inside,
ModelInstancePVS_Limited,
ModelInstancePVS_Partly_Outside,
ModelInstancePVS_Fully_Outside,
ModelInstanceNum_BedStates

View File

@ -4817,7 +4817,7 @@ void generate_tree_support_3D(PrintObject &print_object, TreeSupport* tree_suppo
Points bedpts = tree_support->m_machine_border.contour.points;
Pointfs bedptsf;
std::transform(bedpts.begin(), bedpts.end(), std::back_inserter(bedptsf), [](const Point &p) { return unscale(p); });
BuildVolume build_volume{ bedptsf, tree_support->m_print_config->printable_height };
BuildVolume build_volume{ bedptsf, tree_support->m_print_config->printable_height, {}};
TreeSupport3D::generate_support_areas(*print_object.print(), tree_support, build_volume, { idx }, throw_on_cancel);
}

View File

@ -189,7 +189,7 @@ void Bed3D::Axes::render() const
}
//BBS: add part plate logic
bool Bed3D::set_shape(const Pointfs& printable_area, const double printable_height, const std::string& custom_model, bool force_as_custom,
bool Bed3D::set_shape(const Pointfs& printable_area, const double printable_height, std::vector<Pointfs> extruder_areas, const std::string& custom_model, bool force_as_custom,
const Vec2d position, bool with_reset)
{
/*auto check_texture = [](const std::string& texture) {
@ -227,7 +227,7 @@ bool Bed3D::set_shape(const Pointfs& printable_area, const double printable_heig
}
//BBS: add position related logic
if (m_bed_shape == printable_area && m_build_volume.printable_height() == printable_height && m_type == type && m_model_filename == model_filename && position == m_position)
if (m_bed_shape == printable_area && m_build_volume.printable_height() == printable_height && m_type == type && m_model_filename == model_filename && position == m_position && m_extruder_shapes == extruder_areas)
// No change, no need to update the UI.
return false;
@ -235,16 +235,26 @@ bool Bed3D::set_shape(const Pointfs& printable_area, const double printable_heig
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":current position {%1%,%2%}, new position {%3%, %4%}") % m_position.x() % m_position.y() % position.x() % position.y();
m_position = position;
m_bed_shape = printable_area;
m_extruder_shapes = extruder_areas;
if ((position(0) != 0) || (position(1) != 0)) {
Pointfs new_bed_shape;
for (const Vec2d& p : m_bed_shape) {
Vec2d point(p(0) + m_position.x(), p(1) + m_position.y());
new_bed_shape.push_back(point);
}
m_build_volume = BuildVolume { new_bed_shape, printable_height };
std::vector<Pointfs> new_extruder_shapes;
for (const std::vector<Vec2d>& shape : m_extruder_shapes) {
std::vector<Vec2d> new_extruder_shape;
for (const Vec2d& p : shape) {
Vec2d point(p(0) + m_position.x(), p(1) + m_position.y());
new_extruder_shape.push_back(point);
}
new_extruder_shapes.push_back(new_extruder_shape);
}
m_build_volume = BuildVolume { new_bed_shape, printable_height, new_extruder_shapes };
}
else
m_build_volume = BuildVolume { printable_area, printable_height };
m_build_volume = BuildVolume { printable_area, printable_height, m_extruder_shapes };
m_type = type;
//m_texture_filename = texture_filename;
m_model_filename = model_filename;
@ -293,7 +303,7 @@ bool Bed3D::set_shape(const Pointfs& printable_area, const double printable_heig
//BBS: add api to set position for partplate related bed
void Bed3D::set_position(Vec2d& position)
{
set_shape(m_bed_shape, m_build_volume.printable_height(), m_model_filename, false, position, false);
set_shape(m_bed_shape, m_build_volume.printable_height(), m_extruder_shapes, m_model_filename, false, position, false);
}
void Bed3D::set_axes_mode(bool origin)

View File

@ -105,6 +105,7 @@ private:
//BBS: add part plate related logic
Vec2d m_position{ Vec2d::Zero() };
std::vector<Vec2d> m_bed_shape;
std::vector<std::vector<Vec2d>> m_extruder_shapes;
bool m_is_dark = false;
public:
@ -116,7 +117,7 @@ public:
//FIXME if the build volume max print height is updated, this function still returns zero
// as this class does not use it, thus there is no need to update the UI.
// BBS
bool set_shape(const Pointfs& printable_area, const double printable_height, const std::string& custom_model, bool force_as_custom = false,
bool set_shape(const Pointfs& printable_area, const double printable_height, std::vector<Pointfs> extruder_areas, const std::string& custom_model, bool force_as_custom = false,
const Vec2d position = Vec2d::Zero(), bool with_reset = true);
void set_position(Vec2d& position);

View File

@ -1709,15 +1709,15 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
auto volume_convex_mesh = [volume_sinking, &model](GLVolume& volume) -> const TriangleMesh&
{ return volume_sinking(volume) ? model.objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh() : *volume.convex_hull(); };
ModelInstanceEPrintVolumeState overall_state = ModelInstancePVS_Inside;
ModelInstanceEPrintVolumeState overall_state = ModelInstancePVS_Fully_Outside;
bool contained_min_one = false;
//BBS: add instance judge logic, besides to original volume judge logic
std::map<int64_t, ModelInstanceEPrintVolumeState> model_state;
//std::map<int64_t, ModelInstanceEPrintVolumeState> model_state;
GUI::PartPlate* curr_plate = GUI::wxGetApp().plater()->get_partplate_list().get_selected_plate();
const Pointfs& pp_bed_shape = curr_plate->get_shape();
BuildVolume plate_build_volume(pp_bed_shape, build_volume.printable_height());
BuildVolume plate_build_volume(pp_bed_shape, build_volume.printable_height(), build_volume.extruder_areas());
const std::vector<BoundingBoxf3>& exclude_areas = curr_plate->get_exclude_areas();
for (GLVolume* volume : this->volumes)
@ -1732,13 +1732,27 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
case BuildVolume::Type::Rectangle:
//FIXME this test does not evaluate collision of a build volume bounding box with non-convex objects.
state = plate_build_volume.volume_state_bbox(bb);
if ((state == BuildVolume::ObjectState::Inside) && (build_volume.get_extruder_area_count() > 0))
{
std::vector<bool> inside_extruders;
state = plate_build_volume.check_volume_bbox_state_with_extruder_areas(bb, inside_extruders);
}
break;
case BuildVolume::Type::Circle:
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:
state = plate_build_volume.object_state(volume_convex_mesh(*volume).its, volume->world_matrix().cast<float>(), volume_sinking(*volume));
{
const indexed_triangle_set& convex_mesh_it = volume_convex_mesh(*volume).its;
const Transform3f trafo = volume->world_matrix().cast<float>();
state = plate_build_volume.object_state(convex_mesh_it, trafo, volume_sinking(*volume));
if ((state == BuildVolume::ObjectState::Inside) && (build_volume.get_extruder_area_count() > 0))
{
std::vector<bool> inside_extruders;
state = plate_build_volume.check_object_state_with_extruder_areas(convex_mesh_it, trafo, inside_extruders);
}
break;
}
default:
// Ignore, don't produce any collision.
state = BuildVolume::ObjectState::Inside;
@ -1747,22 +1761,23 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
assert(state != BuildVolume::ObjectState::Below);
}
int64_t comp_id = ((int64_t)volume->composite_id.object_id << 32) | ((int64_t)volume->composite_id.instance_id);
volume->is_outside = state != BuildVolume::ObjectState::Inside;
//volume->partly_inside = (state == BuildVolume::ObjectState::Colliding);
//int64_t comp_id = ((int64_t)volume->composite_id.object_id << 32) | ((int64_t)volume->composite_id.instance_id);
volume->is_outside = (state != BuildVolume::ObjectState::Inside && state != BuildVolume::ObjectState::Limited);
volume->partly_inside = (state == BuildVolume::ObjectState::Colliding);
if (volume->printable) {
if (overall_state == ModelInstancePVS_Inside && volume->is_outside) {
overall_state = ModelInstancePVS_Fully_Outside;
}
if (overall_state == ModelInstancePVS_Fully_Outside && volume->is_outside && (state == BuildVolume::ObjectState::Colliding))
if (state == BuildVolume::ObjectState::Colliding)
{
overall_state = ModelInstancePVS_Partly_Outside;
}
else if ((state == BuildVolume::ObjectState::Limited) && (overall_state != ModelInstancePVS_Partly_Outside))
overall_state = ModelInstancePVS_Limited;
else if ((state == BuildVolume::ObjectState::Inside) && (overall_state == ModelInstancePVS_Fully_Outside)) {
overall_state = ModelInstancePVS_Fully_Outside;
}
contained_min_one |= !volume->is_outside;
}
ModelInstanceEPrintVolumeState volume_state;
/*ModelInstanceEPrintVolumeState volume_state;
//if (volume->is_outside && (plate_build_volume.bounding_volume().intersects(volume->bounding_box())))
if (volume->is_outside && (state == BuildVolume::ObjectState::Colliding))
volume_state = ModelInstancePVS_Partly_Outside;
@ -1791,11 +1806,11 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
if (model_state[comp_id] == ModelInstancePVS_Partly_Outside) {
overall_state = ModelInstancePVS_Partly_Outside;
BOOST_LOG_TRIVIAL(debug) << "instance includes " << volume->name << " is partially outside of bed";
}
}*/
}
}
for (GLVolume* volume : this->volumes)
/*for (GLVolume* volume : this->volumes)
{
if (! volume->is_modifier && (volume->shader_outside_printer_detection_enabled || (! volume->is_wipe_tower && volume->composite_id.volume_id >= 0)))
{
@ -1809,7 +1824,7 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
volume->partly_inside = false;
}
}
}
}*/
if (out_state != nullptr)
*out_state = overall_state;

View File

@ -2,7 +2,7 @@
#include "GUI_App.hpp"
#include "OptionsGroup.hpp"
#include <wx/wx.h>
#include <wx/wx.h>
#include <wx/numformatter.h>
#include <wx/sizer.h>
#include <wx/statbox.h>
@ -22,7 +22,7 @@ namespace GUI {
BedShape::BedShape(const ConfigOptionPoints& points)
{
m_build_volume = { points.values, 0. };
m_build_volume = { points.values, 0.f, {} };
}
static std::string get_option_label(BedShape::Parameter param)
@ -259,7 +259,7 @@ ConfigOptionsGroupShp BedShapePanel::init_shape_options_page(const wxString& tit
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
update_shape();
};
m_optgroups.push_back(optgroup);
// panel->SetSizerAndFit(optgroup->sizer);
m_shape_options_book->AddPage(panel, title);
@ -503,7 +503,7 @@ void BedShapePanel::update_shape()
auto dx = rect_origin(0);
auto dy = rect_origin(1);
if (dx >= x || dy >= y) {
if (dx >= x || dy >= y) {
m_is_valid = false;
return;
}
@ -521,7 +521,7 @@ void BedShapePanel::update_shape()
{
double diameter;
try { diameter = boost::any_cast<double>(opt_group->get_value("diameter")); }
catch (const std::exception & /* e */) { return; }
catch (const std::exception & /* e */) { return; }
if (diameter == 0.0) return ;
auto r = diameter / 2;

View File

@ -1059,6 +1059,7 @@ void GCodeViewer::load(const GCodeProcessorResult& gcode_result, const Print& pr
Pointfs printable_area;
//BBS: add bed exclude area
Pointfs bed_exclude_area = Pointfs();
std::vector<Pointfs> extruder_areas;
std::string texture;
std::string model;
@ -1078,7 +1079,10 @@ void GCodeViewer::load(const GCodeProcessorResult& gcode_result, const Print& pr
if (!gcode_result.bed_exclude_area.empty())
bed_exclude_area = gcode_result.bed_exclude_area;
wxGetApp().plater()->set_bed_shape(printable_area, bed_exclude_area, gcode_result.printable_height, texture, model, gcode_result.printable_area.empty());
if (!gcode_result.extruder_areas.empty())
extruder_areas = gcode_result.extruder_areas;
wxGetApp().plater()->set_bed_shape(printable_area, bed_exclude_area, gcode_result.printable_height, extruder_areas, texture, model, gcode_result.printable_area.empty());
}
/*else {
// adjust printbed size in dependence of toolpaths bbox

View File

@ -2816,8 +2816,10 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
const bool contained_min_one = m_volumes.check_outside_state(m_bed.build_volume(), &state);
const bool partlyOut = (state == ModelInstanceEPrintVolumeState::ModelInstancePVS_Partly_Outside);
const bool fullyOut = (state == ModelInstanceEPrintVolumeState::ModelInstancePVS_Fully_Outside);
const bool objectLimited = (state == ModelInstanceEPrintVolumeState::ModelInstancePVS_Limited);
_set_warning_notification(EWarning::ObjectClashed, partlyOut);
_set_warning_notification(EWarning::ObjectLimited, objectLimited);
//BBS: turn off the warning when fully outside
//_set_warning_notification(EWarning::ObjectOutside, fullyOut);
if (printer_technology != ptSLA || !contained_min_one)
@ -2829,6 +2831,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
else {
_set_warning_notification(EWarning::ObjectOutside, false);
_set_warning_notification(EWarning::ObjectClashed, false);
_set_warning_notification(EWarning::ObjectLimited, false);
_set_warning_notification(EWarning::SlaSupportsOutside, false);
post_event(Event<bool>(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, false));
}
@ -9576,6 +9579,11 @@ std::vector<std::array<float, 4>> GLCanvas3D::_parse_colors(const std::vector<st
return output;
}
std::string object_limited_text = _u8L("An object is laid on the left/right extruder only area.\n"
"Please make sure the filaments used by this object on this area are not mapped to the other extruders.");
std::string object_clashed_text = _u8L("An object is laid over the boundary of plate or exceeds the height limit.\n"
"Please solve the problem by moving it totally on or off the plate, and confirming that the height is within the build volume.");
void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
{
enum ErrorType{
@ -9612,8 +9620,7 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
case EWarning::SlaSupportsOutside: text = ("SLA supports outside the print area were detected."); error = ErrorType::PLATER_ERROR; break;
case EWarning::SomethingNotShown: text = _u8L("Only the object being edited is visible."); break;
case EWarning::ObjectClashed:
text = _u8L("An object is laid over the boundary of plate or exceeds the height limit.\n"
"Please solve the problem by moving it totally on or off the plate, and confirming that the height is within the build volume.");
text = object_clashed_text;
error = ErrorType::PLATER_ERROR;
break;
case EWarning::FilamentUnPrintableOnFirstLayer: {
@ -9627,6 +9634,9 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
text = (boost::format(_u8L("filaments %s cannot be printed directly on the surface of this plate.")) % warning ).str();
error = ErrorType::SLICING_ERROR;
break;
case EWarning::ObjectLimited:
text = object_limited_text;
break;
}
}
//BBS: this may happened when exit the app, plater is null

View File

@ -376,6 +376,7 @@ class GLCanvas3D
SlaSupportsOutside,
SomethingNotShown,
ObjectClashed,
ObjectLimited,
GCodeConflict,
ToolHeightOutside,
FilamentUnPrintableOnFirstLayer

View File

@ -835,7 +835,7 @@ void MainFrame::update_layout()
{
m_main_sizer->Add(m_plater, 1, wxEXPAND);
//BBS: add bed exclude area
m_plater->set_bed_shape({ { 0.0, 0.0 }, { 200.0, 0.0 }, { 200.0, 200.0 }, { 0.0, 200.0 } }, {}, 0.0, {}, {}, true);
m_plater->set_bed_shape({ { 0.0, 0.0 }, { 200.0, 0.0 }, { 200.0, 200.0 }, { 0.0, 200.0 } }, {}, 0.0, {}, {}, {}, true);
m_plater->get_collapse_toolbar().set_enabled(false);
m_plater->collapse_sidebar(true);
m_plater->Show();

View File

@ -2359,7 +2359,7 @@ void PartPlate::generate_exclude_polygon(ExPolygon &exclude_polygon)
}
}
bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, Vec2d position, float height_to_lid, float height_to_rod)
bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, const std::vector<Pointfs>& extruder_areas, Vec2d position, float height_to_lid, float height_to_rod)
{
Pointfs new_shape, new_exclude_areas;
m_raw_shape = shape;
@ -2370,6 +2370,18 @@ bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, Ve
for (const Vec2d& p : exclude_areas) {
new_exclude_areas.push_back(Vec2d(p.x() + position.x(), p.y() + position.y()));
}
std::vector<Pointfs> new_extruder_areas;
for (const Pointfs& shape : extruder_areas) {
Pointfs new_extruder_area;
for (const Vec2d& p : shape) {
Vec2d point(p(0) + position.x(), p(1) + position.y());
new_extruder_area.push_back(point);
}
new_extruder_areas.push_back(new_extruder_area);
}
m_extruder_areas = std::move(new_extruder_areas);
if ((m_shape == new_shape)&&(m_exclude_area == new_exclude_areas)
&&(m_height_to_lid == height_to_lid)&&(m_height_to_rod == height_to_rod)) {
BOOST_LOG_TRIVIAL(info) << "PartPlate same shape, skip directly";
@ -3605,7 +3617,7 @@ void PartPlateList::reset_size(int width, int depth, int height, bool reload_obj
m_plate_height = height;
update_all_plates_pos_and_size(false, false, true);
if (update_shapes) {
set_shapes(m_shape, m_exclude_areas, m_logo_texture_filename, m_height_to_lid, m_height_to_rod);
set_shapes(m_shape, m_exclude_areas, m_extruder_areas, m_logo_texture_filename, m_height_to_lid, m_height_to_rod);
}
if (reload_objects)
reload_all_objects();
@ -3690,7 +3702,7 @@ void PartPlateList::reinit()
//reset plate 0's position
Vec2d pos = compute_shape_position(0, m_plate_cols);
m_plate_list[0]->set_shape(m_shape, m_exclude_areas, pos, m_height_to_lid, m_height_to_rod);
m_plate_list[0]->set_shape(m_shape, m_exclude_areas, m_extruder_areas, pos, m_height_to_lid, m_height_to_rod);
//reset unprintable plate's position
Vec3d origin2 = compute_origin_for_unprintable();
unprintable_plate.set_pos_and_size(origin2, m_plate_width, m_plate_depth, m_plate_height, false);
@ -3737,7 +3749,7 @@ int PartPlateList::create_plate(bool adjust_position)
plate->set_index(new_index);
Vec2d pos = compute_shape_position(new_index, cols);
plate->set_shape(m_shape, m_exclude_areas, pos, m_height_to_lid, m_height_to_rod);
plate->set_shape(m_shape, m_exclude_areas, m_extruder_areas, pos, m_height_to_lid, m_height_to_rod);
m_plate_list.emplace_back(plate);
update_plate_cols();
if (old_cols != cols)
@ -3745,7 +3757,7 @@ int PartPlateList::create_plate(bool adjust_position)
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(":old_cols %1% -> new_cols %2%") % old_cols % cols;
//update the origin of each plate
update_all_plates_pos_and_size(adjust_position, false);
set_shapes(m_shape, m_exclude_areas, m_logo_texture_filename, m_height_to_lid, m_height_to_rod);
set_shapes(m_shape, m_exclude_areas, m_extruder_areas, m_logo_texture_filename, m_height_to_lid, m_height_to_rod);
if (m_plater) {
Vec2d pos = compute_shape_position(m_current_plate, cols);
@ -3892,7 +3904,7 @@ int PartPlateList::delete_plate(int index)
//update render shapes
Vec2d pos = compute_shape_position(i, m_plate_cols);
plate->set_shape(m_shape, m_exclude_areas, pos, m_height_to_lid, m_height_to_rod);
plate->set_shape(m_shape, m_exclude_areas, m_extruder_areas, pos, m_height_to_lid, m_height_to_rod);
}
//update current_plate if delete current
@ -3915,7 +3927,7 @@ int PartPlateList::delete_plate(int index)
{
//update the origin of each plate
update_all_plates_pos_and_size();
set_shapes(m_shape, m_exclude_areas, m_logo_texture_filename, m_height_to_lid, m_height_to_rod);
set_shapes(m_shape, m_exclude_areas, m_extruder_areas, m_logo_texture_filename, m_height_to_lid, m_height_to_rod);
}
else
{
@ -5212,11 +5224,12 @@ void PartPlateList::select_plate_view()
m_plater->get_camera().select_view("topfront");
}
bool PartPlateList::set_shapes(const Pointfs& shape, const Pointfs& exclude_areas, const std::string& texture_filename, float height_to_lid, float height_to_rod)
bool PartPlateList::set_shapes(const Pointfs& shape, const Pointfs& exclude_areas, const std::vector<Pointfs>& extruder_areas, const std::string& texture_filename, float height_to_lid, float height_to_rod)
{
const std::lock_guard<std::mutex> local_lock(m_plates_mutex);
m_shape = shape;
m_exclude_areas = exclude_areas;
m_extruder_areas = extruder_areas;
m_height_to_lid = height_to_lid;
m_height_to_rod = height_to_rod;
@ -5230,7 +5243,7 @@ bool PartPlateList::set_shapes(const Pointfs& shape, const Pointfs& exclude_area
Vec2d pos;
pos = compute_shape_position(i, m_plate_cols);
plate->set_shape(shape, exclude_areas, pos, height_to_lid, height_to_rod);
plate->set_shape(shape, exclude_areas, extruder_areas, pos, height_to_lid, height_to_rod);
}
is_load_bedtype_textures = false; //reload textures
calc_bounding_boxes();
@ -5428,7 +5441,7 @@ int PartPlateList::rebuild_plates_after_deserialize(std::vector<bool>& previous_
for (unsigned int i = 0; i < (unsigned int) m_plate_list.size(); ++i) {
m_plate_list[i]->m_partplate_list = this;
}//set_shapes api: every plate use m_partplate_list
set_shapes(m_shape, m_exclude_areas, m_logo_texture_filename, m_height_to_lid, m_height_to_rod);
set_shapes(m_shape, m_exclude_areas, m_extruder_areas, m_logo_texture_filename, m_height_to_lid, m_height_to_rod);
for (unsigned int i = 0; i < (unsigned int)m_plate_list.size(); ++i){
bool need_reset_print = false;
m_plate_list[i]->m_plater = this->m_plater;
@ -5762,7 +5775,7 @@ int PartPlateList::load_gcode_files()
//BoundingBoxf3 print_volume = m_plate_list[i]->get_bounding_box(false);
//print_volume.max(2) = this->m_plate_height;
//print_volume.min(2) = -1e10;
m_model->update_print_volume_state({m_plate_list[i]->get_shape(), (double)this->m_plate_height });
m_model->update_print_volume_state({m_plate_list[i]->get_shape(), (double)this->m_plate_height, m_plate_list[i]->get_extruder_areas() });
if (!m_plate_list[i]->load_gcode_from_file(m_plate_list[i]->m_gcode_path_from_3mf))
ret ++;

View File

@ -120,6 +120,7 @@ private:
Pointfs m_raw_shape;
Pointfs m_shape;
Pointfs m_exclude_area;
std::vector<Pointfs> m_extruder_areas;
BoundingBoxf3 m_bounding_box;
BoundingBoxf3 m_extended_bounding_box;
BoundingBoxf3 m_cur_bed_boundingbox;
@ -347,7 +348,8 @@ public:
/*rendering related functions*/
const Pointfs& get_shape() const { return m_shape; }
bool set_shape(const Pointfs& shape, const Pointfs& exclude_areas, Vec2d position, float height_to_lid, float height_to_rod);
bool set_shape(const Pointfs& shape, const Pointfs& exclude_areas, const std::vector<Pointfs>& extruder_areas, Vec2d position, float height_to_lid, float height_to_rod);
const std::vector<Pointfs>& get_extruder_areas() const { return m_extruder_areas; }
bool contains(const Vec3d& point) const;
bool contains(const GLVolume& v) const;
bool contains(const BoundingBoxf3& bb) const;
@ -556,6 +558,7 @@ class PartPlateList : public ObjectBase
PartPlate unprintable_plate;
Pointfs m_shape;
Pointfs m_exclude_areas;
std::vector<Pointfs> m_extruder_areas;
BoundingBoxf3 m_bounding_box;
bool m_intialized;
std::string m_logo_texture_filename;
@ -861,7 +864,7 @@ public:
int select_plate_by_obj(int obj_index, int instance_index);
void calc_bounding_boxes();
void select_plate_view();
bool set_shapes(const Pointfs& shape, const Pointfs& exclude_areas, const std::string& custom_texture, float height_to_lid, float height_to_rod);
bool set_shapes(const Pointfs& shape, const Pointfs& exclude_areas, const std::vector<Pointfs>& extruder_areas, const std::string& custom_texture, float height_to_lid, float height_to_rod);
void set_hover_id(int id);
void reset_hover_id();
bool intersects(const BoundingBoxf3 &bb);

View File

@ -2930,7 +2930,7 @@ struct Plater::priv
// fills the m_bed.m_grid_lines and sets m_bed.m_origin.
// Sets m_bed.m_polygon to limit the object placement.
//BBS: add bed exclude area
void set_bed_shape(const Pointfs& shape, const Pointfs& exclude_areas, const double printable_height, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom = false);
void set_bed_shape(const Pointfs& shape, const Pointfs& exclude_areas, const double printable_height, std::vector<Pointfs> extruder_areas, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom = false);
bool can_delete() const;
bool can_delete_all() const;
@ -3054,8 +3054,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
, main_frame(main_frame)
//BBS: add bed_exclude_area
, config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({
"printable_area", "bed_exclude_area", "bed_custom_texture", "bed_custom_model", "print_sequence",
"extruder_clearance_dist_to_rod", "extruder_clearance_max_radius",
"printable_area", "bed_exclude_area", "extruder_printable_area", "bed_custom_texture", "bed_custom_model", "print_sequence",
"extruder_clearance_radius", "extruder_clearance_dist_to_rod", "extruder_clearance_max_radius",
"extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
"nozzle_height", "skirt_loops", "skirt_distance",
"brim_width", "brim_object_gap", "brim_type", "nozzle_diameter", "single_extruder_multi_material",
@ -5405,7 +5405,7 @@ void Plater::priv::update_print_volume_state()
{
//BBS: use the plate's bounding box instead of the bed's
PartPlate* pp = partplate_list.get_curr_plate();
BuildVolume build_volume(pp->get_shape(), this->bed.build_volume().printable_height());
BuildVolume build_volume(pp->get_shape(), this->bed.build_volume().printable_height(), this->bed.build_volume().extruder_areas());
this->model.update_print_volume_state(build_volume);
}
@ -8540,11 +8540,11 @@ bool Plater::priv::show_publish_dlg(bool show)
}
//BBS: add bed exclude area
void Plater::priv::set_bed_shape(const Pointfs& shape, const Pointfs& exclude_areas, const double printable_height, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom)
void Plater::priv::set_bed_shape(const Pointfs& shape, const Pointfs& exclude_areas, const double printable_height, std::vector<Pointfs> extruder_areas, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom)
{
//BBS: add shape position
Vec2d shape_position = partplate_list.get_current_shape_position();
bool new_shape = bed.set_shape(shape, printable_height, custom_model, force_as_custom, shape_position);
bool new_shape = bed.set_shape(shape, printable_height, extruder_areas, custom_model, force_as_custom, shape_position);
float prev_height_lid, prev_height_rod;
partplate_list.get_height_limits(prev_height_lid, prev_height_rod);
@ -8568,11 +8568,11 @@ void Plater::priv::set_bed_shape(const Pointfs& shape, const Pointfs& exclude_ar
//Pointfs& exclude_areas = config->option<ConfigOptionPoints>("bed_exclude_area")->values;
partplate_list.reset_size(max.x() - min.x() - Bed3D::Axes::DefaultTipRadius, max.y() - min.y() - Bed3D::Axes::DefaultTipRadius, z);
partplate_list.set_shapes(shape, exclude_areas, custom_texture, height_to_lid, height_to_rod);
partplate_list.set_shapes(shape, exclude_areas, extruder_areas, custom_texture, height_to_lid, height_to_rod);
Vec2d new_shape_position = partplate_list.get_current_shape_position();
if (shape_position != new_shape_position)
bed.set_shape(shape, printable_height, custom_model, force_as_custom, new_shape_position);
bed.set_shape(shape, printable_height, extruder_areas, custom_model, force_as_custom, new_shape_position);
}
}
@ -13487,14 +13487,15 @@ void Plater::set_bed_shape() const
//BBS: add bed exclude areas
p->config->option<ConfigOptionPoints>("bed_exclude_area")->values,
p->config->option<ConfigOptionFloat>("printable_height")->value,
p->config->option<ConfigOptionPointsGroups>("extruder_printable_area")->values,
p->config->option<ConfigOptionString>("bed_custom_texture")->value.empty() ? texture_filename : p->config->option<ConfigOptionString>("bed_custom_texture")->value,
p->config->option<ConfigOptionString>("bed_custom_model")->value);
}
//BBS: add bed exclude area
void Plater::set_bed_shape(const Pointfs& shape, const Pointfs& exclude_area, const double printable_height, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom) const
void Plater::set_bed_shape(const Pointfs& shape, const Pointfs& exclude_area, const double printable_height, std::vector<Pointfs> extruder_areas, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom) const
{
p->set_bed_shape(shape, exclude_area, printable_height, custom_texture, custom_model, force_as_custom);
p->set_bed_shape(shape, exclude_area, printable_height, extruder_areas, custom_texture, custom_model, force_as_custom);
}
void Plater::force_filament_colors_update()
@ -14225,13 +14226,16 @@ int Plater::select_sliced_plate(int plate_index)
return ret;
}
extern std::string object_limited_text;
extern std::string object_clashed_text;
void Plater::validate_current_plate(bool& model_fits, bool& validate_error)
{
model_fits = p->view3D->get_canvas3d()->check_volumes_outside_state() != ModelInstancePVS_Partly_Outside;
ModelInstanceEPrintVolumeState state = p->view3D->get_canvas3d()->check_volumes_outside_state();
model_fits = (state != ModelInstancePVS_Partly_Outside);
validate_error = false;
if (p->printer_technology == ptFFF) {
std::string plater_text = _u8L("An object is laid over the boundary of plate or exceeds the height limit.\n"
"Please solve the problem by moving it totally on or off the plate, and confirming that the height is within the build volume.");;
//std::string plater_text = _u8L("An object is laid over the boundary of plate or exceeds the height limit.\n"
// "Please solve the problem by moving it totally on or off the plate, and confirming that the height is within the build volume.");;
StringObjectException warning;
Polygons polygons;
std::vector<std::pair<Polygon, float>> height_polygons;
@ -14266,10 +14270,17 @@ void Plater::validate_current_plate(bool& model_fits, bool& validate_error)
}
if (!model_fits) {
p->notification_manager->push_plater_error_notification(plater_text);
p->notification_manager->push_plater_error_notification(object_clashed_text);
}
else {
p->notification_manager->close_plater_error_notification(plater_text);
p->notification_manager->close_plater_error_notification(object_clashed_text);
}
if (state == ModelInstancePVS_Limited) {
p->notification_manager->push_plater_warning_notification(object_limited_text);
}
else {
p->notification_manager->close_plater_warning_notification(object_limited_text);
}
}

View File

@ -618,7 +618,7 @@ public:
void update_flush_volume_matrix(size_t old_nozzle_size, size_t new_nozzle_size);
//BBS: add bed exclude area
void set_bed_shape() const;
void set_bed_shape(const Pointfs& shape, const Pointfs& exclude_area, const double printable_height, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom = false) const;
void set_bed_shape(const Pointfs& shape, const Pointfs& exclude_area, const double printable_height, std::vector<Pointfs> extruder_areas, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom = false) const;
const NotificationManager* get_notification_manager() const;
NotificationManager* get_notification_manager();

View File

@ -1069,6 +1069,7 @@ bool CalibUtils::get_pa_k_n_value_by_cali_idx(const MachineObject *obj, int cali
bool CalibUtils::process_and_store_3mf(Model *model, const DynamicPrintConfig &full_config, const Calib_Params &params, wxString &error_message)
{
Pointfs bedfs = full_config.opt<ConfigOptionPoints>("printable_area")->values;
std::vector<Pointfs> extruder_areas = full_config.option<ConfigOptionPointsGroups>("extruder_printable_area")->values;
double print_height = full_config.opt_float("printable_height");
double current_width = bedfs[2].x() - bedfs[0].x();
double current_depth = bedfs[2].y() - bedfs[0].y();
@ -1115,7 +1116,7 @@ bool CalibUtils::process_and_store_3mf(Model *model, const DynamicPrintConfig &f
int print_index;
part_plate->get_print(&print, &gcode_result, &print_index);
BuildVolume build_volume(bedfs, print_height);
BuildVolume build_volume(bedfs, print_height, extruder_areas);
unsigned int count = model->update_print_volume_state(build_volume);
if (count == 0) {
error_message = _L("Unable to calibrate: maybe because the set calibration value range is too large, or the step is too small");