mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-09-26 12:03:11 +08:00
WIP: Cut with Tongue and Groove
* Implemented preview rendering of groove
This commit is contained in:
parent
ceb9582cb1
commit
1aa8d8ea99
@ -1552,6 +1552,7 @@ void ModelObject::process_solid_part_cut(ModelVolume* volume, const Transform3d&
|
|||||||
if (attributes.has(ModelObjectCutAttribute::KeepAsParts)) {
|
if (attributes.has(ModelObjectCutAttribute::KeepAsParts)) {
|
||||||
add_cut_volume(upper_mesh, upper, volume, cut_matrix, "_A");
|
add_cut_volume(upper_mesh, upper, volume, cut_matrix, "_A");
|
||||||
add_cut_volume(lower_mesh, upper, volume, cut_matrix, "_B");
|
add_cut_volume(lower_mesh, upper, volume, cut_matrix, "_B");
|
||||||
|
upper->volumes.back()->cut_info.is_from_upper = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,6 +239,7 @@ enum class CutConnectorShape : int {
|
|||||||
, Square
|
, Square
|
||||||
, Hexagon
|
, Hexagon
|
||||||
, Circle
|
, Circle
|
||||||
|
, Rivet
|
||||||
, Undef
|
, Undef
|
||||||
//,D-shape
|
//,D-shape
|
||||||
};
|
};
|
||||||
@ -480,7 +481,7 @@ private:
|
|||||||
void process_solid_part_cut(ModelVolume* volume, const Transform3d& instance_matrix, const Transform3d& cut_matrix,
|
void process_solid_part_cut(ModelVolume* volume, const Transform3d& instance_matrix, const Transform3d& cut_matrix,
|
||||||
ModelObjectCutAttributes attributes, ModelObject* upper, ModelObject* lower);
|
ModelObjectCutAttributes attributes, ModelObject* upper, ModelObject* lower);
|
||||||
public:
|
public:
|
||||||
static void reset_instance_transformation(ModelObject* object, size_t src_instance_idx, const Transform3d& cut_matrix,
|
static void reset_instance_transformation(ModelObject* object, size_t src_instance_idx, const Transform3d& cut_matrix = Transform3d::Identity(),
|
||||||
bool place_on_cut = false, bool flip = false);
|
bool place_on_cut = false, bool flip = false);
|
||||||
|
|
||||||
ModelObjectPtrs cut(size_t instance, const Transform3d&cut_matrix, ModelObjectCutAttributes attributes);
|
ModelObjectPtrs cut(size_t instance, const Transform3d&cut_matrix, ModelObjectCutAttributes attributes);
|
||||||
@ -777,6 +778,7 @@ public:
|
|||||||
// It contains information about connetors
|
// It contains information about connetors
|
||||||
struct CutInfo
|
struct CutInfo
|
||||||
{
|
{
|
||||||
|
bool is_from_upper{ true };
|
||||||
bool is_connector{ false };
|
bool is_connector{ false };
|
||||||
bool is_processed{ true };
|
bool is_processed{ true };
|
||||||
CutConnectorType connector_type{ CutConnectorType::Plug };
|
CutConnectorType connector_type{ CutConnectorType::Plug };
|
||||||
@ -794,6 +796,7 @@ public:
|
|||||||
|
|
||||||
void set_processed() { is_processed = true; }
|
void set_processed() { is_processed = true; }
|
||||||
void invalidate() { is_connector = false; }
|
void invalidate() { is_connector = false; }
|
||||||
|
void reset_from_upper() { is_from_upper = true; }
|
||||||
|
|
||||||
template<class Archive> inline void serialize(Archive& ar) {
|
template<class Archive> inline void serialize(Archive& ar) {
|
||||||
ar(is_connector, is_processed, connector_type, radius_tolerance, height_tolerance);
|
ar(is_connector, is_processed, connector_type, radius_tolerance, height_tolerance);
|
||||||
@ -801,6 +804,9 @@ public:
|
|||||||
};
|
};
|
||||||
CutInfo cut_info;
|
CutInfo cut_info;
|
||||||
|
|
||||||
|
bool is_from_upper() const { return cut_info.is_from_upper; }
|
||||||
|
void reset_from_upper() { cut_info.reset_from_upper(); }
|
||||||
|
|
||||||
bool is_cut_connector() const { return cut_info.is_processed && cut_info.is_connector; }
|
bool is_cut_connector() const { return cut_info.is_processed && cut_info.is_connector; }
|
||||||
void invalidate_cut_info() { cut_info.invalidate(); }
|
void invalidate_cut_info() { cut_info.invalidate(); }
|
||||||
|
|
||||||
|
@ -184,6 +184,8 @@ GLGizmoCut3D::GLGizmoCut3D(GLCanvas3D& parent, const std::string& icon_filename,
|
|||||||
, m_connector_shape_id (int(CutConnectorShape::Circle))
|
, m_connector_shape_id (int(CutConnectorShape::Circle))
|
||||||
{
|
{
|
||||||
m_mode = size_t(CutMode::cutTongueAndGroove);
|
m_mode = size_t(CutMode::cutTongueAndGroove);
|
||||||
|
m_contour_width = .0f;
|
||||||
|
|
||||||
m_modes = { _u8L("Planar"), _u8L("Tongue and Groove")//, _u8L("Grid")
|
m_modes = { _u8L("Planar"), _u8L("Tongue and Groove")//, _u8L("Grid")
|
||||||
// , _u8L("Radial"), _u8L("Modular")
|
// , _u8L("Radial"), _u8L("Modular")
|
||||||
};
|
};
|
||||||
@ -1299,7 +1301,8 @@ void GLGizmoCut3D::set_center_pos(const Vec3d& center_pos, bool update_tbb /*=fa
|
|||||||
|
|
||||||
bool can_set_center_pos = false;
|
bool can_set_center_pos = false;
|
||||||
{
|
{
|
||||||
if (tbb.max.z() > -.5 && tbb.min.z() < .5)
|
double limit_val = CutMode(m_mode) == CutMode::cutTongueAndGroove ? 0.5 * double(m_groove_depth) : 0.5;
|
||||||
|
if (tbb.max.z() > -limit_val && tbb.min.z() < limit_val)
|
||||||
can_set_center_pos = true;
|
can_set_center_pos = true;
|
||||||
else {
|
else {
|
||||||
const double old_dist = (m_bb_center - m_plane_center).norm();
|
const double old_dist = (m_bb_center - m_plane_center).norm();
|
||||||
@ -1551,6 +1554,28 @@ GLGizmoCut3D::PartSelection::PartSelection(const ModelObject* mo, const Transfor
|
|||||||
m_valid = true;
|
m_valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLGizmoCut3D::PartSelection::PartSelection(const ModelObject* object, int instance_idx_in)
|
||||||
|
{
|
||||||
|
m_instance_idx = instance_idx_in;
|
||||||
|
|
||||||
|
m_model = Model();
|
||||||
|
// add upper object
|
||||||
|
m_model.add_object(*object);
|
||||||
|
|
||||||
|
m_parts.clear();
|
||||||
|
|
||||||
|
for (const ModelVolume* volume : object->volumes) {
|
||||||
|
assert(volume != nullptr);
|
||||||
|
m_parts.emplace_back(Part{ GLModel(), MeshRaycaster(volume->mesh()), true, !volume->is_model_part() });
|
||||||
|
m_parts.back().glmodel.init_from(volume->mesh());
|
||||||
|
|
||||||
|
// Now check whether this part is below or above the plane.
|
||||||
|
m_parts.back().selected = volume->is_from_upper();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
void GLGizmoCut3D::PartSelection::render(const Vec3d* normal, GLModel& sphere_model)
|
void GLGizmoCut3D::PartSelection::render(const Vec3d* normal, GLModel& sphere_model)
|
||||||
{
|
{
|
||||||
if (! valid())
|
if (! valid())
|
||||||
@ -1701,6 +1726,17 @@ void GLGizmoCut3D::on_render()
|
|||||||
m_c->selection_info()->set_use_shift(true);
|
m_c->selection_info()->set_use_shift(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// init part_selection for groove mode
|
||||||
|
if (CutMode(m_mode) == CutMode::cutTongueAndGroove)
|
||||||
|
{
|
||||||
|
if (!m_part_selection.valid())
|
||||||
|
process_contours();
|
||||||
|
|
||||||
|
m_contour_width = 0.f;
|
||||||
|
//check_and_update_connectors_state();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_contour_width = .4f;
|
||||||
|
|
||||||
update_clipper();
|
update_clipper();
|
||||||
|
|
||||||
@ -1988,6 +2024,9 @@ void GLGizmoCut3D::process_contours()
|
|||||||
const int instance_idx = selection.get_instance_idx();
|
const int instance_idx = selection.get_instance_idx();
|
||||||
const int object_idx = selection.get_object_idx();
|
const int object_idx = selection.get_object_idx();
|
||||||
|
|
||||||
|
if (CutMode(m_mode) == CutMode::cutTongueAndGroove)
|
||||||
|
m_part_selection = PartSelection(perform_cut_with_groove(model_objects[object_idx], true).front(), instance_idx);
|
||||||
|
else
|
||||||
m_part_selection = PartSelection(model_objects[object_idx], get_cut_matrix(selection), instance_idx, m_plane_center, m_cut_normal, *m_c->object_clipper());
|
m_part_selection = PartSelection(model_objects[object_idx], get_cut_matrix(selection), instance_idx, m_plane_center, m_cut_normal, *m_c->object_clipper());
|
||||||
m_parent.toggle_model_objects_visibility(false);
|
m_parent.toggle_model_objects_visibility(false);
|
||||||
}
|
}
|
||||||
@ -2069,8 +2108,10 @@ void GLGizmoCut3D::render_groove_input(const std::string& label, float& in_val,
|
|||||||
}
|
}
|
||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
//if (is_changed)
|
if (is_changed) {
|
||||||
|
reset_cut_by_contours();
|
||||||
// Plater::TakeSnapshot snapshot(wxGetApp().plater(), format_wxstr("%1%: %2%", _L("Groove change"), label), UndoRedo::SnapshotType::GizmoAction);
|
// Plater::TakeSnapshot snapshot(wxGetApp().plater(), format_wxstr("%1%: %2%", _L("Groove change"), label), UndoRedo::SnapshotType::GizmoAction);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
|
void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
|
||||||
@ -2228,7 +2269,7 @@ void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
|
|||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
m_imgui->disabled_begin(!m_is_contour_changed && !can_perform_cut());
|
m_imgui->disabled_begin(!can_perform_cut());
|
||||||
if(m_imgui->button(_L("Perform cut")))
|
if(m_imgui->button(_L("Perform cut")))
|
||||||
perform_cut(m_parent.get_selection());
|
perform_cut(m_parent.get_selection());
|
||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
@ -2324,8 +2365,6 @@ void GLGizmoCut3D::init_input_window_data(CutConnectors &connectors)
|
|||||||
|
|
||||||
void GLGizmoCut3D::render_input_window_warning() const
|
void GLGizmoCut3D::render_input_window_warning() const
|
||||||
{
|
{
|
||||||
if (m_is_contour_changed)
|
|
||||||
return;
|
|
||||||
if (! m_invalid_connectors_idxs.empty()) {
|
if (! m_invalid_connectors_idxs.empty()) {
|
||||||
wxString out = wxString(ImGui::WarningMarkerSmall) + _L("Invalid connectors detected") + ":";
|
wxString out = wxString(ImGui::WarningMarkerSmall) + _L("Invalid connectors detected") + ":";
|
||||||
if (m_info_stats.outside_cut_contour > size_t(0))
|
if (m_info_stats.outside_cut_contour > size_t(0))
|
||||||
@ -2472,7 +2511,7 @@ void GLGizmoCut3D::render_connectors()
|
|||||||
{
|
{
|
||||||
::glEnable(GL_DEPTH_TEST);
|
::glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
if (m_is_contour_changed || cut_line_processing() ||
|
if (cut_line_processing() ||
|
||||||
m_connector_mode == CutConnectorMode::Auto || !m_c->selection_info())
|
m_connector_mode == CutConnectorMode::Auto || !m_c->selection_info())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2548,15 +2587,16 @@ bool GLGizmoCut3D::can_perform_cut() const
|
|||||||
{
|
{
|
||||||
if (! m_invalid_connectors_idxs.empty() || (!m_keep_upper && !m_keep_lower) || m_connectors_editing)
|
if (! m_invalid_connectors_idxs.empty() || (!m_keep_upper && !m_keep_lower) || m_connectors_editing)
|
||||||
return false;
|
return false;
|
||||||
if (m_part_selection.valid())
|
|
||||||
return ! m_part_selection.is_one_object();
|
|
||||||
|
|
||||||
if (CutMode(m_mode) == CutMode::cutTongueAndGroove) {
|
if (CutMode(m_mode) == CutMode::cutTongueAndGroove) {
|
||||||
const float flaps_width = -2.f * m_groove_depth / tan(m_groove_angle);
|
const float flaps_width = -2.f * m_groove_depth / tan(m_groove_angle);
|
||||||
return flaps_width < m_groove_width;
|
return flaps_width < m_groove_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;// has_valid_contour();
|
if (m_part_selection.valid())
|
||||||
|
return ! m_part_selection.is_one_object();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLGizmoCut3D::has_valid_contour() const
|
bool GLGizmoCut3D::has_valid_contour() const
|
||||||
@ -2753,15 +2793,11 @@ ModelObjectPtrs GLGizmoCut3D::perform_cut_by_contour(ModelObject* cut_mo, const
|
|||||||
return cut_object_ptrs;
|
return cut_object_ptrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelObjectPtrs GLGizmoCut3D::perform_cut_with_groove(ModelObject* cut_mo, const ModelObjectCutAttributes& attributes)
|
ModelObjectPtrs GLGizmoCut3D::perform_cut_with_groove(ModelObject* cut_mo, bool keep_as_parts/* = false*/)
|
||||||
{
|
{
|
||||||
const Selection& selection = m_parent.get_selection();
|
const Selection& selection = m_parent.get_selection();
|
||||||
const int instance_idx = selection.get_instance_idx();
|
const int instance_idx = selection.get_instance_idx();
|
||||||
|
|
||||||
const ModelObjectCutAttributes groove_cut_attributes = ModelObjectCutAttribute::KeepUpper |
|
|
||||||
ModelObjectCutAttribute::KeepLower |
|
|
||||||
ModelObjectCutAttribute::KeepAsParts ;
|
|
||||||
|
|
||||||
// Clone the object to duplicate instances, materials etc.
|
// Clone the object to duplicate instances, materials etc.
|
||||||
ModelObject* upper{ nullptr };
|
ModelObject* upper{ nullptr };
|
||||||
cut_mo->clone_for_cut(&upper);
|
cut_mo->clone_for_cut(&upper);
|
||||||
@ -2772,25 +2808,31 @@ ModelObjectPtrs GLGizmoCut3D::perform_cut_with_groove(ModelObject* cut_mo, const
|
|||||||
|
|
||||||
const Transform3d cut_matrix = get_cut_matrix(selection);
|
const Transform3d cut_matrix = get_cut_matrix(selection);
|
||||||
|
|
||||||
Model tmp_model;
|
|
||||||
ModelObjectPtrs cut_part_ptrs;
|
ModelObjectPtrs cut_part_ptrs;
|
||||||
|
Model tmp_model = Model();
|
||||||
|
tmp_model.add_object(*cut_mo);
|
||||||
|
ModelObject* tmp_object = tmp_model.objects.front();
|
||||||
|
|
||||||
ModelObject* tmp_object{ nullptr };
|
auto add_volumes_from_cut = [](ModelObject* object, const ModelObjectCutAttribute attribute, const ModelObjectPtrs& cut_part_ptrs) {
|
||||||
cut_mo->clone_for_cut(&tmp_object);
|
const auto& volumes = cut_part_ptrs.front()->volumes;
|
||||||
|
for (const ModelVolume* volume : volumes)
|
||||||
|
if ((attribute == ModelObjectCutAttribute::KeepUpper && volume->is_from_upper()) ||
|
||||||
|
(attribute != ModelObjectCutAttribute::KeepUpper && !volume->is_from_upper()) ) {
|
||||||
|
ModelVolume* new_vol = object->add_volume(*volume);
|
||||||
|
new_vol->reset_from_upper();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
auto cut = [&tmp_model, instance_idx](ModelObject* object, const Transform3d& cut_matrix, bool leave_upper, ModelObjectPtrs& cut_part_ptrs) {
|
auto cut = [instance_idx, add_volumes_from_cut]
|
||||||
tmp_model = Model();
|
(ModelObject* object, const Transform3d& cut_matrix, const ModelObjectCutAttribute attribute, ModelObjectPtrs& cut_part_ptrs) {
|
||||||
tmp_model.add_object(*object);
|
Model model = Model();
|
||||||
cut_part_ptrs = tmp_model.objects.back()->cut(instance_idx, cut_matrix, ModelObjectCutAttribute::KeepUpper |
|
model.add_object(*object);
|
||||||
ModelObjectCutAttribute::KeepLower |
|
|
||||||
ModelObjectCutAttribute::KeepAsParts);
|
|
||||||
auto& volumes = cut_part_ptrs.front()->volumes;
|
|
||||||
|
|
||||||
|
cut_part_ptrs = model.objects.front()->cut(instance_idx, cut_matrix, ModelObjectCutAttribute::KeepUpper | ModelObjectCutAttribute::KeepLower | ModelObjectCutAttribute::KeepAsParts);
|
||||||
assert(cut_part_ptrs.size() == 1);
|
assert(cut_part_ptrs.size() == 1);
|
||||||
assert(volumes.size() == 2);
|
|
||||||
|
|
||||||
object->clear_volumes();
|
object->clear_volumes();
|
||||||
object->add_volume(*(leave_upper ? volumes.front() : volumes.back()));
|
add_volumes_from_cut(object, attribute, cut_part_ptrs);
|
||||||
ModelObject::reset_instance_transformation(object, instance_idx);
|
ModelObject::reset_instance_transformation(object, instance_idx);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2798,16 +2840,16 @@ ModelObjectPtrs GLGizmoCut3D::perform_cut_with_groove(ModelObject* cut_mo, const
|
|||||||
|
|
||||||
const Transform3d cut_matrix_upper = translation_transform(m_rotation_m * (groove_half_depth * Vec3d::UnitZ())) * cut_matrix;
|
const Transform3d cut_matrix_upper = translation_transform(m_rotation_m * (groove_half_depth * Vec3d::UnitZ())) * cut_matrix;
|
||||||
{
|
{
|
||||||
cut(cut_mo, cut_matrix_upper, false, cut_part_ptrs);
|
cut(tmp_object, cut_matrix_upper, ModelObjectCutAttribute::KeepLower, cut_part_ptrs);
|
||||||
upper->add_volume(*cut_part_ptrs.front()->volumes.front());
|
add_volumes_from_cut(upper, ModelObjectCutAttribute::KeepUpper, cut_part_ptrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// cut by lower plane
|
// cut by lower plane
|
||||||
|
|
||||||
const Transform3d cut_matrix_lower = translation_transform(m_rotation_m * (-groove_half_depth * Vec3d::UnitZ())) * cut_matrix;
|
const Transform3d cut_matrix_lower = translation_transform(m_rotation_m * (-groove_half_depth * Vec3d::UnitZ())) * cut_matrix;
|
||||||
{
|
{
|
||||||
cut(cut_mo, cut_matrix_lower, true, cut_part_ptrs);
|
cut(tmp_object, cut_matrix_lower, ModelObjectCutAttribute::KeepUpper, cut_part_ptrs);
|
||||||
lower->add_volume(*cut_part_ptrs.front()->volumes.back());
|
add_volumes_from_cut(lower, ModelObjectCutAttribute::KeepLower, cut_part_ptrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// cut middle part with 2 angles and add parts to related upper/lower objects
|
// cut middle part with 2 angles and add parts to related upper/lower objects
|
||||||
@ -2818,16 +2860,16 @@ ModelObjectPtrs GLGizmoCut3D::perform_cut_with_groove(ModelObject* cut_mo, const
|
|||||||
{
|
{
|
||||||
const Transform3d cut_matrix_angle1 = translation_transform(m_rotation_m * (-h_side_shift * Vec3d::UnitX())) * cut_matrix * rotation_transform(-m_groove_angle * Vec3d::UnitY());
|
const Transform3d cut_matrix_angle1 = translation_transform(m_rotation_m * (-h_side_shift * Vec3d::UnitX())) * cut_matrix * rotation_transform(-m_groove_angle * Vec3d::UnitY());
|
||||||
|
|
||||||
cut(cut_mo, cut_matrix_angle1, false, cut_part_ptrs);
|
cut(tmp_object, cut_matrix_angle1, ModelObjectCutAttribute::KeepLower, cut_part_ptrs);
|
||||||
lower->add_volume(*cut_part_ptrs.front()->volumes.front());
|
add_volumes_from_cut(lower, ModelObjectCutAttribute::KeepUpper, cut_part_ptrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// cut by angle2 plane
|
// cut by angle2 plane
|
||||||
{
|
{
|
||||||
const Transform3d cut_matrix_angle2 = translation_transform(m_rotation_m * (h_side_shift * Vec3d::UnitX())) * cut_matrix * rotation_transform(m_groove_angle * Vec3d::UnitY());
|
const Transform3d cut_matrix_angle2 = translation_transform(m_rotation_m * (h_side_shift * Vec3d::UnitX())) * cut_matrix * rotation_transform(m_groove_angle * Vec3d::UnitY());
|
||||||
|
|
||||||
cut(cut_mo, cut_matrix_angle2, false, cut_part_ptrs);
|
cut(tmp_object, cut_matrix_angle2, ModelObjectCutAttribute::KeepLower, cut_part_ptrs);
|
||||||
lower->add_volume(*cut_part_ptrs.front()->volumes.front());
|
add_volumes_from_cut(lower, ModelObjectCutAttribute::KeepUpper, cut_part_ptrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply tolerance to the middle part
|
// apply tolerance to the middle part
|
||||||
@ -2835,19 +2877,32 @@ ModelObjectPtrs GLGizmoCut3D::perform_cut_with_groove(ModelObject* cut_mo, const
|
|||||||
const double h_groove_shift_tolerance = groove_half_depth - (double)m_groove_depth_tolerance;
|
const double h_groove_shift_tolerance = groove_half_depth - (double)m_groove_depth_tolerance;
|
||||||
|
|
||||||
const Transform3d cut_matrix_lower_tolerance = translation_transform(m_rotation_m * (-h_groove_shift_tolerance * Vec3d::UnitZ())) * cut_matrix;
|
const Transform3d cut_matrix_lower_tolerance = translation_transform(m_rotation_m * (-h_groove_shift_tolerance * Vec3d::UnitZ())) * cut_matrix;
|
||||||
cut(cut_mo, cut_matrix_lower_tolerance, true, cut_part_ptrs);
|
cut(tmp_object, cut_matrix_lower_tolerance, ModelObjectCutAttribute::KeepUpper, cut_part_ptrs);
|
||||||
|
|
||||||
const double h_side_shift_tolerance = h_side_shift - 0.5 * double(m_groove_width_tolerance);
|
const double h_side_shift_tolerance = h_side_shift - 0.5 * double(m_groove_width_tolerance);
|
||||||
|
|
||||||
const Transform3d cut_matrix_angle1_tolerance = translation_transform(m_rotation_m * (-h_side_shift_tolerance * Vec3d::UnitX())) * cut_matrix * rotation_transform(-m_groove_angle * Vec3d::UnitY());
|
const Transform3d cut_matrix_angle1_tolerance = translation_transform(m_rotation_m * (-h_side_shift_tolerance * Vec3d::UnitX())) * cut_matrix * rotation_transform(-m_groove_angle * Vec3d::UnitY());
|
||||||
cut(cut_mo, cut_matrix_angle1_tolerance, false, cut_part_ptrs);
|
cut(tmp_object, cut_matrix_angle1_tolerance, ModelObjectCutAttribute::KeepLower, cut_part_ptrs);
|
||||||
|
|
||||||
const Transform3d cut_matrix_angle2_tolerance = translation_transform(m_rotation_m * (h_side_shift_tolerance * Vec3d::UnitX())) * cut_matrix * rotation_transform(m_groove_angle * Vec3d::UnitY());
|
const Transform3d cut_matrix_angle2_tolerance = translation_transform(m_rotation_m * (h_side_shift_tolerance * Vec3d::UnitX())) * cut_matrix * rotation_transform(m_groove_angle * Vec3d::UnitY());
|
||||||
cut(cut_mo, cut_matrix_angle2_tolerance, true, cut_part_ptrs);
|
cut(tmp_object, cut_matrix_angle2_tolerance, ModelObjectCutAttribute::KeepUpper, cut_part_ptrs);
|
||||||
|
}
|
||||||
|
|
||||||
// this part can be added to the upper object now
|
// this part can be added to the upper object now
|
||||||
upper->add_volume(*cut_part_ptrs.front()->volumes.back());
|
add_volumes_from_cut(upper, ModelObjectCutAttribute::KeepLower, cut_part_ptrs);
|
||||||
|
|
||||||
|
ModelObjectPtrs cut_object_ptrs;
|
||||||
|
|
||||||
|
if (keep_as_parts) {
|
||||||
|
// add volumes from lower object to the upper, but mark them as a lower
|
||||||
|
const auto& volumes = lower->volumes;
|
||||||
|
for (const ModelVolume* volume : volumes) {
|
||||||
|
ModelVolume* new_vol = upper->add_volume(*volume);
|
||||||
|
new_vol->cut_info.is_from_upper = false;
|
||||||
}
|
}
|
||||||
|
cut_object_ptrs.push_back(upper);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
auto add_cut_objects = [this, &instance_idx](ModelObjectPtrs& cut_objects, ModelObject* object, const Transform3d& cut_matrix) {
|
auto add_cut_objects = [this, &instance_idx](ModelObjectPtrs& cut_objects, ModelObject* object, const Transform3d& cut_matrix) {
|
||||||
if (object && !object->volumes.empty()) {
|
if (object && !object->volumes.empty()) {
|
||||||
@ -2856,8 +2911,6 @@ ModelObjectPtrs GLGizmoCut3D::perform_cut_with_groove(ModelObject* cut_mo, const
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ModelObjectPtrs cut_object_ptrs;
|
|
||||||
|
|
||||||
add_cut_objects(cut_object_ptrs, upper, cut_matrix_upper);
|
add_cut_objects(cut_object_ptrs, upper, cut_matrix_upper);
|
||||||
add_cut_objects(cut_object_ptrs, lower, cut_matrix_lower);
|
add_cut_objects(cut_object_ptrs, lower, cut_matrix_lower);
|
||||||
|
|
||||||
@ -2885,6 +2938,8 @@ ModelObjectPtrs GLGizmoCut3D::perform_cut_with_groove(ModelObject* cut_mo, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return cut_object_ptrs;
|
return cut_object_ptrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2943,7 +2998,7 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
|
|||||||
update_object_cut_id(cut_mo->cut_id, attributes, dowels_count);
|
update_object_cut_id(cut_mo->cut_id, attributes, dowels_count);
|
||||||
|
|
||||||
ModelObjectPtrs cut_object_ptrs = cut_by_contour ? perform_cut_by_contour(cut_mo, attributes, dowels_count) :
|
ModelObjectPtrs cut_object_ptrs = cut_by_contour ? perform_cut_by_contour(cut_mo, attributes, dowels_count) :
|
||||||
cut_with_groove ? perform_cut_with_groove(cut_mo, attributes) :
|
cut_with_groove ? perform_cut_with_groove(cut_mo) :
|
||||||
cut_mo->cut(instance_idx, cut_matrix, attributes);
|
cut_mo->cut(instance_idx, cut_matrix, attributes);
|
||||||
|
|
||||||
// save cut_id to post update synchronization
|
// save cut_id to post update synchronization
|
||||||
|
@ -138,7 +138,6 @@ class GLGizmoCut3D : public GLGizmoBase
|
|||||||
|
|
||||||
float m_contour_width{ 0.4f };
|
float m_contour_width{ 0.4f };
|
||||||
float m_cut_plane_radius_koef{ 1.5f };
|
float m_cut_plane_radius_koef{ 1.5f };
|
||||||
bool m_is_contour_changed{ false };
|
|
||||||
float m_shortcut_label_width{ -1.f };
|
float m_shortcut_label_width{ -1.f };
|
||||||
|
|
||||||
mutable std::vector<bool> m_selected; // which pins are currently selected
|
mutable std::vector<bool> m_selected; // which pins are currently selected
|
||||||
@ -154,6 +153,7 @@ class GLGizmoCut3D : public GLGizmoBase
|
|||||||
public:
|
public:
|
||||||
PartSelection() = default;
|
PartSelection() = default;
|
||||||
PartSelection(const ModelObject* mo, const Transform3d& cut_matrix, int instance_idx, const Vec3d& center, const Vec3d& normal, const CommonGizmosDataObjects::ObjectClipper& oc);
|
PartSelection(const ModelObject* mo, const Transform3d& cut_matrix, int instance_idx, const Vec3d& center, const Vec3d& normal, const CommonGizmosDataObjects::ObjectClipper& oc);
|
||||||
|
PartSelection(const ModelObject* mo, int instance_idx_in);
|
||||||
~PartSelection() { m_model.clear_objects(); }
|
~PartSelection() { m_model.clear_objects(); }
|
||||||
|
|
||||||
struct Part {
|
struct Part {
|
||||||
@ -342,7 +342,7 @@ private:
|
|||||||
void render_cut_plane_grabbers();
|
void render_cut_plane_grabbers();
|
||||||
void render_cut_line();
|
void render_cut_line();
|
||||||
ModelObjectPtrs perform_cut_by_contour(ModelObject* cut_mo, const ModelObjectCutAttributes& attributes, int dowels_count);
|
ModelObjectPtrs perform_cut_by_contour(ModelObject* cut_mo, const ModelObjectCutAttributes& attributes, int dowels_count);
|
||||||
ModelObjectPtrs perform_cut_with_groove(ModelObject* cut_mo, const ModelObjectCutAttributes& attributes);
|
ModelObjectPtrs perform_cut_with_groove(ModelObject* cut_mo, bool keep_as_parts = false);
|
||||||
void perform_cut(const Selection&selection);
|
void perform_cut(const Selection&selection);
|
||||||
void set_center_pos(const Vec3d¢er_pos, bool update_tbb = false);
|
void set_center_pos(const Vec3d¢er_pos, bool update_tbb = false);
|
||||||
void update_bb();
|
void update_bb();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user