optimize icon position for circle bed

This commit is contained in:
SoftFever 2023-04-10 18:55:14 +08:00
parent cb22560d38
commit ef3614a21a
12 changed files with 99 additions and 67 deletions

View file

@ -70,6 +70,26 @@ public:
return ! (this->max(0) < other.min(0) || this->min(0) > other.max(0) || return ! (this->max(0) < other.min(0) || this->min(0) > other.max(0) ||
this->max(1) < other.min(1) || this->min(1) > other.max(1)); this->max(1) < other.min(1) || this->min(1) > other.max(1));
} }
PointClass operator[](size_t idx) const {
switch (idx) {
case 0:
return min;
break;
case 1:
return PointClass(max(0), min(1));
break;
case 2:
return max;
break;
case 3:
return PointClass(min(0), max(1));
break;
default:
return PointClass();
break;
}
return PointClass();
}
bool operator==(const BoundingBoxBase<PointClass> &rhs) { return this->min == rhs.min && this->max == rhs.max; } bool operator==(const BoundingBoxBase<PointClass> &rhs) { return this->min == rhs.min && this->max == rhs.max; }
bool operator!=(const BoundingBoxBase<PointClass> &rhs) { return ! (*this == rhs); } bool operator!=(const BoundingBoxBase<PointClass> &rhs) { return ! (*this == rhs); }
friend std::ostream &operator<<(std::ostream &os, const BoundingBoxBase &bbox) friend std::ostream &operator<<(std::ostream &os, const BoundingBoxBase &bbox)

View file

@ -24,7 +24,7 @@ BuildVolume::BuildVolume(const std::vector<Vec2d> &printable_area, const double
if (printable_area.size() >= 4 && std::abs((m_area - double(m_bbox.size().x()) * double(m_bbox.size().y()))) < sqr(SCALED_EPSILON)) { if (printable_area.size() >= 4 && std::abs((m_area - double(m_bbox.size().x()) * double(m_bbox.size().y()))) < sqr(SCALED_EPSILON)) {
// Square print bed, use the bounding box for collision detection. // Square print bed, use the bounding box for collision detection.
m_type = Type::Rectangle; m_type = BuildVolume_Type::Rectangle;
m_circle.center = 0.5 * (m_bbox.min.cast<double>() + m_bbox.max.cast<double>()); m_circle.center = 0.5 * (m_bbox.min.cast<double>() + m_bbox.max.cast<double>());
m_circle.radius = 0.5 * m_bbox.size().cast<double>().norm(); m_circle.radius = 0.5 * m_bbox.size().cast<double>().norm();
} else if (printable_area.size() > 3) { } else if (printable_area.size() > 3) {
@ -52,16 +52,16 @@ BuildVolume::BuildVolume(const std::vector<Vec2d> &printable_area, const double
prev = p; prev = p;
} }
if (is_circle) { if (is_circle) {
m_type = Type::Circle; m_type = BuildVolume_Type::Circle;
m_circle.center = scaled<double>(m_circle.center); m_circle.center = scaled<double>(m_circle.center);
m_circle.radius = scaled<double>(m_circle.radius); m_circle.radius = scaled<double>(m_circle.radius);
} }
} }
if (printable_area.size() >= 3 && m_type == Type::Invalid) { if (printable_area.size() >= 3 && m_type == BuildVolume_Type::Invalid) {
// Circle check is not used for Convex / Custom shapes, fill it with something reasonable. // Circle check is not used for Convex / Custom shapes, fill it with something reasonable.
m_circle = Geometry::smallest_enclosing_circle_welzl(m_convex_hull.points); m_circle = Geometry::smallest_enclosing_circle_welzl(m_convex_hull.points);
m_type = (m_convex_hull.area() - m_area) < sqr(SCALED_EPSILON) ? Type::Convex : Type::Custom; m_type = (m_convex_hull.area() - m_area) < sqr(SCALED_EPSILON) ? BuildVolume_Type::Convex : BuildVolume_Type::Custom;
// Initialize the top / bottom decomposition for inside convex polygon check. Do it with two different epsilons applied. // Initialize the top / bottom decomposition for inside convex polygon check. Do it with two different epsilons applied.
auto convex_decomposition = [](const Polygon &in, double epsilon) { auto convex_decomposition = [](const Polygon &in, double epsilon) {
Polygon src = expand(in, float(epsilon)).front(); Polygon src = expand(in, float(epsilon)).front();
@ -272,7 +272,7 @@ BuildVolume::ObjectState object_state_templ(const indexed_triangle_set &its, con
BuildVolume::ObjectState BuildVolume::object_state(const indexed_triangle_set& its, const Transform3f& trafo, bool may_be_below_bed, bool ignore_bottom) const BuildVolume::ObjectState BuildVolume::object_state(const indexed_triangle_set& its, const Transform3f& trafo, bool may_be_below_bed, bool ignore_bottom) const
{ {
switch (m_type) { switch (m_type) {
case Type::Rectangle: case BuildVolume_Type::Rectangle:
{ {
BoundingBox3Base<Vec3d> build_volume = this->bounding_volume().inflated(SceneEpsilon); BoundingBox3Base<Vec3d> build_volume = this->bounding_volume().inflated(SceneEpsilon);
if (m_max_print_height == 0.0) if (m_max_print_height == 0.0)
@ -285,20 +285,20 @@ BuildVolume::ObjectState BuildVolume::object_state(const indexed_triangle_set& i
//FIXME This test does NOT correctly interprets intersection of a non-convex object with a rectangular build volume. //FIXME This test does NOT correctly interprets intersection of a non-convex object with a rectangular build volume.
return object_state_templ(its, trafo, may_be_below_bed, [build_volumef](const Vec3f &pt) { return build_volumef.contains(pt); }); return object_state_templ(its, trafo, may_be_below_bed, [build_volumef](const Vec3f &pt) { return build_volumef.contains(pt); });
} }
case Type::Circle: case BuildVolume_Type::Circle:
{ {
Geometry::Circlef circle { unscaled<float>(m_circle.center), unscaled<float>(m_circle.radius + SceneEpsilon) }; 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](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)); }); 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: case BuildVolume_Type::Convex:
//FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently. //FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently.
case Type::Custom: 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, [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](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>()); }); 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: case BuildVolume_Type::Invalid:
default: default:
return ObjectState::Inside; return ObjectState::Inside;
} }
@ -306,7 +306,7 @@ BuildVolume::ObjectState BuildVolume::object_state(const indexed_triangle_set& i
BuildVolume::ObjectState BuildVolume::volume_state_bbox(const BoundingBoxf3& volume_bbox, bool ignore_bottom) const BuildVolume::ObjectState BuildVolume::volume_state_bbox(const BoundingBoxf3& volume_bbox, bool ignore_bottom) const
{ {
assert(m_type == Type::Rectangle); assert(m_type == BuildVolume_Type::Rectangle);
BoundingBox3Base<Vec3d> build_volume = this->bounding_volume().inflated(SceneEpsilon); BoundingBox3Base<Vec3d> build_volume = this->bounding_volume().inflated(SceneEpsilon);
if (m_max_print_height == 0.0) if (m_max_print_height == 0.0)
build_volume.max.z() = std::numeric_limits<double>::max(); build_volume.max.z() = std::numeric_limits<double>::max();
@ -325,7 +325,7 @@ bool BuildVolume::all_paths_inside(const GCodeProcessorResult& paths, const Boun
static constexpr const double epsilon = BedEpsilon; static constexpr const double epsilon = BedEpsilon;
switch (m_type) { switch (m_type) {
case Type::Rectangle: case BuildVolume_Type::Rectangle:
{ {
BoundingBox3Base<Vec3d> build_volume = this->bounding_volume().inflated(epsilon); BoundingBox3Base<Vec3d> build_volume = this->bounding_volume().inflated(epsilon);
if (m_max_print_height == 0.0) if (m_max_print_height == 0.0)
@ -334,7 +334,7 @@ bool BuildVolume::all_paths_inside(const GCodeProcessorResult& paths, const Boun
build_volume.min.z() = -std::numeric_limits<double>::max(); build_volume.min.z() = -std::numeric_limits<double>::max();
return build_volume.contains(paths_bbox); return build_volume.contains(paths_bbox);
} }
case Type::Circle: case BuildVolume_Type::Circle:
{ {
const Vec2f c = unscaled<float>(m_circle.center); const Vec2f c = unscaled<float>(m_circle.center);
const float r = unscaled<double>(m_circle.radius) + epsilon; const float r = unscaled<double>(m_circle.radius) + epsilon;
@ -345,9 +345,9 @@ bool BuildVolume::all_paths_inside(const GCodeProcessorResult& paths, const Boun
std::all_of(paths.moves.begin(), paths.moves.end(), [move_valid, c, r2, z = m_max_print_height + epsilon](const GCodeProcessorResult::MoveVertex& move) std::all_of(paths.moves.begin(), paths.moves.end(), [move_valid, c, r2, z = m_max_print_height + epsilon](const GCodeProcessorResult::MoveVertex& move)
{ return ! move_valid(move) || ((to_2d(move.position) - c).squaredNorm() <= r2 && move.position.z() <= z); }); { return ! move_valid(move) || ((to_2d(move.position) - c).squaredNorm() <= r2 && move.position.z() <= z); });
} }
case Type::Convex: case BuildVolume_Type::Convex:
//FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently. //FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently.
case Type::Custom: case BuildVolume_Type::Custom:
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, 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>()); }) : { return ! move_valid(move) || Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_bed, to_2d(move.position).cast<double>()); }) :
@ -375,7 +375,7 @@ bool BuildVolume::all_paths_inside_vertices_and_normals_interleaved(const std::v
assert(paths.size() % 6 == 0); assert(paths.size() % 6 == 0);
static constexpr const double epsilon = BedEpsilon; static constexpr const double epsilon = BedEpsilon;
switch (m_type) { switch (m_type) {
case Type::Rectangle: case BuildVolume_Type::Rectangle:
{ {
BoundingBox3Base<Vec3d> build_volume = this->bounding_volume().inflated(epsilon); BoundingBox3Base<Vec3d> build_volume = this->bounding_volume().inflated(epsilon);
if (m_max_print_height == 0.0) if (m_max_print_height == 0.0)
@ -384,7 +384,7 @@ bool BuildVolume::all_paths_inside_vertices_and_normals_interleaved(const std::v
build_volume.min.z() = -std::numeric_limits<double>::max(); build_volume.min.z() = -std::numeric_limits<double>::max();
return build_volume.contains(paths_bbox.min().cast<double>()) && build_volume.contains(paths_bbox.max().cast<double>()); return build_volume.contains(paths_bbox.min().cast<double>()) && build_volume.contains(paths_bbox.max().cast<double>());
} }
case Type::Circle: case BuildVolume_Type::Circle:
{ {
const Vec2f c = unscaled<float>(m_circle.center); const Vec2f c = unscaled<float>(m_circle.center);
const float r = unscaled<double>(m_circle.radius) + float(epsilon); const float r = unscaled<double>(m_circle.radius) + float(epsilon);
@ -393,9 +393,9 @@ bool BuildVolume::all_paths_inside_vertices_and_normals_interleaved(const std::v
all_inside_vertices_normals_interleaved(paths, [c, r2](Vec3f p) { return (to_2d(p) - c).squaredNorm() <= r2; }) : all_inside_vertices_normals_interleaved(paths, [c, r2](Vec3f p) { return (to_2d(p) - c).squaredNorm() <= r2; }) :
all_inside_vertices_normals_interleaved(paths, [c, r2, z = m_max_print_height + epsilon](Vec3f p) { return (to_2d(p) - c).squaredNorm() <= r2 && p.z() <= z; }); all_inside_vertices_normals_interleaved(paths, [c, r2, z = m_max_print_height + epsilon](Vec3f p) { return (to_2d(p) - c).squaredNorm() <= r2 && p.z() <= z; });
} }
case Type::Convex: case BuildVolume_Type::Convex:
//FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently. //FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently.
case Type::Custom: case BuildVolume_Type::Custom:
return m_max_print_height == 0.0 ? return m_max_print_height == 0.0 ?
all_inside_vertices_normals_interleaved(paths, [this](Vec3f p) { return Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_bed, to_2d(p).cast<double>()); }) : all_inside_vertices_normals_interleaved(paths, [this](Vec3f p) { return Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_bed, to_2d(p).cast<double>()); }) :
all_inside_vertices_normals_interleaved(paths, [this, z = m_max_print_height + epsilon](Vec3f p) { return Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_bed, to_2d(p).cast<double>()) && p.z() <= z; }); all_inside_vertices_normals_interleaved(paths, [this, z = m_max_print_height + epsilon](Vec3f p) { return Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_bed, to_2d(p).cast<double>()) && p.z() <= z; });
@ -404,15 +404,15 @@ bool BuildVolume::all_paths_inside_vertices_and_normals_interleaved(const std::v
} }
} }
std::string_view BuildVolume::type_name(Type type) std::string_view BuildVolume::type_name(BuildVolume_Type type)
{ {
using namespace std::literals; using namespace std::literals;
switch (type) { switch (type) {
case Type::Invalid: return "Invalid"sv; case BuildVolume_Type::Invalid: return "Invalid"sv;
case Type::Rectangle: return "Rectangle"sv; case BuildVolume_Type::Rectangle: return "Rectangle"sv;
case Type::Circle: return "Circle"sv; case BuildVolume_Type::Circle: return "Circle"sv;
case Type::Convex: return "Convex"sv; case BuildVolume_Type::Convex: return "Convex"sv;
case Type::Custom: return "Custom"sv; case BuildVolume_Type::Custom: return "Custom"sv;
} }
// make visual studio happy // make visual studio happy
assert(false); assert(false);

View file

@ -12,24 +12,23 @@
namespace Slic3r { namespace Slic3r {
struct GCodeProcessorResult; struct GCodeProcessorResult;
enum class BuildVolume_Type : unsigned char {
// Not set yet or undefined.
Invalid,
// Rectangular print bed. Most common, cheap to work with.
Rectangle,
// Circular print bed. Common on detals, cheap to work with.
Circle,
// Convex print bed. Complex to process.
Convex,
// Some non convex shape.
Custom
};
// For collision detection of objects and G-code (extrusion paths) against the build volume. // For collision detection of objects and G-code (extrusion paths) against the build volume.
class BuildVolume class BuildVolume
{ {
public: public:
enum class Type : unsigned char
{
// Not set yet or undefined.
Invalid,
// Rectangular print bed. Most common, cheap to work with.
Rectangle,
// Circular print bed. Common on detals, cheap to work with.
Circle,
// Convex print bed. Complex to process.
Convex,
// Some non convex shape.
Custom
};
// Initialized to empty, all zeros, Invalid. // Initialized to empty, all zeros, Invalid.
BuildVolume() {} BuildVolume() {}
@ -41,11 +40,11 @@ public:
double printable_height() const { return m_max_print_height; } double printable_height() const { return m_max_print_height; }
// Derived data // Derived data
Type type() const { return m_type; } BuildVolume_Type type() const { return m_type; }
// Format the type for console output. // Format the type for console output.
static std::string_view type_name(Type type); static std::string_view type_name(BuildVolume_Type type);
std::string_view type_name() const { return type_name(m_type); } std::string_view type_name() const { return type_name(m_type); }
bool valid() const { return m_type != Type::Invalid; } bool valid() const { return m_type != BuildVolume_Type::Invalid; }
// Same as printable_area(), but scaled coordinates. // Same as printable_area(), but scaled coordinates.
const Polygon& polygon() const { return m_polygon; } const Polygon& polygon() const { return m_polygon; }
// Bounding box of polygon(), scaled. // Bounding box of polygon(), scaled.
@ -101,7 +100,7 @@ private:
double m_max_print_height { 0.f }; double m_max_print_height { 0.f };
// Derived values. // Derived values.
Type m_type { Type::Invalid }; BuildVolume_Type m_type { BuildVolume_Type::Invalid };
// Geometry of the print bed, scaled copy of m_bed_shape. // Geometry of the print bed, scaled copy of m_bed_shape.
Polygon m_polygon; Polygon m_polygon;
// Scaled snug bounding box around m_polygon. // Scaled snug bounding box around m_polygon.

View file

@ -131,6 +131,9 @@ public:
// Was the model generated procedurally? // Was the model generated procedurally?
bool is_custom() const { return m_type == Type::Custom; } bool is_custom() const { return m_type == Type::Custom; }
// get the bed shape type
BuildVolume_Type get_build_volume_type() const { return m_build_volume.type(); }
// Bounding box around the print bed, axes and model, for rendering. // Bounding box around the print bed, axes and model, for rendering.
const BoundingBoxf3& extended_bounding_box() const { return m_extended_bounding_box; } const BoundingBoxf3& extended_bounding_box() const { return m_extended_bounding_box; }

View file

@ -1414,14 +1414,14 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
state = BuildVolume::ObjectState::Below; state = BuildVolume::ObjectState::Below;
else { else {
switch (plate_build_volume.type()) { switch (plate_build_volume.type()) {
case BuildVolume::Type::Rectangle: case BuildVolume_Type::Rectangle:
//FIXME this test does not evaluate collision of a build volume bounding box with non-convex objects. //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); state = plate_build_volume.volume_state_bbox(bb);
break; break;
case BuildVolume::Type::Circle: case BuildVolume_Type::Circle:
case BuildVolume::Type::Convex: case BuildVolume_Type::Convex:
//FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently. //FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently.
case BuildVolume::Type::Custom: case BuildVolume_Type::Custom:
state = plate_build_volume.object_state(volume_convex_mesh(*volume).its, volume->world_matrix().cast<float>(), volume_sinking(*volume)); state = plate_build_volume.object_state(volume_convex_mesh(*volume).its, volume->world_matrix().cast<float>(), volume_sinking(*volume));
break; break;
default: default:

View file

@ -88,11 +88,11 @@ wxString BedShape::get_name(PageType type)
BedShape::PageType BedShape::get_page_type() BedShape::PageType BedShape::get_page_type()
{ {
switch (m_build_volume.type()) { switch (m_build_volume.type()) {
case BuildVolume::Type::Rectangle: case BuildVolume_Type::Rectangle:
case BuildVolume::Type::Invalid: return PageType::Rectangle; case BuildVolume_Type::Invalid: return PageType::Rectangle;
case BuildVolume::Type::Circle: return PageType::Circle; case BuildVolume_Type::Circle: return PageType::Circle;
case BuildVolume::Type::Convex: case BuildVolume_Type::Convex:
case BuildVolume::Type::Custom: return PageType::Custom; case BuildVolume_Type::Custom: return PageType::Custom;
} }
// make visual studio happy // make visual studio happy
assert(false); assert(false);
@ -103,7 +103,7 @@ wxString BedShape::get_full_name_with_params()
{ {
wxString out = _L("Shape") + ": " + get_name(this->get_page_type()); wxString out = _L("Shape") + ": " + get_name(this->get_page_type());
switch (m_build_volume.type()) { switch (m_build_volume.type()) {
case BuildVolume::Type::Circle: case BuildVolume_Type::Circle:
out += "\n" + _L(get_option_label(Parameter::Diameter)) + ": [" + double_to_string(2. * unscaled<double>(m_build_volume.circle().radius)) + "]"; out += "\n" + _L(get_option_label(Parameter::Diameter)) + ": [" + double_to_string(2. * unscaled<double>(m_build_volume.circle().radius)) + "]";
break; break;
default: default:
@ -118,7 +118,7 @@ wxString BedShape::get_full_name_with_params()
void BedShape::apply_optgroup_values(ConfigOptionsGroupShp optgroup) void BedShape::apply_optgroup_values(ConfigOptionsGroupShp optgroup)
{ {
switch (m_build_volume.type()) { switch (m_build_volume.type()) {
case BuildVolume::Type::Circle: case BuildVolume_Type::Circle:
optgroup->set_value("diameter", double_to_string(2. * unscaled<double>(m_build_volume.circle().radius))); optgroup->set_value("diameter", double_to_string(2. * unscaled<double>(m_build_volume.circle().radius)));
break; break;
default: default:

View file

@ -35,7 +35,7 @@ struct BedShape
BedShape(const ConfigOptionPoints& points); BedShape(const ConfigOptionPoints& points);
bool is_custom() { return m_build_volume.type() == BuildVolume::Type::Convex || m_build_volume.type() == BuildVolume::Type::Custom; } bool is_custom() { return m_build_volume.type() == BuildVolume_Type::Convex || m_build_volume.type() == BuildVolume_Type::Custom; }
static void append_option_line(ConfigOptionsGroupShp optgroup, Parameter param); static void append_option_line(ConfigOptionsGroupShp optgroup, Parameter param);
static wxString get_name(PageType type); static wxString get_name(PageType type);

View file

@ -116,7 +116,7 @@ RetinaHelper::~RetinaHelper() {}
float RetinaHelper::get_scale_factor() { return float(m_window->GetContentScaleFactor()); } float RetinaHelper::get_scale_factor() { return float(m_window->GetContentScaleFactor()); }
#endif // __WXGTK3__ #endif // __WXGTK3__
// Fixed the collision between BuildVolume::Type::Convex and macro Convex defined inside /usr/include/X11/X.h that is included by WxWidgets 3.0. // Fixed the collision between BuildVolume_Type::Convex and macro Convex defined inside /usr/include/X11/X.h that is included by WxWidgets 3.0.
#if defined(__linux__) && defined(Convex) #if defined(__linux__) && defined(Convex)
#undef Convex #undef Convex
#endif #endif
@ -6542,22 +6542,22 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
if (const BuildVolume &build_volume = m_bed.build_volume(); build_volume.valid()) { if (const BuildVolume &build_volume = m_bed.build_volume(); build_volume.valid()) {
switch (build_volume.type()) { switch (build_volume.type()) {
case BuildVolume::Type::Rectangle: { case BuildVolume_Type::Rectangle: {
const BoundingBox3Base<Vec3d> bed_bb = build_volume.bounding_volume().inflated(BuildVolume::SceneEpsilon); const BoundingBox3Base<Vec3d> bed_bb = build_volume.bounding_volume().inflated(BuildVolume::SceneEpsilon);
m_volumes.set_print_volume({ 0, // Rectangle m_volumes.set_print_volume({ 0, // Rectangle
{ float(bed_bb.min.x()), float(bed_bb.min.y()), float(bed_bb.max.x()), float(bed_bb.max.y()) }, { float(bed_bb.min.x()), float(bed_bb.min.y()), float(bed_bb.max.x()), float(bed_bb.max.y()) },
{ 0.0f, float(build_volume.printable_height()) } }); { 0.0f, float(build_volume.printable_height()) } });
break; break;
} }
case BuildVolume::Type::Circle: { case BuildVolume_Type::Circle: {
m_volumes.set_print_volume({ 1, // Circle m_volumes.set_print_volume({ 1, // Circle
{ unscaled<float>(build_volume.circle().center.x()), unscaled<float>(build_volume.circle().center.y()), unscaled<float>(build_volume.circle().radius + BuildVolume::SceneEpsilon), 0.0f }, { unscaled<float>(build_volume.circle().center.x()), unscaled<float>(build_volume.circle().center.y()), unscaled<float>(build_volume.circle().radius + BuildVolume::SceneEpsilon), 0.0f },
{ 0.0f, float(build_volume.printable_height() + BuildVolume::SceneEpsilon) } }); { 0.0f, float(build_volume.printable_height() + BuildVolume::SceneEpsilon) } });
break; break;
} }
default: default:
case BuildVolume::Type::Convex: case BuildVolume_Type::Convex:
case BuildVolume::Type::Custom: { case BuildVolume_Type::Custom: {
m_volumes.set_print_volume({ static_cast<int>(type), m_volumes.set_print_volume({ static_cast<int>(type),
{ -FLT_MAX, -FLT_MAX, FLT_MAX, FLT_MAX }, { -FLT_MAX, -FLT_MAX, FLT_MAX, FLT_MAX },
{ -FLT_MAX, FLT_MAX } } { -FLT_MAX, FLT_MAX } }

View file

@ -437,7 +437,8 @@ void PartPlate::calc_vertex_for_number(int index, bool one_number, GeometryBuffe
poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP + PARTPLATE_ICON_SIZE - offset_x), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP)- PARTPLATE_ICON_GAP - PARTPLATE_TEXT_OFFSET_Y)}); poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP + PARTPLATE_ICON_SIZE - offset_x), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP)- PARTPLATE_ICON_GAP - PARTPLATE_TEXT_OFFSET_Y)});
poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP + offset_x), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP)- PARTPLATE_ICON_GAP - PARTPLATE_TEXT_OFFSET_Y) }); poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP + offset_x), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP)- PARTPLATE_ICON_GAP - PARTPLATE_TEXT_OFFSET_Y) });
#else //in the bottom #else //in the bottom
Vec2d& p = m_shape[1]; auto bed_ext = get_extents(m_shape);
Vec2d p = bed_ext[1];
float offset_x = one_number?PARTPLATE_TEXT_OFFSET_X1: PARTPLATE_TEXT_OFFSET_X2; float offset_x = one_number?PARTPLATE_TEXT_OFFSET_X1: PARTPLATE_TEXT_OFFSET_X2;
poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x), scale_(p(1) + PARTPLATE_TEXT_OFFSET_Y) }); poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x), scale_(p(1) + PARTPLATE_TEXT_OFFSET_Y) });
@ -453,7 +454,11 @@ void PartPlate::calc_vertex_for_number(int index, bool one_number, GeometryBuffe
void PartPlate::calc_vertex_for_icons(int index, GeometryBuffer &buffer) void PartPlate::calc_vertex_for_icons(int index, GeometryBuffer &buffer)
{ {
ExPolygon poly; ExPolygon poly;
Vec2d& p = m_shape[2]; auto bed_ext = get_extents(m_shape);
Vec2d p = bed_ext[2];
if (m_plater->get_build_volume_type() == BuildVolume_Type::Circle)
p[1] -= std::max(
0.0, (bed_ext.size()(1) - 5 * PARTPLATE_ICON_SIZE - 4 * PARTPLATE_ICON_GAP_Y - PARTPLATE_ICON_GAP_TOP) / 2);
poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP - PARTPLATE_ICON_SIZE) }); poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP - PARTPLATE_ICON_SIZE) });
poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y)- PARTPLATE_ICON_GAP_TOP - PARTPLATE_ICON_SIZE) }); poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y)- PARTPLATE_ICON_GAP_TOP - PARTPLATE_ICON_SIZE) });
@ -468,7 +473,8 @@ void PartPlate::calc_vertex_for_icons(int index, GeometryBuffer &buffer)
void PartPlate::calc_vertex_for_icons_background(int icon_count, GeometryBuffer &buffer) void PartPlate::calc_vertex_for_icons_background(int icon_count, GeometryBuffer &buffer)
{ {
ExPolygon poly; ExPolygon poly;
Vec2d& p = m_shape[2]; auto bed_ext = get_extents(m_shape);
Vec2d p = bed_ext[2];
poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT), scale_(p(1) - icon_count * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP) }); poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT), scale_(p(1) - icon_count * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP) });
poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE), scale_(p(1) - icon_count * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y)- PARTPLATE_ICON_GAP_TOP) }); poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE), scale_(p(1) - icon_count * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y)- PARTPLATE_ICON_GAP_TOP) });
@ -1576,7 +1582,7 @@ void PartPlate::generate_plate_name_texture()
float offset_x = 1; float offset_x = 1;
w = int(factor * (m_name_texture.get_width() * 16) / m_name_texture.get_height()); w = int(factor * (m_name_texture.get_width() * 16) / m_name_texture.get_height());
h = int(factor * 16); h = int(factor * 16);
Vec2d p = m_shape[3] + Vec2d(0, h*0.6); Vec2d p = bed_ext[3] + Vec2d(0, h*0.6);
poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x), scale_(p(1) - h + PARTPLATE_TEXT_OFFSET_Y) }); poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x), scale_(p(1) - h + PARTPLATE_TEXT_OFFSET_Y) });
poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + w - offset_x), scale_(p(1) - h + PARTPLATE_TEXT_OFFSET_Y) }); poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + w - offset_x), scale_(p(1) - h + PARTPLATE_TEXT_OFFSET_Y) });
poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + w - offset_x), scale_(p(1) - PARTPLATE_TEXT_OFFSET_Y)}); poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + w - offset_x), scale_(p(1) - PARTPLATE_TEXT_OFFSET_Y)});

View file

@ -6862,8 +6862,8 @@ bool Plater::priv::has_assemble_view() const
#if ENABLE_ENHANCED_PRINT_VOLUME_FIT #if ENABLE_ENHANCED_PRINT_VOLUME_FIT
bool Plater::priv::can_scale_to_print_volume() const bool Plater::priv::can_scale_to_print_volume() const
{ {
const BuildVolume::Type type = this->bed.build_volume().type(); const BuildVolume_Type type = this->bed.build_volume().type();
return !view3D->get_canvas3d()->get_selection().is_empty() && (type == BuildVolume::Type::Rectangle || type == BuildVolume::Type::Circle); return !view3D->get_canvas3d()->get_selection().is_empty() && (type == BuildVolume_Type::Rectangle || type == BuildVolume_Type::Circle);
} }
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT #endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
@ -8369,6 +8369,7 @@ void Plater::calib_VFA(const Calib_Params& params)
p->background_process.fff_print()->set_calib_params(params); p->background_process.fff_print()->set_calib_params(params);
} }
BuildVolume_Type Plater::get_build_volume_type() const { return p->bed.get_build_volume_type(); }
void Plater::import_sl1_archive() void Plater::import_sl1_archive()
{ {
if (!p->m_ui_jobs.is_any_running()) if (!p->m_ui_jobs.is_any_running())

View file

@ -38,6 +38,7 @@ class Button;
namespace Slic3r { namespace Slic3r {
class BuildVolume; class BuildVolume;
enum class BuildVolume_Type : unsigned char;
class Model; class Model;
class ModelObject; class ModelObject;
enum class ModelObjectCutAttribute : int; enum class ModelObjectCutAttribute : int;
@ -236,6 +237,8 @@ public:
void calib_max_vol_speed(const Calib_Params& params); void calib_max_vol_speed(const Calib_Params& params);
void calib_VFA(const Calib_Params& params); void calib_VFA(const Calib_Params& params);
BuildVolume_Type get_build_volume_type() const;
//BBS: add only gcode mode //BBS: add only gcode mode
bool only_gcode_mode() { return m_only_gcode; } bool only_gcode_mode() { return m_only_gcode; }
void set_only_gcode(bool only_gcode) { m_only_gcode = only_gcode; } void set_only_gcode(bool only_gcode) { m_only_gcode = only_gcode; }

View file

@ -1234,8 +1234,8 @@ void Selection::scale_to_fit_print_volume(const BuildVolume& volume)
switch (volume.type()) switch (volume.type())
{ {
case BuildVolume::Type::Rectangle: { fit_rectangle(volume); break; } case BuildVolume_Type::Rectangle: { fit_rectangle(volume); break; }
case BuildVolume::Type::Circle: { fit_circle(volume); break; } case BuildVolume_Type::Circle: { fit_circle(volume); break; }
default: { break; } default: { break; }
} }
} }