CutGizmo: Implemented validation of groove size/position

This commit is contained in:
YuSanka 2023-08-03 10:01:23 +02:00
parent ba25da571a
commit 4e74e4ecc0
2 changed files with 79 additions and 32 deletions

View File

@ -509,10 +509,8 @@ bool GLGizmoCut3D::render_cut_mode_combo()
m_contour_width = CutMode(m_mode) == CutMode::cutTongueAndGroove ? 0.f : 0.4f;
oc->set_behavior(m_connectors_editing, m_connectors_editing, double(m_contour_width));
}
if (m_use_TAG_mesh) {
m_plane.reset();
on_unregister_raycasters_for_picking();
}
if (m_use_TAG_mesh)
update_plane_model();
reset_cut_by_contours();
update_clipper();
check_and_update_connectors_state();
@ -921,6 +919,23 @@ indexed_triangle_set GLGizmoCut3D::its_make_groove_plane()
const float cut_plane_thiknes = 0.02f;// 0.02f * (float)get_grabber_mean_size(m_bounding_box); // cut_plane_thiknes
// Vertices of the groove used to detection if groove is valid
// They are written as:
// {left_ext_lower, left_nar_lower, left_ext_upper, left_nar_upper,
// right_ext_lower, right_nar_lower, right_ext_upper, right_nar_upper }
{
m_groove_vertices.clear();
m_groove_vertices.reserve(8);
m_groove_vertices.emplace_back(Vec3f(-ext_lower_x, -y, z_lower).cast<double>());
m_groove_vertices.emplace_back(Vec3f(-nar_lower_x, y, z_lower).cast<double>());
m_groove_vertices.emplace_back(Vec3f(-ext_upper_x, -y, z_upper).cast<double>());
m_groove_vertices.emplace_back(Vec3f(-nar_upper_x, y, z_upper).cast<double>());
m_groove_vertices.emplace_back(Vec3f( ext_lower_x, -y, z_lower).cast<double>());
m_groove_vertices.emplace_back(Vec3f( nar_lower_x, y, z_lower).cast<double>());
m_groove_vertices.emplace_back(Vec3f( ext_upper_x, -y, z_upper).cast<double>());
m_groove_vertices.emplace_back(Vec3f( nar_upper_x, y, z_upper).cast<double>());
}
// Different cases of groove plane:
@ -1211,7 +1226,7 @@ void GLGizmoCut3D::render_cut_plane()
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
if (m_use_TAG_mesh) {
ColorRGBA cp_clr = can_perform_cut() && has_valid_contour() ? CUT_PLANE_DEF_COLOR : CUT_PLANE_ERR_COLOR;
ColorRGBA cp_clr = can_perform_cut() && has_valid_groove() ? CUT_PLANE_DEF_COLOR : CUT_PLANE_ERR_COLOR;
if (m_mode == size_t(CutMode::cutTongueAndGroove))
cp_clr.a(cp_clr.a() - 0.1f);
m_plane.model.set_color(cp_clr);
@ -1718,6 +1733,14 @@ void GLGizmoCut3D::update_raycasters_for_picking_transform()
}
}
void GLGizmoCut3D::update_plane_model()
{
m_plane.reset();
on_unregister_raycasters_for_picking();
init_picking_models();
}
void GLGizmoCut3D::on_set_hover_id()
{
}
@ -2415,10 +2438,7 @@ void GLGizmoCut3D::render_debug_input_window(float x)
is_changed |= m_imgui->checkbox(("Render Cut plane as a full mesh"), m_use_TAG_mesh_full);
if (is_changed)
{
m_plane.reset();
on_unregister_raycasters_for_picking();
}
update_plane_model();
m_imgui->end();
return;
@ -2710,15 +2730,13 @@ void GLGizmoCut3D::reset_cut_by_contours()
m_part_selection = PartSelection();
if (CutMode(m_mode) == CutMode::cutTongueAndGroove) {
if (m_optimaze_groove_rendering && m_dragging)
if (m_optimaze_groove_rendering && m_dragging || !has_valid_groove())
return;
process_contours();
}
else {
m_invalid_groove = false;
else
toggle_model_objects_visibility();
}
}
void GLGizmoCut3D::process_contours()
{
@ -2734,10 +2752,8 @@ void GLGizmoCut3D::process_contours()
if (CutMode(m_mode) == CutMode::cutTongueAndGroove) {
ModelObjectPtrs cut_objects = perform_cut_with_groove(model_objects[object_idx], true);
if (!cut_objects.empty() && !m_invalid_groove)
if (!cut_objects.empty())
m_part_selection = PartSelection(cut_objects.front(), instance_idx);
else
m_invalid_groove = true;
}
else {
reset_cut_by_contours();
@ -2808,10 +2824,8 @@ void GLGizmoCut3D::render_groove_float_input(const std::string& label, float& in
m_imgui->disabled_end();
if (is_changed) {
if (m_use_TAG_mesh) {
m_plane.reset();
on_unregister_raycasters_for_picking();
}
if (m_use_TAG_mesh)
update_plane_model();
reset_cut_by_contours();
// Plater::TakeSnapshot snapshot(wxGetApp().plater(), format_wxstr("%1%: %2%", _L("Groove change"), label), UndoRedo::SnapshotType::GizmoAction);
}
@ -2848,10 +2862,8 @@ void GLGizmoCut3D::render_groove_angle_input(const std::string& label, float& in
m_imgui->disabled_end();
if (is_changed) {
if (m_use_TAG_mesh) {
m_plane.reset();
on_unregister_raycasters_for_picking();
}
if (m_use_TAG_mesh)
update_plane_model();
reset_cut_by_contours();
// Plater::TakeSnapshot snapshot(wxGetApp().plater(), format_wxstr("%1%: %2%", _L("Groove change"), label), UndoRedo::SnapshotType::GizmoAction);
}
@ -3129,7 +3141,7 @@ void GLGizmoCut3D::render_input_window_warning() const
m_imgui->text(wxString(ImGui::WarningMarkerSmall) + _L("Select at least one object to keep after cutting."));
if (!has_valid_contour())
m_imgui->text(wxString(ImGui::WarningMarkerSmall) + _L("Cut plane is placed out of object"));
if (m_invalid_groove)
else if (!has_valid_groove())
m_imgui->text(wxString(ImGui::WarningMarkerSmall) + _L("Cut plane with groove is invalid"));
}
@ -3362,7 +3374,7 @@ bool GLGizmoCut3D::can_perform_cut() const
if (CutMode(m_mode) == CutMode::cutTongueAndGroove) {
const float flaps_width = -2.f * m_groove_depth / tan(m_groove_flaps_angle);
return flaps_width < m_groove_width && !m_invalid_groove && has_valid_contour();
return flaps_width < m_groove_width && has_valid_groove();
}
if (m_part_selection.valid())
@ -3371,6 +3383,39 @@ bool GLGizmoCut3D::can_perform_cut() const
return true;
}
bool GLGizmoCut3D::has_valid_groove() const
{
if (CutMode(m_mode) != CutMode::cutTongueAndGroove)
return true;
const Selection& selection = m_parent.get_selection();
const auto&list = selection.get_volume_idxs();
// is more volumes selected?
if (list.empty())
return false;
const Transform3d cp_matrix = translation_transform(m_plane_center) * m_rotation_m;
for (size_t id = 0; id < m_groove_vertices.size(); id += 2) {
const Vec3d beg = cp_matrix * m_groove_vertices[id];
const Vec3d end = cp_matrix * m_groove_vertices[id + 1];
bool intersection = false;
for (const unsigned int volume_idx : list) {
const GLVolume* glvol = selection.get_volume(volume_idx);
if (!glvol->is_modifier &&
glvol->mesh_raycaster->intersects_line(beg, end - beg, glvol->world_matrix())) {
intersection = true;
break;
}
}
if (!intersection)
return false;
}
return true;
}
bool GLGizmoCut3D::has_valid_contour() const
{
const auto clipper = m_c->object_clipper();
@ -3569,7 +3614,8 @@ ModelObjectPtrs GLGizmoCut3D::perform_cut_by_contour(ModelObject* cut_mo, const
ModelObjectPtrs GLGizmoCut3D::perform_cut_with_groove(ModelObject* cut_mo, bool keep_as_parts/* = false*/)
{
m_invalid_groove = false;
if (!has_valid_groove())
return {};
const Selection& selection = m_parent.get_selection();
const int instance_idx = selection.get_instance_idx();
@ -3684,9 +3730,6 @@ ModelObjectPtrs GLGizmoCut3D::perform_cut_with_groove(ModelObject* cut_mo, bool
invalid_added_volumes |= !add_volumes_from_cut(upper, ModelObjectCutAttribute::KeepLower, cut_part_ptrs);
if (keep_as_parts) {
if (!m_invalid_groove)
m_invalid_groove = upper->volumes.empty() || lower->volumes.empty() || invalid_added_volumes;
// add volumes from lower object to the upper, but mark them as a lower
const auto& volumes = lower->volumes;
for (const ModelVolume* volume : volumes) {

View File

@ -109,8 +109,6 @@ class GLGizmoCut3D : public GLGizmoBase
}
} m_info_stats;
bool m_invalid_groove{ false };
bool m_keep_upper{ true };
bool m_keep_lower{ true };
bool m_keep_as_parts{ false };
@ -163,6 +161,9 @@ class GLGizmoCut3D : public GLGizmoBase
bool m_was_cut_plane_dragged { false };
bool m_was_contour_selected { false };
// Vertices of the groove used to detection if groove is valid
std::vector<Vec3d> m_groove_vertices;
class PartSelection {
public:
PartSelection() = default;
@ -323,6 +324,8 @@ protected:
void set_volumes_picking_state(bool state);
void update_raycasters_for_picking_transform();
void update_plane_model();
void on_render_input_window(float x, float y, float bottom_limit) override;
bool wants_enter_leave_snapshots() const override { return true; }
@ -348,6 +351,7 @@ private:
void render_connectors();
bool can_perform_cut() const;
bool has_valid_groove() const;
bool has_valid_contour() const;
void apply_connectors_in_model(ModelObject* mo, int &dowels_count);
bool cut_line_processing() const;