From 301d0d5288d46f6328fd805e4104fde55a08eb15 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 22 Mar 2022 11:25:48 +0100 Subject: [PATCH] Cut WIP: * Processed Auto/Manual connetor's mode * Processed Dowel type of connectors * Added TriangeMesh::its_make_frustum_dowel --- src/libslic3r/Model.cpp | 128 +++++++++++++++++++-------- src/libslic3r/Model.hpp | 3 +- src/libslic3r/TriangleMesh.cpp | 55 ++++++++++++ src/libslic3r/TriangleMesh.hpp | 1 + src/slic3r/GUI/Gizmos/GLGizmoCut.cpp | 92 +++++++++++-------- src/slic3r/GUI/Gizmos/GLGizmoCut.hpp | 8 +- 6 files changed, 206 insertions(+), 81 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index dcb4c503a7..00c489ac13 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -712,6 +712,7 @@ ModelVolume* ModelObject::add_volume(const ModelVolume &other, ModelVolumeType t ModelVolume* v = new ModelVolume(this, other); if (type != ModelVolumeType::INVALID && v->type() != type) v->set_type(type); + v->source.is_connector = other.source.is_connector; this->volumes.push_back(v); // The volume should already be centered at this point of time when copying shared pointers of the triangle mesh and convex hull. // v->center_geometry_after_creation(); @@ -1336,29 +1337,42 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, ModelObjectCutAttr return res; } +indexed_triangle_set ModelObject::get_connector_mesh(CutConnectorAttributes connector_attributes) +{ + indexed_triangle_set connector_mesh; + + int sectorCount; + switch (CutConnectorShape(connector_attributes.shape)) { + case CutConnectorShape::Triangle: + sectorCount = 3; + break; + case CutConnectorShape::Square: + sectorCount = 4; + break; + case CutConnectorShape::Circle: + sectorCount = 360; + break; + case CutConnectorShape::Hexagon: + sectorCount = 6; + break; + } + + if (connector_attributes.style == CutConnectorStyle::Prizm) + connector_mesh = its_make_cylinder(1.0, 1.0, (2 * PI / sectorCount)); + else if (connector_attributes.type == CutConnectorType::Plug) + connector_mesh = its_make_cone(1.0, 1.0, (2 * PI / sectorCount)); + else + connector_mesh = its_make_frustum_dowel(1.0, 1.0, sectorCount); + + return connector_mesh; +} + void ModelObject::apply_cut_connectors(const std::string& name, CutConnectorAttributes connector_attributes) { if (cut_connectors.empty()) return; - bool is_prizm = connector_attributes.style == CutConnectorStyle::Prizm; - const std::function& its_make_shape = is_prizm ? its_make_cylinder : its_make_cone; - - indexed_triangle_set connector_mesh; - switch (CutConnectorShape(connector_attributes.shape)) { - case CutConnectorShape::Triangle: - connector_mesh = its_make_shape(1.0, 1.0, (2 * PI / 3)); - break; - case CutConnectorShape::Square: - connector_mesh = its_make_shape(1.0, 1.0, (2 * PI / 4)); - break; - case CutConnectorShape::Circle: - connector_mesh = its_make_shape(1.0, 1.0, 2 * PI / 360); - break; - case CutConnectorShape::Hexagon: - connector_mesh = its_make_shape(1.0, 1.0, (2 * PI / 6)); - break; - } + indexed_triangle_set connector_mesh = get_connector_mesh(connector_attributes); size_t connector_id = 0; @@ -1393,6 +1407,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const // Clone the object to duplicate instances, materials etc. ModelObject* upper = attributes.has(ModelObjectCutAttribute::KeepUpper) ? ModelObject::new_clone(*this) : nullptr; ModelObject* lower = attributes.has(ModelObjectCutAttribute::KeepLower) ? ModelObject::new_clone(*this) : nullptr; + ModelObject* dowels = attributes.has(ModelObjectCutAttribute::CreateDowels) ? ModelObject::new_clone(*this) : nullptr; if (attributes.has(ModelObjectCutAttribute::KeepUpper)) { upper->set_model(nullptr); @@ -1412,6 +1427,15 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const lower->input_file.clear(); } + if (attributes.has(ModelObjectCutAttribute::CreateDowels)) { + dowels->set_model(nullptr); + dowels->sla_support_points.clear(); + dowels->sla_drain_holes.clear(); + dowels->sla_points_status = sla::PointsStatus::NoPoints; + dowels->clear_volumes(); + dowels->input_file.clear(); + } + // Because transformations are going to be applied to meshes directly, // we reset transformation of all instances and volumes, // except for translation and Z-rotation on instances, which are preserved @@ -1450,29 +1474,31 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const volume->mmu_segmentation_facets.reset(); if (!volume->is_model_part()) { - // Modifiers are not cut, but we still need to add the instance transformation - // to the modifier volume transformation to preserve their shape properly. - // But if this modifier is a connector, then just set volume transformation - if (volume->source.is_connector) - volume->set_transformation(Geometry::Transformation(volume_matrix)); - else - volume->set_transformation(Geometry::Transformation(instance_matrix * volume_matrix)); - - ModelVolume* vol = { nullptr }; - if (attributes.has(ModelObjectCutAttribute::KeepUpper)) { - ModelVolume* vol = upper->add_volume(*volume); - if (volume->source.is_connector) - vol->source.is_connector = true; - } - if (attributes.has(ModelObjectCutAttribute::KeepLower)) { - ModelVolume* vol = lower->add_volume(*volume); - if (volume->source.is_connector) { - vol->source.is_connector = true; - // for lower part change type of conector from NEGATIVE_VOLUME to MODEL_PART - if (vol->type() == ModelVolumeType::NEGATIVE_VOLUME) + if (volume->source.is_connector) { + if (attributes.has(ModelObjectCutAttribute::KeepUpper)) + ModelVolume* vol = upper->add_volume(*volume); + if (attributes.has(ModelObjectCutAttribute::KeepLower)) { + ModelVolume* vol = lower->add_volume(*volume); + if (!attributes.has(ModelObjectCutAttribute::CreateDowels)) + // for lower part change type of connector from NEGATIVE_VOLUME to MODEL_PART if this connector is a plug vol->set_type(ModelVolumeType::MODEL_PART); } + if (attributes.has(ModelObjectCutAttribute::CreateDowels)) { + // add one more solid part same as connector if this connector is a dowel + // But discard rotation and Z-offset for this volume + volume->set_rotation(Vec3d::Zero()); + Vec3d offset = volume->get_offset(); + offset[Z] = 0.0; + volume->set_offset(offset); + + ModelVolume* vol = dowels->add_volume(*volume); + vol->set_type(ModelVolumeType::MODEL_PART); + } } + else + // Modifiers are not cut, but we still need to add the instance transformation + // to the modifier volume transformation to preserve their shape properly. + volume->set_transformation(Geometry::Transformation(instance_matrix * volume_matrix)); } else if (!volume->mesh().empty() // && !volume->source.is_connector // we don't allow to cut a connectors @@ -1584,6 +1610,32 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const res.push_back(lower); } + if (attributes.has(ModelObjectCutAttribute::CreateDowels) && dowels->volumes.size() > 0) { + if (!dowels->origin_translation.isApprox(Vec3d::Zero()) && instances[instance]->get_offset().isApprox(Vec3d::Zero())) { + dowels->center_around_origin(); + dowels->translate_instances(-dowels->origin_translation); + dowels->origin_translation = Vec3d::Zero(); + } + else { + dowels->invalidate_bounding_box(); + dowels->center_around_origin(); + } + + dowels->name += "-Dowels"; + + // Reset instance transformation except offset and Z-rotation + for (size_t i = 0; i < instances.size(); ++i) { + auto& obj_instance = dowels->instances[i]; + const Vec3d offset = obj_instance->get_offset(); + const double rot_z = obj_instance->get_rotation().z(); + obj_instance->set_transformation(Geometry::Transformation()); + obj_instance->set_offset(offset); + obj_instance->set_rotation(Vec3d(0.0, 0.0, i == instance ? 0.0 : rot_z)); + } + + res.push_back(dowels); + } + BOOST_LOG_TRIVIAL(trace) << "ModelObject::cut - end"; return res; diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index c0b2e8e39f..c8ae063ecd 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -304,7 +304,7 @@ enum class ModelVolumeType : int { SUPPORT_ENFORCER, }; -enum class ModelObjectCutAttribute : int { KeepUpper, KeepLower, FlipLower }; +enum class ModelObjectCutAttribute : int { KeepUpper, KeepLower, FlipLower, CreateDowels }; using ModelObjectCutAttributes = enum_bitmask; ENABLE_ENUM_BITMASK_OPERATORS(ModelObjectCutAttribute); @@ -432,6 +432,7 @@ public: size_t facets_count() const; size_t parts_count() const; ModelObjectPtrs cut(size_t instance, coordf_t z, ModelObjectCutAttributes attributes); + static indexed_triangle_set get_connector_mesh(CutConnectorAttributes connector_attributes); void apply_cut_connectors(const std::string& name, CutConnectorAttributes connector_attributes); ModelObjectPtrs cut(size_t instance, const Vec3d& cut_center, const Vec3d& cut_rotation, ModelObjectCutAttributes attributes); void split(ModelObjectPtrs* new_objects); diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 0dffdaab0e..f98d7d4dcd 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -1053,6 +1053,61 @@ indexed_triangle_set its_make_sphere(double radius, double fa) return mesh; } +// Generates mesh for a frustum dowel centered about the origin, using the count of sectors +// Note: This function uses code for sphere generation, but for stackCount = 2; +indexed_triangle_set its_make_frustum_dowel(double radius, double h, int sectorCount) +{ + int stackCount = 2; + float sectorStep = float(2. * M_PI / sectorCount); + float stackStep = float(M_PI / stackCount); + + indexed_triangle_set mesh; + auto& vertices = mesh.vertices; + vertices.reserve((stackCount - 1) * sectorCount + 2); + for (int i = 0; i <= stackCount; ++i) { + // from pi/2 to -pi/2 + double stackAngle = 0.5 * M_PI - stackStep * i; + double xy = radius * cos(stackAngle); + double z = radius * sin(stackAngle); + if (i == 0 || i == stackCount) + vertices.emplace_back(Vec3f(float(xy), 0.f, float(h * sin(stackAngle)))); + else + for (int j = 0; j < sectorCount; ++j) { + // from 0 to 2pi + double sectorAngle = sectorStep * j; + vertices.emplace_back(Vec3d(xy * std::cos(sectorAngle), xy * std::sin(sectorAngle), z).cast()); + } + } + + auto& facets = mesh.indices; + facets.reserve(2 * (stackCount - 1) * sectorCount); + for (int i = 0; i < stackCount; ++i) { + // Beginning of current stack. + int k1 = (i == 0) ? 0 : (1 + (i - 1) * sectorCount); + int k1_first = k1; + // Beginning of next stack. + int k2 = (i == 0) ? 1 : (k1 + sectorCount); + int k2_first = k2; + for (int j = 0; j < sectorCount; ++j) { + // 2 triangles per sector excluding first and last stacks + int k1_next = k1; + int k2_next = k2; + if (i != 0) { + k1_next = (j + 1 == sectorCount) ? k1_first : (k1 + 1); + facets.emplace_back(k1, k2, k1_next); + } + if (i + 1 != stackCount) { + k2_next = (j + 1 == sectorCount) ? k2_first : (k2 + 1); + facets.emplace_back(k1_next, k2, k2_next); + } + k1 = k1_next; + k2 = k2_next; + } + } + + return mesh; +} + indexed_triangle_set its_convex_hull(const std::vector &pts) { std::vector dst_vertices; diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index 3f3af0261c..abf9cefb73 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -302,6 +302,7 @@ indexed_triangle_set its_make_cube(double x, double y, double z); indexed_triangle_set its_make_prism(float width, float length, float height); indexed_triangle_set its_make_cylinder(double r, double h, double fa=(2*PI/360)); indexed_triangle_set its_make_cone(double r, double h, double fa=(2*PI/360)); +indexed_triangle_set its_make_frustum_dowel(double r, double h, int sectorCount); indexed_triangle_set its_make_pyramid(float base, float height); indexed_triangle_set its_make_sphere(double radius, double fa); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 511622cf2d..411cebbb55 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -326,8 +326,10 @@ void GLGizmoCut3D::render_connect_type_radio_button(CutConnectorType type) { ImGui::SameLine(type == CutConnectorType::Plug ? m_label_width : 2*m_label_width); ImGui::PushItemWidth(m_control_width); - if (m_imgui->radio_button(m_connector_types[int(type)], m_connector_type == type)) + if (m_imgui->radio_button(m_connector_types[size_t(type)], m_connector_type == type)) { m_connector_type = type; + update_connector_shape(); + } } void GLGizmoCut3D::render_connect_mode_radio_button(CutConnectorMode mode) @@ -606,7 +608,7 @@ void GLGizmoCut3D::on_dragging(const UpdateData& data) set_center(starting_box_center + shift); } - else if (m_hover_id > m_group_id) + else if (m_hover_id > m_group_id && m_connector_mode == CutConnectorMode::Manual) { std::pair pos_and_normal; if (!unproject_on_cut_plane(data.mouse_pos.cast(), pos_and_normal)) @@ -669,7 +671,7 @@ void GLGizmoCut3D::on_render() if (!m_hide_cut_plane) { render_cut_plane(); render_cut_center_graber(); - if (m_mode == CutMode::cutPlanar) { + if (m_mode == size_t(CutMode::cutPlanar)) { if (m_hover_id < m_group_id) m_rotation_gizmo.render(); } @@ -716,10 +718,12 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit) bool revert_rotation{ false }; bool revert_move{ false }; - if (m_mode <= CutMode::cutByLine) { + CutConnectors& connectors = m_c->selection_info()->model_object()->cut_connectors; + + if (m_mode <= size_t(CutMode::cutByLine)) { ImGui::Separator(); - if (m_mode == CutMode::cutPlanar) { + if (m_mode == size_t(CutMode::cutPlanar)) { ImGui::AlignTextToFramePadding(); m_imgui->text(_L("Move center")); revert_move = render_revert_button("move"); @@ -748,11 +752,18 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit) ImGui::AlignTextToFramePadding(); m_imgui->text(_L("After cut")); ImGui::SameLine(m_label_width); - m_imgui->checkbox(_L("Keep upper part"), m_keep_upper); + + m_imgui->disabled_begin(!connectors.empty()); + + bool keep = true; + m_imgui->checkbox(_L("Keep upper part"), connectors.empty() ? m_keep_upper : keep); m_imgui->text(""); ImGui::SameLine(m_label_width); - m_imgui->checkbox(_L("Keep lower part"), m_keep_lower); + m_imgui->checkbox(_L("Keep lower part"), connectors.empty() ? m_keep_lower : keep); m_imgui->text(""); + + m_imgui->disabled_end(); + ImGui::SameLine(m_label_width); m_imgui->disabled_begin(!m_keep_lower); m_imgui->checkbox(_L("Rotate lower part upwards"), m_rotate_lower); @@ -779,7 +790,6 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit) if (render_combo(_u8L("Shape"), m_connector_shapes, m_connector_shape_id)) update_connector_shape(); - CutConnectors& connectors = m_c->selection_info()->model_object()->cut_connectors; if (render_double_input(_u8L("Depth ratio"), m_connector_depth_ratio)) for (auto& connector : connectors) connector.height = float(m_connector_depth_ratio); @@ -829,6 +839,9 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit) void GLGizmoCut3D::render_connectors(bool picking) { + if (m_connector_mode == CutConnectorMode::Auto) + return; + #if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_GL_SHADERS_ATTRIBUTES GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat_attr") : wxGetApp().get_shader("gouraud_light_attr"); @@ -863,6 +876,9 @@ void GLGizmoCut3D::render_connectors(bool picking) const Vec3d& instance_offset = mo->instances[m_c->selection_info()->get_active_instance()]->get_offset(); const float sla_shift = m_c->selection_info()->get_sla_shift(); + const ClippingPlane* cp = m_c->object_clipper()->get_clipping_plane(); + const Vec3d& normal = cp ? cp->get_normal() : Vec3d::Ones(); + for (size_t i = 0; i < cache_size; ++i) { const CutConnector& connector = connectors[i]; const bool& point_selected = m_selected[i]; @@ -883,15 +899,21 @@ void GLGizmoCut3D::render_connectors(bool picking) const_cast(&m_connector_shape)->set_color(-1, render_color); #endif // ENABLE_GLBEGIN_GLEND_REMOVAL + double height = connector.height; // recalculate connector position to world position Vec3d pos = connector.pos + instance_offset; + if (m_connector_type == CutConnectorType::Dowel && + m_connector_style == size_t(CutConnectorStyle::Prizm)) { + pos -= height * normal; + height *= 2; + } pos[Z] += sla_shift; #if ENABLE_GL_SHADERS_ATTRIBUTES const Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform( Vec3d(pos.x(), pos.y(), pos.z()), m_rotation_gizmo.get_rotation(), - Vec3d(connector.radius, connector.radius, connector.height), + Vec3d(connector.radius, connector.radius, height), Vec3d::Ones() ); shader->set_uniform("view_model_matrix", view_model_matrix); @@ -906,7 +928,7 @@ void GLGizmoCut3D::render_connectors(bool picking) glsafe(::glRotated(Geometry::rad2deg(angles.x()), 1.0, 0.0, 0.0)); glsafe(::glTranslated(0., 0., -0.5*connector.height)); - glsafe(::glScaled(connector.radius, connector.radius, connector.height)); + glsafe(::glScaled(connector.radius, connector.radius, height)); #endif // ENABLE_GL_SHADERS_ATTRIBUTES m_connector_shape.render(); @@ -947,26 +969,37 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) Vec3d cut_center_offset = m_plane_center - instance_offset; cut_center_offset[Z] -= first_glvolume->get_sla_shift_z(); + bool create_dowels_as_separate_object = false; if (0.0 < object_cut_z && can_perform_cut()) { ModelObject* mo = wxGetApp().plater()->model().objects[object_idx]; + const bool has_connectors = !mo->cut_connectors.empty(); // update connectors pos as offset of its center before cut performing - if (!mo->cut_connectors.empty()) { + if (has_connectors && m_connector_mode == CutConnectorMode::Manual) { for (CutConnector& connector : mo->cut_connectors) { connector.rotation = m_rotation_gizmo.get_rotation(); - // culculate shift of the connector center regarding to the position on the cut plane - Vec3d norm = m_grabbers[0].center - m_plane_center; - norm.normalize(); - Vec3d shift = norm * (0.5 * connector.height); - connector.pos += shift; + if (m_connector_style == size_t(CutConnectorStyle::Prizm)) { + if (m_connector_type == CutConnectorType::Dowel) + connector.height *= 2; + else { + // culculate shift of the connector center regarding to the position on the cut plane + Vec3d norm = m_grabbers[0].center - m_plane_center; + norm.normalize(); + Vec3d shift = norm * (0.5 * connector.height); + connector.pos += shift; + } + } } mo->apply_cut_connectors(_u8L("Connector"), CutConnectorAttributes(CutConnectorType(m_connector_type), CutConnectorStyle(m_connector_style), CutConnectorShape(m_connector_shape_id))); + if (m_connector_type == CutConnectorType::Dowel) + create_dowels_as_separate_object = true; } wxGetApp().plater()->cut(object_idx, instance_idx, cut_center_offset, m_rotation_gizmo.get_rotation(), - only_if(m_keep_upper, ModelObjectCutAttribute::KeepUpper) | - only_if(m_keep_lower, ModelObjectCutAttribute::KeepLower) | - only_if(m_rotate_lower, ModelObjectCutAttribute::FlipLower)); + only_if(has_connectors ? true : m_keep_upper, ModelObjectCutAttribute::KeepUpper) | + only_if(has_connectors ? true : m_keep_lower, ModelObjectCutAttribute::KeepLower) | + only_if(m_rotate_lower, ModelObjectCutAttribute::FlipLower) | + only_if(create_dowels_as_separate_object, ModelObjectCutAttribute::CreateDowels)); m_selected.clear(); } else { @@ -1025,24 +1058,7 @@ void GLGizmoCut3D::update_connector_shape() if (m_connector_shape.is_initialized()) m_connector_shape.reset(); - bool is_prizm = m_connector_style == size_t(CutConnectorStyle::Prizm); - const std::function& its_make_shape = is_prizm ? its_make_cylinder : its_make_cone; - - - switch (CutConnectorShape(m_connector_shape_id)) { - case CutConnectorShape::Triangle: - m_connector_shape.init_from(its_make_shape(1.0, 1.0, (2 * PI / 3))); - break; - case CutConnectorShape::Square: - m_connector_shape.init_from(its_make_shape(1.0, 1.0, (2 * PI / 4))); - break; - case CutConnectorShape::Circle: - m_connector_shape.init_from(its_make_shape(1.0, 1.0, 2 * PI / 360)); - break; - case CutConnectorShape::Hexagon: - m_connector_shape.init_from(its_make_shape(1.0, 1.0, (2 * PI / 6))); - break; - } + m_connector_shape.init_from(ModelObject::get_connector_mesh({ m_connector_type, CutConnectorStyle(m_connector_style), CutConnectorShape(m_connector_shape_id) })); } void GLGizmoCut3D::update_model_object() const @@ -1056,7 +1072,7 @@ void GLGizmoCut3D::update_model_object() const bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down) { - if (is_dragging()) + if (is_dragging() || m_connector_mode == CutConnectorMode::Auto || (!m_keep_upper || !m_keep_lower)) return false; CutConnectors& connectors = m_c->selection_info()->model_object()->cut_connectors; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp index a9552e5e7b..57be3c739f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp @@ -59,7 +59,7 @@ class GLGizmoCut3D : public GLGizmoBase Matrix3d m_rotation_matrix; Vec3d m_rotations{ Vec3d::Zero() }; - enum CutMode { + enum class CutMode { cutPlanar , cutByLine , cutGrig @@ -67,16 +67,16 @@ class GLGizmoCut3D : public GLGizmoBase //,cutModular }; - enum CutConnectorMode { + enum class CutConnectorMode { Auto , Manual }; std::vector m_modes; - size_t m_mode{ size_t(cutPlanar) }; + size_t m_mode{ size_t(CutMode::cutPlanar) }; std::vector m_connector_modes; - CutConnectorMode m_connector_mode{ Auto }; + CutConnectorMode m_connector_mode{ CutConnectorMode::Manual }; std::vector m_connector_types; CutConnectorType m_connector_type;