mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-12-28 02:10:30 -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
|
|
@ -3027,6 +3027,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");
|
||||
|
|
@ -3035,6 +3036,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;
|
||||
|
|
@ -3085,7 +3089,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(make_counter_clockwise(current_printable_area), current_exclude_area, bed_texture, height_to_lid, height_to_rod);
|
||||
partplate_list.set_shapes(make_counter_clockwise(current_printable_area), current_exclude_areas, bed_texture, height_to_lid, height_to_rod);
|
||||
//plate_stride = partplate_list.plate_stride_x();
|
||||
}
|
||||
|
||||
|
|
@ -4805,7 +4809,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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); });
|
||||
|
|
|
|||
|
|
@ -29,16 +29,24 @@ class BuildVolume
|
|||
{
|
||||
public:
|
||||
|
||||
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
|
||||
BuildVolume_Type type() const { return m_type; }
|
||||
// Format the type for console output.
|
||||
|
|
@ -69,9 +77,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.
|
||||
|
|
@ -94,12 +104,22 @@ 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;
|
||||
|
||||
const std::pair<std::vector<Vec2d>, std::vector<Vec2d>>& top_bottom_convex_hull_decomposition_scene() const { return m_top_bottom_convex_hull_decomposition_scene; }
|
||||
const std::pair<std::vector<Vec2d>, std::vector<Vec2d>>& top_bottom_convex_hull_decomposition_bed() const { return m_top_bottom_convex_hull_decomposition_bed; }
|
||||
|
||||
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 };
|
||||
|
||||
|
|
|
|||
|
|
@ -201,6 +201,7 @@ class Print;
|
|||
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
|
||||
|
|
|
|||
|
|
@ -3349,8 +3349,23 @@ ModelInstanceEPrintVolumeState ModelInstance::calc_print_volume_state(const Buil
|
|||
BuildVolume::ObjectState state;
|
||||
if (!build_volume.bounding_volume2d().inflated(BuildVolume::SceneEpsilon).overlap(bbox2d))
|
||||
state = BuildVolume::ObjectState::Outside;
|
||||
else
|
||||
state = build_volume.object_state(vol->mesh().its, matrix.cast<float>(), true /* may be below print bed */);
|
||||
else {
|
||||
switch(build_volume.type())
|
||||
{
|
||||
case BuildVolume_Type::Rectangle:
|
||||
{
|
||||
state = build_volume.volume_state_bbox(bboxt);
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -1227,6 +1227,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
|
||||
|
|
|
|||
|
|
@ -4020,7 +4020,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ void Bed3D::Axes::render()
|
|||
}
|
||||
|
||||
//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) {
|
||||
|
|
@ -289,7 +289,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;
|
||||
|
||||
|
|
@ -297,16 +297,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;
|
||||
|
|
@ -342,7 +352,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)
|
||||
|
|
|
|||
|
|
@ -115,6 +115,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:
|
||||
|
|
@ -126,7 +127,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);
|
||||
|
|
|
|||
|
|
@ -1067,15 +1067,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)
|
||||
|
|
@ -1090,14 +1090,27 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
|
|||
//FIXME this test does not evaluate collision of a build volume bounding box with non-convex objects.
|
||||
const BoundingBoxf3& bb = volume_bbox(*volume);
|
||||
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;
|
||||
|
|
@ -1106,22 +1119,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;
|
||||
|
|
@ -1150,11 +1164,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)))
|
||||
{
|
||||
|
|
@ -1168,7 +1182,7 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
|
|||
volume->partly_inside = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
if (out_state != nullptr)
|
||||
*out_state = overall_state;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -25,7 +25,7 @@ namespace GUI {
|
|||
|
||||
BedShape::BedShape(const Pointfs& points)
|
||||
{
|
||||
m_build_volume = { points, 0. };
|
||||
m_build_volume = { points, 0.f, {} };
|
||||
}
|
||||
|
||||
static std::string get_option_label(BedShape::Parameter param)
|
||||
|
|
@ -283,7 +283,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);
|
||||
|
|
@ -522,7 +522,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;
|
||||
|
|
|
|||
|
|
@ -1008,6 +1008,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;
|
||||
|
||||
|
|
@ -1027,7 +1028,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
|
||||
|
|
|
|||
|
|
@ -2810,8 +2810,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)
|
||||
|
|
@ -2823,6 +2825,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));
|
||||
}
|
||||
|
|
@ -9650,6 +9653,11 @@ void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning)
|
|||
_set_warning_notification(warning, show);
|
||||
}
|
||||
|
||||
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{
|
||||
|
|
@ -9686,10 +9694,12 @@ 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 plate boundaries 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::ObjectLimited:
|
||||
text = object_limited_text;
|
||||
break;
|
||||
}
|
||||
//BBS: this may happened when exit the app, plater is null
|
||||
if (!wxGetApp().plater())
|
||||
|
|
|
|||
|
|
@ -380,6 +380,7 @@ class GLCanvas3D
|
|||
SlaSupportsOutside,
|
||||
SomethingNotShown,
|
||||
ObjectClashed,
|
||||
ObjectLimited,
|
||||
GCodeConflict,
|
||||
ToolHeightOutside
|
||||
};
|
||||
|
|
|
|||
|
|
@ -846,7 +846,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->enable_sidebar(false);
|
||||
m_plater->Show();
|
||||
|
|
|
|||
|
|
@ -2645,7 +2645,7 @@ void PartPlate::generate_exclude_polygon(ExPolygon &exclude_polygon)
|
|||
exclude_polygon.contour.make_counter_clockwise();
|
||||
}
|
||||
|
||||
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;
|
||||
for (const Vec2d& p : shape) {
|
||||
|
|
@ -2655,6 +2655,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";
|
||||
|
|
@ -3629,7 +3641,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();
|
||||
|
|
@ -3714,7 +3726,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);
|
||||
|
|
@ -3764,7 +3776,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)
|
||||
|
|
@ -3772,7 +3784,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);
|
||||
|
|
@ -3943,7 +3955,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
|
||||
|
|
@ -3966,7 +3978,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
|
||||
{
|
||||
|
|
@ -5063,11 +5075,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;
|
||||
|
||||
|
|
@ -5081,7 +5094,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();
|
||||
|
|
@ -5260,7 +5273,7 @@ int PartPlateList::rebuild_plates_after_deserialize(std::vector<bool>& previous_
|
|||
}
|
||||
update_plate_cols();
|
||||
update_all_plates_pos_and_size(false, false, false, 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);
|
||||
for (unsigned int i = 0; i < (unsigned int)m_plate_list.size(); ++i)
|
||||
{
|
||||
bool need_reset_print = false;
|
||||
|
|
@ -5592,7 +5605,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 ++;
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ private:
|
|||
|
||||
Pointfs m_shape;
|
||||
Pointfs m_exclude_area;
|
||||
std::vector<Pointfs> m_extruder_areas;
|
||||
BoundingBoxf3 m_bounding_box;
|
||||
BoundingBoxf3 m_extended_bounding_box;
|
||||
mutable std::vector<BoundingBoxf3> m_exclude_bounding_box;
|
||||
|
|
@ -363,7 +364,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;
|
||||
|
|
@ -562,6 +564,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;
|
||||
|
|
@ -821,7 +824,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);
|
||||
|
|
|
|||
|
|
@ -2880,7 +2880,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;
|
||||
|
|
@ -3034,8 +3034,9 @@ 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_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
|
||||
"printable_area", "bed_exclude_area", "extruder_printable_area", "bed_custom_texture", "bed_custom_model", "print_sequence",
|
||||
"extruder_clearance_radius",
|
||||
"extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
|
||||
"nozzle_height", "skirt_type", "skirt_loops", "skirt_speed","min_skirt_length", "skirt_distance", "skirt_start_angle",
|
||||
"brim_width", "brim_object_gap", "brim_type", "nozzle_diameter", "single_extruder_multi_material", "preferred_orientation",
|
||||
"enable_prime_tower", "wipe_tower_x", "wipe_tower_y", "prime_tower_width", "prime_tower_brim_width", "prime_volume",
|
||||
|
|
@ -5450,7 +5451,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);
|
||||
}
|
||||
|
||||
|
|
@ -8464,7 +8465,7 @@ 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)
|
||||
{
|
||||
//Orca: reduce resolution for large bed printer
|
||||
BoundingBoxf bed_size = get_extents(shape);
|
||||
|
|
@ -8475,7 +8476,7 @@ void Plater::priv::set_bed_shape(const Pointfs& shape, const Pointfs& exclude_ar
|
|||
|
||||
//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);
|
||||
|
|
@ -8499,11 +8500,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -13602,14 +13603,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(make_counter_clockwise(shape), exclude_area, printable_height, custom_texture, custom_model, force_as_custom);
|
||||
p->set_bed_shape(make_counter_clockwise(shape), exclude_area, printable_height, extruder_areas, custom_texture, custom_model, force_as_custom);
|
||||
}
|
||||
|
||||
void Plater::force_filament_colors_update()
|
||||
|
|
@ -14328,13 +14330,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;
|
||||
|
|
@ -14369,10 +14374,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -664,7 +664,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();
|
||||
|
|
|
|||
|
|
@ -987,6 +987,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 ¶ms, wxString &error_message)
|
||||
{
|
||||
Pointfs bedfs = make_counter_clockwise(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();
|
||||
|
|
@ -1033,7 +1034,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");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue