Merge remote-tracking branch 'origin/et_print_volume_fit'
This commit is contained in:
commit
9868206eee
@ -91,5 +91,8 @@
|
||||
// an additional button can be used to set the keyboard focus into the slider
|
||||
// to allow the user to type in the desired value
|
||||
#define ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT (1 && ENABLE_2_4_0_BETA2)
|
||||
// Enable fit print volume command for circular printbeds
|
||||
#define ENABLE_ENHANCED_PRINT_VOLUME_FIT (1 && ENABLE_2_4_0_BETA2)
|
||||
|
||||
|
||||
#endif // _prusaslicer_technologies_h_
|
||||
|
@ -786,8 +786,14 @@ void MenuFactory::append_menu_item_change_extruder(wxMenu* menu)
|
||||
|
||||
void MenuFactory::append_menu_item_scale_selection_to_fit_print_volume(wxMenu* menu)
|
||||
{
|
||||
#if ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
append_menu_item(menu, wxID_ANY, _L("Scale to print volume"), _L("Scale the selected object to fit the print volume"),
|
||||
[](wxCommandEvent&) { plater()->scale_selection_to_fit_print_volume(); }, "", menu,
|
||||
[]() { return plater()->can_scale_to_print_volume(); }, m_parent);
|
||||
#else
|
||||
append_menu_item(menu, wxID_ANY, _L("Scale to print volume"), _L("Scale the selected object to fit the print volume"),
|
||||
[](wxCommandEvent&) { plater()->scale_selection_to_fit_print_volume(); }, "", menu);
|
||||
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
}
|
||||
|
||||
void MenuFactory::append_menu_items_convert_unit(wxMenu* menu, int insert_pos/* = 1*/)
|
||||
|
@ -1910,6 +1910,9 @@ struct Plater::priv
|
||||
bool can_reload_from_disk() const;
|
||||
bool can_replace_with_stl() const;
|
||||
bool can_split(bool to_objects) const;
|
||||
#if ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
bool can_scale_to_print_volume() const;
|
||||
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
|
||||
void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type);
|
||||
ThumbnailsList generate_thumbnails(const ThumbnailsParams& params, Camera::EType camera_type);
|
||||
@ -3075,7 +3078,11 @@ void Plater::priv::split_volume()
|
||||
|
||||
void Plater::priv::scale_selection_to_fit_print_volume()
|
||||
{
|
||||
#if ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
this->view3D->get_canvas3d()->get_selection().scale_to_fit_print_volume(this->bed.build_volume());
|
||||
#else
|
||||
this->view3D->get_canvas3d()->get_selection().scale_to_fit_print_volume(*config);
|
||||
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
}
|
||||
|
||||
void Plater::priv::schedule_background_process()
|
||||
@ -4543,6 +4550,14 @@ bool Plater::priv::can_split(bool to_objects) const
|
||||
return sidebar->obj_list()->is_splittable(to_objects);
|
||||
}
|
||||
|
||||
#if ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
bool Plater::priv::can_scale_to_print_volume() const
|
||||
{
|
||||
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);
|
||||
}
|
||||
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
|
||||
bool Plater::priv::layers_height_allowed() const
|
||||
{
|
||||
if (printer_technology != ptFFF)
|
||||
@ -6872,6 +6887,10 @@ bool Plater::can_reload_from_disk() const { return p->can_reload_from_disk(); }
|
||||
bool Plater::can_replace_with_stl() const { return p->can_replace_with_stl(); }
|
||||
bool Plater::can_mirror() const { return p->can_mirror(); }
|
||||
bool Plater::can_split(bool to_objects) const { return p->can_split(to_objects); }
|
||||
#if ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
bool Plater::can_scale_to_print_volume() const { return p->can_scale_to_print_volume(); }
|
||||
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
|
||||
const UndoRedo::Stack& Plater::undo_redo_stack_main() const { return p->undo_redo_stack_main(); }
|
||||
void Plater::clear_undo_redo_stack_main() { p->undo_redo_stack_main().clear(); }
|
||||
void Plater::enter_gizmos_stack() { p->enter_gizmos_stack(); }
|
||||
|
@ -322,6 +322,9 @@ public:
|
||||
bool can_replace_with_stl() const;
|
||||
bool can_mirror() const;
|
||||
bool can_split(bool to_objects) const;
|
||||
#if ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
bool can_scale_to_print_volume() const;
|
||||
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
|
||||
void msw_rescale();
|
||||
void sys_color_changed();
|
||||
|
@ -15,6 +15,9 @@
|
||||
#include "libslic3r/LocalesUtils.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#if ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
#include "libslic3r/BuildVolume.hpp"
|
||||
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
@ -948,6 +951,94 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type
|
||||
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
|
||||
}
|
||||
|
||||
#if ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
void Selection::scale_to_fit_print_volume(const BuildVolume& volume)
|
||||
{
|
||||
auto fit = [this](double s, const Vec3d& offset) {
|
||||
if (s <= 0.0 || s == 1.0)
|
||||
return;
|
||||
|
||||
wxGetApp().plater()->take_snapshot(_L("Scale To Fit"));
|
||||
|
||||
TransformationType type;
|
||||
type.set_world();
|
||||
type.set_relative();
|
||||
type.set_joint();
|
||||
|
||||
// apply scale
|
||||
start_dragging();
|
||||
scale(s * Vec3d::Ones(), type);
|
||||
wxGetApp().plater()->canvas3D()->do_scale(""); // avoid storing another snapshot
|
||||
|
||||
// center selection on print bed
|
||||
start_dragging();
|
||||
translate(offset);
|
||||
wxGetApp().plater()->canvas3D()->do_move(""); // avoid storing another snapshot
|
||||
|
||||
wxGetApp().obj_manipul()->set_dirty();
|
||||
};
|
||||
|
||||
auto fit_rectangle = [this, fit](const BuildVolume& volume) {
|
||||
const BoundingBoxf3 print_volume = volume.bounding_volume();
|
||||
const Vec3d print_volume_size = print_volume.size();
|
||||
|
||||
// adds 1/100th of a mm on all sides to avoid false out of print volume detections due to floating-point roundings
|
||||
const Vec3d box_size = get_bounding_box().size() + 0.02 * Vec3d::Ones();
|
||||
|
||||
const double sx = (box_size.x() != 0.0) ? print_volume_size.x() / box_size.x() : 0.0;
|
||||
const double sy = (box_size.y() != 0.0) ? print_volume_size.y() / box_size.y() : 0.0;
|
||||
const double sz = (box_size.z() != 0.0) ? print_volume_size.z() / box_size.z() : 0.0;
|
||||
|
||||
if (sx != 0.0 && sy != 0.0 && sz != 0.0)
|
||||
fit(std::min(sx, std::min(sy, sz)), print_volume.center() - get_bounding_box().center());
|
||||
};
|
||||
|
||||
auto fit_circle = [this, fit](const BuildVolume& volume) {
|
||||
const Geometry::Circled& print_circle = volume.circle();
|
||||
double print_circle_radius = unscale<double>(print_circle.radius);
|
||||
|
||||
if (print_circle_radius == 0.0)
|
||||
return;
|
||||
|
||||
Points points;
|
||||
double max_z = 0.0;
|
||||
for (unsigned int i : m_list) {
|
||||
const GLVolume& v = *(*m_volumes)[i];
|
||||
TriangleMesh hull_3d = *v.convex_hull();
|
||||
hull_3d.transform(v.world_matrix());
|
||||
max_z = std::max(max_z, hull_3d.bounding_box().size().z());
|
||||
const Polygon hull_2d = hull_3d.convex_hull();
|
||||
points.insert(points.end(), hull_2d.begin(), hull_2d.end());
|
||||
}
|
||||
|
||||
if (points.empty())
|
||||
return;
|
||||
|
||||
const Geometry::Circled circle = Geometry::smallest_enclosing_circle_welzl(points);
|
||||
// adds 1/100th of a mm on all sides to avoid false out of print volume detections due to floating-point roundings
|
||||
const double circle_radius = unscale<double>(circle.radius) + 0.01;
|
||||
|
||||
if (circle_radius == 0.0 || max_z == 0.0)
|
||||
return;
|
||||
|
||||
const double s = std::min(print_circle_radius / circle_radius, volume.max_print_height() / max_z);
|
||||
const Vec3d sel_center = get_bounding_box().center();
|
||||
const Vec3d offset = s * (Vec3d(unscale<double>(circle.center.x()), unscale<double>(circle.center.y()), 0.5 * max_z) - sel_center);
|
||||
const Vec3d print_center = { unscale<double>(print_circle.center.x()), unscale<double>(print_circle.center.y()), 0.5 * volume.max_print_height() };
|
||||
fit(s, print_center - (sel_center + offset));
|
||||
};
|
||||
|
||||
if (is_empty() || m_mode == Volume)
|
||||
return;
|
||||
|
||||
switch (volume.type())
|
||||
{
|
||||
case BuildVolume::Type::Rectangle: { fit_rectangle(volume); break; }
|
||||
case BuildVolume::Type::Circle: { fit_circle(volume); break; }
|
||||
default: { break; }
|
||||
}
|
||||
}
|
||||
#else
|
||||
void Selection::scale_to_fit_print_volume(const DynamicPrintConfig& config)
|
||||
{
|
||||
if (is_empty() || m_mode == Volume)
|
||||
@ -990,6 +1081,7 @@ void Selection::scale_to_fit_print_volume(const DynamicPrintConfig& config)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
|
||||
void Selection::mirror(Axis axis)
|
||||
{
|
||||
|
@ -17,6 +17,9 @@ class GLArrow;
|
||||
class GLCurvedArrow;
|
||||
class DynamicPrintConfig;
|
||||
class GLShaderProgram;
|
||||
#if ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
class BuildVolume;
|
||||
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
|
||||
using GLVolumePtrs = std::vector<GLVolume*>;
|
||||
using ModelObjectPtrs = std::vector<ModelObject*>;
|
||||
@ -320,7 +323,11 @@ public:
|
||||
void rotate(const Vec3d& rotation, TransformationType transformation_type);
|
||||
void flattening_rotate(const Vec3d& normal);
|
||||
void scale(const Vec3d& scale, TransformationType transformation_type);
|
||||
#if ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
void scale_to_fit_print_volume(const BuildVolume& volume);
|
||||
#else
|
||||
void scale_to_fit_print_volume(const DynamicPrintConfig& config);
|
||||
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
void mirror(Axis axis);
|
||||
|
||||
void translate(unsigned int object_idx, const Vec3d& displacement);
|
||||
|
Loading…
Reference in New Issue
Block a user