Prototype of scale to fit print volume command

This commit is contained in:
Enrico Turri 2019-05-22 14:42:38 +02:00
parent f70cc70626
commit 844e99f84e
6 changed files with 119 additions and 11 deletions

View File

@ -12,7 +12,7 @@
// Renders a small sphere in the center of the bounding box of the current selection when no gizmo is active
#define ENABLE_RENDER_SELECTION_CENTER 0
// Shows an imgui dialog with render related data
#define ENABLE_RENDER_STATISTICS 1
#define ENABLE_RENDER_STATISTICS 0
//====================
@ -47,7 +47,9 @@
// Enable saving textures on GPU in compressed format
#define ENABLE_COMPRESSED_TEXTURES 1
#define ENABLE_COMPRESSED_TEXTURES 0
// Enable scale object to fit print volume
#define ENABLE_SCALE_TO_FIT_PRINT_VOLUME 1
#endif // _technologies_h_

View File

@ -847,6 +847,19 @@ bool GLGizmosManager::on_char(wxKeyEvent& evt, GLCanvas3D& canvas)
break;
}
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
case 'F':
case 'f':
{
if (m_current == Scale)
{
wxGetApp().plater()->scale_selection_to_fit_print_volume();
processed = true;
}
break;
}
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
}
}

View File

@ -1286,7 +1286,10 @@ struct Plater::priv
void sla_optimize_rotation();
void split_object();
void split_volume();
bool background_processing_enabled() const { return this->get_config("background_processing") == "1"; }
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
void scale_selection_to_fit_print_volume();
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
bool background_processing_enabled() const { return this->get_config("background_processing") == "1"; }
void update_print_volume_state();
void schedule_background_process();
// Update background processing thread from the current config and Model.
@ -2346,6 +2349,13 @@ void Plater::priv::split_volume()
wxGetApp().obj_list()->split();
}
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
void Plater::priv::scale_selection_to_fit_print_volume()
{
this->view3D->get_canvas3d()->get_selection().scale_to_fit_print_volume(*config);
}
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
void Plater::priv::schedule_background_process()
{
delayed_error_message.clear();
@ -3008,6 +3018,11 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
sidebar->obj_list()->append_menu_item_fix_through_netfabb(menu);
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
append_menu_item(menu, wxID_ANY, _(L("Scale to print volume")), _(L("Scale the selected object to fit the print volume")),
[this](wxCommandEvent&) { scale_selection_to_fit_print_volume(); }, "", menu);
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
wxMenu* mirror_menu = new wxMenu();
if (mirror_menu == nullptr)
return false;
@ -3447,6 +3462,13 @@ bool Plater::is_selection_empty() const
return p->get_selection().is_empty() || p->get_selection().is_wipe_tower();
}
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
void Plater::scale_selection_to_fit_print_volume()
{
p->scale_selection_to_fit_print_volume();
}
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper, bool keep_lower, bool rotate_lower)
{
wxCHECK_RET(obj_idx < p->model.objects.size(), "obj_idx out of bounds");

View File

@ -162,6 +162,9 @@ public:
void decrease_instances(size_t num = 1);
void set_number_of_copies(/*size_t num*/);
bool is_selection_empty() const;
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
void scale_selection_to_fit_print_volume();
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
void cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper = true, bool keep_lower = true, bool rotate_lower = false);

View File

@ -662,14 +662,34 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type
{
GLVolume &volume = *(*m_volumes)[i];
if (is_single_full_instance()) {
assert(transformation_type.absolute());
if (transformation_type.world() && (std::abs(scale.x() - scale.y()) > EPSILON || std::abs(scale.x() - scale.z()) > EPSILON)) {
// Non-uniform scaling. Transform the scaling factors into the local coordinate system.
// This is only possible, if the instance rotation is mulitples of ninety degrees.
assert(Geometry::is_rotation_ninety_degrees(volume.get_instance_rotation()));
volume.set_instance_scaling_factor((volume.get_instance_transformation().get_matrix(true, false, true, true).matrix().block<3, 3>(0, 0).transpose() * scale).cwiseAbs());
} else
volume.set_instance_scaling_factor(scale);
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
if (transformation_type.relative())
{
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale);
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3);
// extracts scaling factors from the composed transformation
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
if (transformation_type.joint())
volume.set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
volume.set_instance_scaling_factor(new_scale);
}
else
{
#else
assert(transformation_type.absolute());
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
if (transformation_type.world() && (std::abs(scale.x() - scale.y()) > EPSILON || std::abs(scale.x() - scale.z()) > EPSILON)) {
// Non-uniform scaling. Transform the scaling factors into the local coordinate system.
// This is only possible, if the instance rotation is mulitples of ninety degrees.
assert(Geometry::is_rotation_ninety_degrees(volume.get_instance_rotation()));
volume.set_instance_scaling_factor((volume.get_instance_transformation().get_matrix(true, false, true, true).matrix().block<3, 3>(0, 0).transpose() * scale).cwiseAbs());
}
else
volume.set_instance_scaling_factor(scale);
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
}
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
}
else if (is_single_volume() || is_single_modifier())
volume.set_volume_scaling_factor(scale);
@ -713,6 +733,51 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type
this->set_bounding_boxes_dirty();
}
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
void Selection::scale_to_fit_print_volume(const DynamicPrintConfig& config)
{
if (is_empty() || (m_mode == Volume))
return;
// adds 1/100th of a mm on all sides to avoid false out of print volume detections due to floating-point roundings
Vec3d box_size = get_bounding_box().size() + 0.01 * Vec3d::Ones();
const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(config.option("bed_shape"));
if (opt != nullptr)
{
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values));
BoundingBoxf3 print_volume(Vec3d(unscale<double>(bed_box_2D.min(0)), unscale<double>(bed_box_2D.min(1)), 0.0), Vec3d(unscale<double>(bed_box_2D.max(0)), unscale<double>(bed_box_2D.max(1)), config.opt_float("max_print_height")));
Vec3d print_volume_size = print_volume.size();
double sx = (box_size(0) != 0.0) ? print_volume_size(0) / box_size(0) : 0.0;
double sy = (box_size(1) != 0.0) ? print_volume_size(1) / box_size(1) : 0.0;
double sz = (box_size(2) != 0.0) ? print_volume_size(2) / box_size(2) : 0.0;
if ((sx != 0.0) && (sy != 0.0) && (sz != 0.0))
{
double s = std::min(sx, std::min(sy, sz));
if (s != 1.0)
{
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();
// center selection on print bed
start_dragging();
translate(print_volume.center() - get_bounding_box().center());
wxGetApp().plater()->canvas3D()->do_move();
wxGetApp().obj_manipul()->set_dirty();
}
}
}
}
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
void Selection::mirror(Axis axis)
{
if (!m_valid)

View File

@ -287,6 +287,9 @@ 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_SCALE_TO_FIT_PRINT_VOLUME
void scale_to_fit_print_volume(const DynamicPrintConfig& config);
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
void mirror(Axis axis);
void translate(unsigned int object_idx, const Vec3d& displacement);