As an example of using the enum_bitmask infrastructure for type safe
sets of optional boolean parameters, the cut function "keep upper", "keep lower" and "flip lower" boolean parameters were converted into a single type safe enum_bitmask. Such a coding style is certainly wordier than the original code, but much safer and more readable than the error prone "boolean, boolean, boolean" function call parameter list.
This commit is contained in:
parent
0f3cabb5d9
commit
e4e8c5df12
6 changed files with 38 additions and 26 deletions
|
@ -376,7 +376,7 @@ int CLI::run(int argc, char **argv)
|
|||
o->cut(Z, m_config.opt_float("cut"), &out);
|
||||
}
|
||||
#else
|
||||
model.objects.front()->cut(0, m_config.opt_float("cut"), true, true, true);
|
||||
model.objects.front()->cut(0, m_config.opt_float("cut"), ModelObjectCutAttribute::KeepLower | ModelObjectCutAttribute::KeepUpper | ModelObjectCutAttribute::FlipLower);
|
||||
#endif
|
||||
model.delete_object(size_t(0));
|
||||
}
|
||||
|
|
|
@ -1143,17 +1143,18 @@ bool ModelObject::needed_repair() const
|
|||
return false;
|
||||
}
|
||||
|
||||
ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, bool keep_lower, bool rotate_lower)
|
||||
ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, ModelObjectCutAttributes attributes)
|
||||
{
|
||||
if (!keep_upper && !keep_lower) { return {}; }
|
||||
if (! attributes.has(ModelObjectCutAttribute::KeepUpper) && ! attributes.has(ModelObjectCutAttribute::KeepLower))
|
||||
return {};
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "ModelObject::cut - start";
|
||||
|
||||
// Clone the object to duplicate instances, materials etc.
|
||||
ModelObject* upper = keep_upper ? ModelObject::new_clone(*this) : nullptr;
|
||||
ModelObject* lower = keep_lower ? ModelObject::new_clone(*this) : nullptr;
|
||||
ModelObject* upper = attributes.has(ModelObjectCutAttribute::KeepUpper) ? ModelObject::new_clone(*this) : nullptr;
|
||||
ModelObject* lower = attributes.has(ModelObjectCutAttribute::KeepLower) ? ModelObject::new_clone(*this) : nullptr;
|
||||
|
||||
if (keep_upper) {
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepUpper)) {
|
||||
upper->set_model(nullptr);
|
||||
upper->sla_support_points.clear();
|
||||
upper->sla_drain_holes.clear();
|
||||
|
@ -1162,7 +1163,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
|
|||
upper->input_file.clear();
|
||||
}
|
||||
|
||||
if (keep_lower) {
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepLower)) {
|
||||
lower->set_model(nullptr);
|
||||
lower->sla_support_points.clear();
|
||||
lower->sla_drain_holes.clear();
|
||||
|
@ -1202,8 +1203,10 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
|
|||
|
||||
volume->set_transformation(Geometry::Transformation(instance_matrix * volume_matrix));
|
||||
|
||||
if (keep_upper) { upper->add_volume(*volume); }
|
||||
if (keep_lower) { lower->add_volume(*volume); }
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepUpper))
|
||||
upper->add_volume(*volume);
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepLower))
|
||||
lower->add_volume(*volume);
|
||||
}
|
||||
else if (! volume->mesh().empty()) {
|
||||
|
||||
|
@ -1223,19 +1226,19 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
|
|||
indexed_triangle_set upper_its, lower_its;
|
||||
mesh.require_shared_vertices();
|
||||
cut_mesh(mesh.its, float(z), &upper_its, &lower_its);
|
||||
if (keep_upper) {
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepUpper)) {
|
||||
upper_mesh = TriangleMesh(upper_its);
|
||||
upper_mesh.repair();
|
||||
upper_mesh.reset_repair_stats();
|
||||
}
|
||||
if (keep_lower) {
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepLower)) {
|
||||
lower_mesh = TriangleMesh(lower_its);
|
||||
lower_mesh.repair();
|
||||
lower_mesh.reset_repair_stats();
|
||||
}
|
||||
}
|
||||
|
||||
if (keep_upper && upper_mesh.facets_count() > 0) {
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepUpper) && upper_mesh.facets_count() > 0) {
|
||||
ModelVolume* vol = upper->add_volume(upper_mesh);
|
||||
vol->name = volume->name;
|
||||
// Don't copy the config's ID.
|
||||
|
@ -1244,7 +1247,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
|
|||
assert(vol->config.id() != volume->config.id());
|
||||
vol->set_material(volume->material_id(), *volume->material());
|
||||
}
|
||||
if (keep_lower && lower_mesh.facets_count() > 0) {
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepLower) && lower_mesh.facets_count() > 0) {
|
||||
ModelVolume* vol = lower->add_volume(lower_mesh);
|
||||
vol->name = volume->name;
|
||||
// Don't copy the config's ID.
|
||||
|
@ -1255,7 +1258,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
|
|||
|
||||
// Compute the lower part instances' bounding boxes to figure out where to place
|
||||
// the upper part
|
||||
if (keep_upper) {
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepUpper)) {
|
||||
for (size_t i = 0; i < instances.size(); i++) {
|
||||
lower_bboxes[i].merge(instances[i]->transform_mesh_bounding_box(lower_mesh, true));
|
||||
}
|
||||
|
@ -1266,7 +1269,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
|
|||
|
||||
ModelObjectPtrs res;
|
||||
|
||||
if (keep_upper && upper->volumes.size() > 0) {
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepUpper) && upper->volumes.size() > 0) {
|
||||
upper->invalidate_bounding_box();
|
||||
upper->center_around_origin();
|
||||
|
||||
|
@ -1286,7 +1289,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
|
|||
|
||||
res.push_back(upper);
|
||||
}
|
||||
if (keep_lower && lower->volumes.size() > 0) {
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepLower) && lower->volumes.size() > 0) {
|
||||
lower->invalidate_bounding_box();
|
||||
lower->center_around_origin();
|
||||
|
||||
|
@ -1297,7 +1300,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
|
|||
|
||||
instance->set_transformation(Geometry::Transformation());
|
||||
instance->set_offset(offset);
|
||||
instance->set_rotation(Vec3d(rotate_lower ? Geometry::deg2rad(180.0) : 0.0, 0.0, rot_z));
|
||||
instance->set_rotation(Vec3d(attributes.has(ModelObjectCutAttribute::FlipLower) ? Geometry::deg2rad(180.0) : 0.0, 0.0, rot_z));
|
||||
}
|
||||
|
||||
res.push_back(lower);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define slic3r_Model_hpp_
|
||||
|
||||
#include "libslic3r.h"
|
||||
#include "enum_bitmask.hpp"
|
||||
#include "Geometry.hpp"
|
||||
#include "ObjectID.hpp"
|
||||
#include "Point.hpp"
|
||||
|
@ -227,6 +228,10 @@ enum class ModelVolumeType : int {
|
|||
SUPPORT_ENFORCER,
|
||||
};
|
||||
|
||||
enum class ModelObjectCutAttribute : int { KeepUpper, KeepLower, FlipLower };
|
||||
using ModelObjectCutAttributes = enum_bitmask<ModelObjectCutAttribute>;
|
||||
ENABLE_ENUM_BITMASK_OPERATORS(ModelObjectCutAttribute);
|
||||
|
||||
// A printable object, possibly having multiple print volumes (each with its own set of parameters and materials),
|
||||
// and possibly having multiple modifier volumes, each modifier volume with its set of parameters and materials.
|
||||
// Each ModelObject may be instantiated mutliple times, each instance having different placement on the print bed,
|
||||
|
@ -345,7 +350,7 @@ public:
|
|||
size_t materials_count() const;
|
||||
size_t facets_count() const;
|
||||
bool needed_repair() const;
|
||||
ModelObjectPtrs cut(size_t instance, coordf_t z, bool keep_upper = true, bool keep_lower = true, bool rotate_lower = false); // Note: z is in world coordinates
|
||||
ModelObjectPtrs cut(size_t instance, coordf_t z, ModelObjectCutAttributes attributes);
|
||||
void split(ModelObjectPtrs* new_objects);
|
||||
void merge();
|
||||
// Support for non-uniform scaling of instances. If an instance is rotated by angles, which are not multiples of ninety degrees,
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/GUI/GUI_ObjectManipulation.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
@ -231,7 +232,10 @@ void GLGizmoCut::perform_cut(const Selection& selection)
|
|||
coordf_t object_cut_z = m_cut_z - first_glvolume->get_sla_shift_z();
|
||||
|
||||
if (object_cut_z > 0.)
|
||||
wxGetApp().plater()->cut(object_idx, instance_idx, object_cut_z, m_keep_upper, m_keep_lower, m_rotate_lower);
|
||||
wxGetApp().plater()->cut(object_idx, instance_idx, object_cut_z,
|
||||
only_if(m_keep_upper, ModelObjectCutAttribute::KeepUpper) |
|
||||
only_if(m_keep_lower, ModelObjectCutAttribute::KeepLower) |
|
||||
only_if(m_rotate_lower, ModelObjectCutAttribute::FlipLower));
|
||||
else {
|
||||
// the object is SLA-elevated and the plane is under it.
|
||||
}
|
||||
|
|
|
@ -5315,21 +5315,20 @@ void Plater::toggle_layers_editing(bool enable)
|
|||
wxPostEvent(canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING));
|
||||
}
|
||||
|
||||
void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper, bool keep_lower, bool rotate_lower)
|
||||
void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, ModelObjectCutAttributes attributes)
|
||||
{
|
||||
wxCHECK_RET(obj_idx < p->model.objects.size(), "obj_idx out of bounds");
|
||||
auto *object = p->model.objects[obj_idx];
|
||||
|
||||
wxCHECK_RET(instance_idx < object->instances.size(), "instance_idx out of bounds");
|
||||
|
||||
if (!keep_upper && !keep_lower) {
|
||||
if (! attributes.has(ModelObjectCutAttribute::KeepUpper) && ! attributes.has(ModelObjectCutAttribute::KeepLower))
|
||||
return;
|
||||
}
|
||||
|
||||
Plater::TakeSnapshot snapshot(this, _L("Cut by Plane"));
|
||||
|
||||
wxBusyCursor wait;
|
||||
const auto new_objects = object->cut(instance_idx, z, keep_upper, keep_lower, rotate_lower);
|
||||
const auto new_objects = object->cut(instance_idx, z, attributes);
|
||||
|
||||
remove(obj_idx);
|
||||
p->load_model_objects(new_objects);
|
||||
|
@ -5337,9 +5336,7 @@ void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_uppe
|
|||
Selection& selection = p->get_selection();
|
||||
size_t last_id = p->model.objects.size() - 1;
|
||||
for (size_t i = 0; i < new_objects.size(); ++i)
|
||||
{
|
||||
selection.add_object((unsigned int)(last_id - i), i == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Plater::export_gcode(bool prefer_removable)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "Selection.hpp"
|
||||
|
||||
#include "libslic3r/enum_bitmask.hpp"
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include "libslic3r/BoundingBox.hpp"
|
||||
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
||||
|
@ -24,6 +25,8 @@ namespace Slic3r {
|
|||
|
||||
class Model;
|
||||
class ModelObject;
|
||||
enum class ModelObjectCutAttribute : int;
|
||||
using ModelObjectCutAttributes = enum_bitmask<ModelObjectCutAttribute>;
|
||||
class ModelInstance;
|
||||
class Print;
|
||||
class SLAPrint;
|
||||
|
@ -204,7 +207,7 @@ public:
|
|||
void convert_unit(ConversionType conv_type);
|
||||
void toggle_layers_editing(bool enable);
|
||||
|
||||
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);
|
||||
void cut(size_t obj_idx, size_t instance_idx, coordf_t z, ModelObjectCutAttributes attributes);
|
||||
|
||||
void export_gcode(bool prefer_removable);
|
||||
void export_stl(bool extended = false, bool selection_only = false);
|
||||
|
|
Loading…
Reference in a new issue