Refactor planar cut code so it can be reused by other cut type

This commit is contained in:
Noisyfox
2026-05-10 20:01:50 +08:00
parent 1299fcef4a
commit a0d1ccaf28
2 changed files with 44 additions and 21 deletions

View File

@@ -8,7 +8,6 @@
#include "ObjectID.hpp"
#include <boost/log/trivial.hpp>
#include <optional>
namespace Slic3r {
@@ -62,9 +61,10 @@ static void add_cut_volume(TriangleMesh& mesh, ModelObject* object, const ModelV
assert(vol->config.id() != src_volume->config.id());
vol->set_material(src_volume->material_id(), *src_volume->material());
vol->cut_info = src_volume->cut_info;
vol->cut_info.source_volume = src_volume->id();
}
static void process_volume_cut( ModelVolume* volume, const Transform3d& instance_matrix, const Transform3d& cut_matrix,
static void process_volume_cut( const ModelVolume* volume, const Transform3d& instance_matrix, const Transform3d& cut_matrix,
ModelObjectCutAttributes attributes, TriangleMesh& upper_mesh, TriangleMesh& lower_mesh)
{
const auto volume_matrix = volume->get_matrix();
@@ -179,9 +179,8 @@ static void process_modifier_cut(ModelVolume* volume, const Transform3d& instanc
lower->add_volume(*volume);
}
static void process_solid_part_cut(ModelVolume* volume, const Transform3d& instance_matrix, const Transform3d& cut_matrix,
ModelObjectCutAttributes attributes, ModelObject* upper, ModelObject* lower,
const std::optional<TriangleSelector::SavedPainting>& saved_painting)
static void process_solid_part_cut(const ModelVolume* volume, const Transform3d& instance_matrix, const Transform3d& cut_matrix,
ModelObjectCutAttributes attributes, ModelObject* upper, ModelObject* lower)
{
// Perform cut
TriangleMesh upper_mesh, lower_mesh;
@@ -190,27 +189,19 @@ static void process_solid_part_cut(ModelVolume* volume, const Transform3d& insta
// Add required cut parts to the objects
if (attributes.has(ModelObjectCutAttribute::KeepAsParts)) {
if (!upper_mesh.empty()) {
add_cut_volume(upper_mesh, upper, volume, cut_matrix, "_A");
upper->volumes.back()->restore_painting(saved_painting);
}
add_cut_volume(upper_mesh, upper, volume, cut_matrix, "_A");
if (!lower_mesh.empty()) {
add_cut_volume(lower_mesh, upper, volume, cut_matrix, "_B");
upper->volumes.back()->cut_info.is_from_upper = false;
upper->volumes.back()->restore_painting(saved_painting);
}
return;
}
if (attributes.has(ModelObjectCutAttribute::KeepUpper) && !upper_mesh.empty()) {
if (attributes.has(ModelObjectCutAttribute::KeepUpper))
add_cut_volume(upper_mesh, upper, volume, cut_matrix);
upper->volumes.back()->restore_painting(saved_painting);
}
if (attributes.has(ModelObjectCutAttribute::KeepLower) && !lower_mesh.empty()) {
if (attributes.has(ModelObjectCutAttribute::KeepLower) && !lower_mesh.empty())
add_cut_volume(lower_mesh, lower, volume, cut_matrix);
lower->volumes.back()->restore_painting(saved_painting);
}
}
static void reset_instance_transformation(ModelObject* object, size_t src_instance_idx,
@@ -259,8 +250,12 @@ Cut::Cut(const ModelObject* object, int instance, const Transform3d& cut_matrix,
: m_instance(instance), m_cut_matrix(cut_matrix), m_attributes(attributes)
{
m_model = Model();
if (object)
m_model.add_object(*object);
if (object) {
const auto obj = m_model.add_object(*object);
for (int i = 0; i < obj->volumes.size(); i++) {
obj->volumes[i]->cut_info.source_volume = object->volumes[i]->id();
}
}
}
void Cut::post_process(ModelObject* object, ModelObjectPtrs& cut_object_ptrs, bool keep, bool place_on_cut, bool flip)
@@ -291,7 +286,20 @@ void Cut::post_process(ModelObject* upper, ModelObject* lower, ModelObjectPtrs&
void Cut::finalize(const ModelObjectPtrs& objects)
{
//clear model from temporarry objects
for (const auto obj : objects) {
for (const auto v : obj->volumes) {
if (v->cut_info.source_volume.valid()) {
for (const auto src : m_model.objects.front()->volumes) {
if (src->id() == v->cut_info.source_volume) {
v->cut_info.source_volume = src->cut_info.source_volume;
break;
}
}
}
}
}
//clear model from temporary objects
m_model.clear_objects();
// add to model result objects
@@ -350,8 +358,22 @@ const ModelObjectPtrs& Cut::perform_with_plane()
else
process_connector_cut(volume, instance_matrix, m_cut_matrix, m_attributes, upper, lower, dowels);
}
else if (!volume->mesh().empty())
process_solid_part_cut(volume, instance_matrix, m_cut_matrix, m_attributes, upper, lower, saved_painting);
else if (!volume->mesh().empty()) {
process_solid_part_cut(volume, instance_matrix, m_cut_matrix, m_attributes, upper, lower);
// Apply paint to volumes cut from current volume
if (saved_painting) {
auto apply_paint = [&saved_painting, &volume](const ModelObject* obj) {
for (const auto v : obj->volumes) {
if (v->cut_info.source_volume == volume->id()) {
v->restore_painting(saved_painting);
}
}
};
apply_paint(upper);
apply_paint(lower);
}
}
}
// Post-process cut parts

View File

@@ -825,6 +825,7 @@ public:
CutConnectorType connector_type{ CutConnectorType::Plug };
float radius_tolerance{ 0.f };// [0.f : 1.f]
float height_tolerance{ 0.f };// [0.f : 1.f]
ObjectID source_volume; // id of the volume from input model that this one is cut from
CutInfo() = default;
CutInfo(CutConnectorType type, float rad_tolerance, float h_tolerance, bool processed = false) :