OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::Cut Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/CutUtils.hpp>

Collaboration diagram for Slic3r::Cut:

Classes

struct  Groove
struct  Part

Public Member Functions

 Cut (const ModelObject *object, int instance, const Transform3d &cut_matrix, ModelObjectCutAttributes attributes=ModelObjectCutAttribute::KeepUpper|ModelObjectCutAttribute::KeepLower|ModelObjectCutAttribute::KeepAsParts)
 ~Cut ()
const ModelObjectPtrs & perform_with_plane ()
const ModelObjectPtrs & perform_by_contour (const ModelObject *src_object, std::vector< Part > parts, int dowels_count)
const ModelObjectPtrs & perform_with_groove (const Groove &groove, const Transform3d &rotation_m, const int groove_count, const float groove_gap, const float m_radius, bool keep_as_parts=false)

Static Public Member Functions

static float calculate_groove_width (const Cut::Groove &groove, const float m_radius)

Private Member Functions

void post_process (ModelObject *object, ModelObjectPtrs &objects, bool keep, bool place_on_cut, bool flip)
void post_process (ModelObject *upper_object, ModelObject *lower_object, ModelObjectPtrs &objects)
void finalize (const ModelObjectPtrs &objects, const std::vector< std::optional< TriangleSelector::SavedPainting > > &saved_paintings)

Private Attributes

Model m_model
int m_instance
const Transform3d m_cut_matrix
ModelObjectCutAttributes m_attributes

Detailed Description


Class Documentation

◆ Slic3r::Cut::Groove

struct Slic3r::Cut::Groove
Class Members
float angle { 0.f }
float angle_init { 0.f }
float depth { 0.f }
float depth_init { 0.f }
float depth_tolerance { 0.1f }
float flaps_angle { 0.f }
float flaps_angle_init { 0.f }
float width { 0.f }
float width_init { 0.f }
float width_tolerance { 0.1f }

◆ Slic3r::Cut::Part

struct Slic3r::Cut::Part
Class Members
bool is_modifier
bool selected

Constructor & Destructor Documentation

◆ Cut()

Slic3r::Cut::Cut ( const ModelObject * object,
int instance,
const Transform3d & cut_matrix,
ModelObjectCutAttributes attributes = ModelObjectCutAttribute::KeepUpper | ModelObjectCutAttribute::KeepLower | ModelObjectCutAttribute::KeepAsParts )
261 : m_instance(instance), m_cut_matrix(cut_matrix), m_attributes(attributes)
262{
263 m_model = Model();
264 if (object)
265 m_model.add_object(*object);
266}
ModelObjectCutAttributes m_attributes
Definition CutUtils.hpp:25
Model m_model
Definition CutUtils.hpp:22
int m_instance
Definition CutUtils.hpp:23
const Transform3d m_cut_matrix
Definition CutUtils.hpp:24

References m_attributes, m_cut_matrix, m_instance, and m_model.

Referenced by perform_by_contour(), and perform_with_groove().

Here is the caller graph for this function:

◆ ~Cut()

Slic3r::Cut::~Cut ( )
inline
37{ m_model.clear_objects(); }

References m_model.

Member Function Documentation

◆ calculate_groove_width()

float Slic3r::Cut::calculate_groove_width ( const Cut::Groove & groove,
const float m_radius )
static
781{
782 // Compute same slot outer width used in preview plane
783 const double flap_width = is_approx(groove.flaps_angle, 0.f) ? groove.depth : groove.depth / sin(groove.flaps_angle);
784 const double total_flap_width = 2.0 * flap_width * cos(groove.flaps_angle);
785 const double slot_neck_half_width = 0.5f * (groove.width);
786 const double slot_mouth_half_width = 0.5 * (groove.width + total_flap_width);
787 const double plane_half_height = 0.5f* (1.5f * (1.5f *m_radius));
788 const double flap_taper_offset = plane_half_height * tan(groove.angle);
789 const double slot_outer_x_max = std::max(slot_mouth_half_width + flap_taper_offset, slot_neck_half_width + flap_taper_offset);
790
791 return float(2.0 * slot_outer_x_max);
792}
constexpr bool is_approx(Number value, Number test_value, Number precision=EPSILON)
Definition libslic3r.h:320

References Slic3r::Cut::Groove::angle, Slic3r::Cut::Groove::depth, Slic3r::Cut::Groove::flaps_angle, Slic3r::is_approx(), and Slic3r::Cut::Groove::width.

Referenced by perform_with_groove(), and Slic3r::GUI::GLGizmoCut3D::render_cut_plane_input_window().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ finalize()

void Slic3r::Cut::finalize ( const ModelObjectPtrs & objects,
const std::vector< std::optional< TriangleSelector::SavedPainting > > & saved_paintings )
private
295{
296 // Paint volumes
297 for (const auto& saved_painting : saved_paintings) {
298 if (saved_painting) {
299 for (const auto object : objects) {
300 for (const auto volume : object->volumes) {
301 if (volume->is_model_part() && !volume->is_cut_connector()) {
302 volume->restore_painting(saved_painting, true);
303 }
304 }
305 }
306 }
307 }
308
309 //clear model from temporary objects
310 m_model.clear_objects();
311
312 // add to model result objects
313 m_model.objects = objects;
314}

References m_model, and Slic3r::ModelObject::volumes.

Referenced by perform_by_contour(), perform_with_groove(), and perform_with_plane().

Here is the caller graph for this function:

◆ perform_by_contour()

const ModelObjectPtrs & Slic3r::Cut::perform_by_contour ( const ModelObject * src_object,
std::vector< Part > parts,
int dowels_count )
470{
471 ModelObject* cut_mo = m_model.objects.front();
472
473 // Clone the object to duplicate instances, materials etc.
474 ModelObject* upper{ nullptr };
475 if (m_attributes.has(ModelObjectCutAttribute::KeepUpper)) cut_mo->clone_for_cut(&upper);
476 ModelObject* lower{ nullptr };
477 if (m_attributes.has(ModelObjectCutAttribute::KeepLower)) cut_mo->clone_for_cut(&lower);
478
479 if (upper && lower) {
480 upper->name = upper->name + "_A";
481 lower->name = lower->name + "_B";
482 }
483
484 // Save painting data so we later can remap it.
485 std::vector<std::optional<TriangleSelector::SavedPainting>> saved_paintings;
487 const auto instance_matrix = src_object->instances[m_instance]->get_transformation().get_matrix_no_offset();
488 for (const auto volume : src_object->volumes) {
489 saved_paintings.emplace_back(volume->save_painting());
490 if (saved_paintings.back()) {
491 // Transform mesh to cut space (same transform as process_volume_cut applies)
492 saved_paintings.back()->mesh.transform(instance_matrix * volume->get_matrix(), true);
493 }
494 }
495 }
496
497 const size_t cut_parts_cnt = parts.size();
498 bool has_modifiers = false;
499
500 // Distribute SolidParts to the Upper/Lower object
501 for (size_t id = 0; id < cut_parts_cnt; ++id) {
502 if (parts[id].is_modifier)
503 has_modifiers = true; // modifiers will be added later to the related parts
504 else if (ModelObject* obj = (parts[id].selected ? upper : lower))
505 obj->add_volume(*(cut_mo->volumes[id]));
506 }
507
508 if (has_modifiers) {
509 // Distribute Modifiers to the Upper/Lower object
510 distribute_modifiers_from_object(cut_mo, m_instance, upper, lower);
511 }
512
513 ModelObjectPtrs cut_object_ptrs;
514
515 ModelVolumePtrs& volumes = cut_mo->volumes;
516 if (volumes.size() == cut_parts_cnt) {
517 // Means that object is cut without connectors
518
519 // Just add Upper and Lower objects to cut_object_ptrs
520 post_process(upper, lower, cut_object_ptrs);
521
522 // Now merge all model parts together:
523 merge_solid_parts_inside_object(cut_object_ptrs);
524
525 // replace initial objects in model with cut object
526 finalize(cut_object_ptrs, saved_paintings);
527 }
528 else if (volumes.size() > cut_parts_cnt) {
529 // Means that object is cut with connectors
530
531 // All volumes are distributed to Upper / Lower object,
532 // So we don’t need them anymore
533 for (size_t id = 0; id < cut_parts_cnt; id++)
534 delete* (volumes.begin() + id);
535 volumes.erase(volumes.begin(), volumes.begin() + cut_parts_cnt);
536
537 // Perform cut just to get connectors
539 const ModelObjectPtrs& cut_connectors_obj = cut.perform_with_plane();
540 assert(dowels_count > 0 ? cut_connectors_obj.size() >= 3 : cut_connectors_obj.size() == 2);
541
542 // Connectors from upper object
543 for (const ModelVolume* volume : cut_connectors_obj[0]->volumes)
544 upper->add_volume(*volume, volume->type());
545
546 // Connectors from lower object
547 for (const ModelVolume* volume : cut_connectors_obj[1]->volumes)
548 lower->add_volume(*volume, volume->type());
549
550 // Add Upper and Lower objects to cut_object_ptrs
551 post_process(upper, lower, cut_object_ptrs);
552
553 // Now merge all model parts together:
554 merge_solid_parts_inside_object(cut_object_ptrs);
555
556 // replace initial objects in model with cut object
557 finalize(cut_object_ptrs, saved_paintings);
558
559 // Add Dowel-connectors as separate objects to model
560 if (cut_connectors_obj.size() >= 3)
561 for (size_t id = 2; id < cut_connectors_obj.size(); id++)
562 m_model.add_object(*cut_connectors_obj[id]);
563 }
564
565 return m_model.objects;
566}
void post_process(ModelObject *object, ModelObjectPtrs &objects, bool keep, bool place_on_cut, bool flip)
Definition CutUtils.cpp:268
Cut(const ModelObject *object, int instance, const Transform3d &cut_matrix, ModelObjectCutAttributes attributes=ModelObjectCutAttribute::KeepUpper|ModelObjectCutAttribute::KeepLower|ModelObjectCutAttribute::KeepAsParts)
Definition CutUtils.cpp:259
void finalize(const ModelObjectPtrs &objects, const std::vector< std::optional< TriangleSelector::SavedPainting > > &saved_paintings)
Definition CutUtils.cpp:294
static void merge_solid_parts_inside_object(ModelObjectPtrs &objects)
Definition CutUtils.cpp:441
static void distribute_modifiers_from_object(ModelObject *from_obj, const int instance_idx, ModelObject *to_obj1, ModelObject *to_obj2)
Definition CutUtils.cpp:421
@ KeepPaint
Definition CutUtils.hpp:15
@ KeepLower
Definition CutUtils.hpp:15
@ KeepUpper
Definition CutUtils.hpp:15
std::vector< ModelVolume * > ModelVolumePtrs
Definition Model.hpp:139
std::vector< ModelObject * > ModelObjectPtrs
Definition CutUtils.hpp:13

References Cut(), Slic3r::ModelObject::add_volume(), Slic3r::ModelObject::clone_for_cut(), Slic3r::distribute_modifiers_from_object(), finalize(), Slic3r::ModelObject::instances, Slic3r::KeepLower, Slic3r::KeepPaint, Slic3r::KeepUpper, m_attributes, m_cut_matrix, m_instance, m_model, Slic3r::merge_solid_parts_inside_object(), Slic3r::ModelObject::name, perform_with_plane(), post_process(), and Slic3r::ModelObject::volumes.

Referenced by Slic3r::GUI::GLGizmoCut3D::perform_cut().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ perform_with_groove()

const ModelObjectPtrs & Slic3r::Cut::perform_with_groove ( const Groove & groove,
const Transform3d & rotation_m,
const int groove_count,
const float groove_gap,
const float m_radius,
bool keep_as_parts = false )
575{
576 ModelObject* cut_mo = m_model.objects.front();
577
578 // Clone the object to duplicate instances, materials etc.
579 ModelObject* upper{ nullptr };
580 cut_mo->clone_for_cut(&upper);
581 ModelObject* lower{ nullptr };
582 cut_mo->clone_for_cut(&lower);
583
584 if (upper && lower) {
585 upper->name = upper->name + "_A";
586 lower->name = lower->name + "_B";
587 }
588
589 // Save painting data so we later can remap it.
590 std::vector<std::optional<TriangleSelector::SavedPainting>> saved_paintings;
592 const auto instance_matrix = cut_mo->instances[m_instance]->get_transformation().get_matrix_no_offset();
593 for (const auto volume : cut_mo->volumes) {
594 saved_paintings.emplace_back(volume->save_painting());
595 if (saved_paintings.back()) {
596 // Transform mesh to cut space (same transform as process_volume_cut applies)
597 saved_paintings.back()->mesh.transform(instance_matrix * volume->get_matrix(), true);
598 }
599 }
600 }
601
602 const double groove_half_depth = 0.5 * double(groove.depth);
603
604 Model tmp_model_for_cut = Model();
605
606 Model tmp_model = Model();
607 tmp_model.add_object(*cut_mo);
608 ModelObject* tmp_object = tmp_model.objects.front();
609
610 auto add_volumes_from_cut = [](ModelObject* object, const ModelObjectCutAttribute attribute, const Model& tmp_model_for_cut) {
611 const auto& volumes = tmp_model_for_cut.objects.front()->volumes;
612 for (const ModelVolume* volume : volumes)
613 if (volume->is_model_part()) {
614 if ((attribute == ModelObjectCutAttribute::KeepUpper && volume->is_from_upper()) ||
615 (attribute != ModelObjectCutAttribute::KeepUpper && !volume->is_from_upper())) {
616 ModelVolume* new_vol = object->add_volume(*volume);
617 new_vol->reset_from_upper();
618 }
619 }
620 };
621
622 auto cut = [this, add_volumes_from_cut]
623 (ModelObject* object, const Transform3d& cut_matrix, const ModelObjectCutAttribute add_volumes_attribute, Model& tmp_model_for_cut) {
624 Cut cut(object, m_instance, cut_matrix);
625
626 tmp_model_for_cut = Model();
627 tmp_model_for_cut.add_object(*cut.perform_with_plane().front());
628 assert(!tmp_model_for_cut.objects.empty());
629
630 object->clear_volumes();
631 add_volumes_from_cut(object, add_volumes_attribute, tmp_model_for_cut);
633 };
634
635 // cut by upper plane (+Z)
636 {
637 const Transform3d cut_matrix_upper = translation_transform(rotation_m * (groove_half_depth * Vec3d::UnitZ())) * m_cut_matrix;
638
639 cut(tmp_object, cut_matrix_upper, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
640 add_volumes_from_cut(upper, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
641 }
642
643 // cut by lower plane (-Z)
644 {
645 const Transform3d cut_matrix_lower = translation_transform(rotation_m * (-groove_half_depth * Vec3d::UnitZ())) * m_cut_matrix;
646
647 cut(tmp_object, cut_matrix_lower, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
648 add_volumes_from_cut(lower, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
649 }
650
651 // Compute same slot outer width used in preview plane
652 const float groove_width = calculate_groove_width(groove, m_radius);
653
654 ModelObject* groove_object{nullptr};
655
656 // multiple cuts
657 for (int i = 0; i < groove_count; i++) {
658 bool is_first_groove = i == 0;
659 bool is_last_groove = i == groove_count - 1;
660
661 // Calculate the x-axis offset for this dovetail
662 float groove_offset_factor_start = -.5 * ((groove_count - 1));
663 float groove_offset_factor = groove_offset_factor_start + i;
664
665 float offset_x = groove_offset_factor * (groove_gap + groove_width);
666
667
668 tmp_object->clone_for_cut(&groove_object);
669 for (ModelVolume* volume : tmp_object->volumes) {
670 ModelVolume* new_vol = groove_object->add_volume(*volume);
671 new_vol->reset_from_upper();
672 }
673
674 // isolate area of current groove
675 if (!is_first_groove) {
676 float left_cut_position = (-groove_gap / 2.f) - (groove_width / 2.f) + offset_x;
677
678 const Transform3d cut_matrix_left = translation_transform(rotation_m * (left_cut_position * Vec3d::UnitX())) *
680
681 cut(groove_object, cut_matrix_left, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
682 }
683 if (!is_last_groove) {
684 float right_cut_position = (groove_gap / 2.f) + (groove_width / 2.f) + offset_x;
685
686 const Transform3d cut_matrix_right = translation_transform(rotation_m * (right_cut_position * Vec3d::UnitX())) *
688 cut(groove_object, cut_matrix_right, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
689 }
690
691 const Transform3d groove_translation = translation_transform(rotation_m * (offset_x * Vec3d::UnitX()));
692 // cut middle part with 2 angles and add parts to related upper/lower objects
693 const double h_side_shift = 0.5 * double(groove.width + groove.depth / tan(groove.flaps_angle));
694
695 // cut by angle1 plane
696 {
697 const Transform3d cut_matrix_angle1 = groove_translation * translation_transform(rotation_m * (-h_side_shift * Vec3d::UnitX())) *
698 m_cut_matrix * rotation_transform(Vec3d(0, -groove.flaps_angle, -groove.angle));
699
700 cut(groove_object, cut_matrix_angle1, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
701 add_volumes_from_cut(lower, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
702 }
703
704 // cut by angle2 plane
705 {
706 const Transform3d cut_matrix_angle2 = groove_translation * translation_transform(rotation_m * (h_side_shift * Vec3d::UnitX())) *
707 m_cut_matrix * rotation_transform(Vec3d(0, groove.flaps_angle, groove.angle));
708
709 cut(groove_object, cut_matrix_angle2, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
710 add_volumes_from_cut(lower, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
711 }
712
713 // apply tolerance to the middle part
714 {
715 const double h_groove_shift_tolerance = groove_half_depth - (double)groove.depth_tolerance;
716
717 const Transform3d cut_matrix_lower_tolerance = groove_translation * translation_transform(rotation_m * (-h_groove_shift_tolerance * Vec3d::UnitZ())) *
719 cut(groove_object, cut_matrix_lower_tolerance, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
720
721 const double h_side_shift_tolerance = h_side_shift - 0.5 * double(groove.width_tolerance);
722
723 const Transform3d cut_matrix_angle1_tolerance = groove_translation * translation_transform(rotation_m * (-h_side_shift_tolerance * Vec3d::UnitX())) *
724 m_cut_matrix * rotation_transform(Vec3d(0, -groove.flaps_angle, -groove.angle));
725 cut(groove_object, cut_matrix_angle1_tolerance, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
726
727 const Transform3d cut_matrix_angle2_tolerance = groove_translation * translation_transform(rotation_m * (h_side_shift_tolerance * Vec3d::UnitX())) *
728 m_cut_matrix * rotation_transform(Vec3d(0, groove.flaps_angle, groove.angle));
729 cut(groove_object, cut_matrix_angle2_tolerance, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
730 }
731
732 add_volumes_from_cut(upper, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
733
734 groove_object->clear_volumes();
735 }
736
737 ModelObjectPtrs cut_object_ptrs;
738
739 if (keep_as_parts) {
740 // add volumes from lower object to the upper, but mark them as a lower
741 const auto& volumes = lower->volumes;
742 for (const ModelVolume* volume : volumes) {
743 ModelVolume* new_vol = upper->add_volume(*volume);
744 new_vol->cut_info.is_from_upper = false;
745 }
746
747 // add modifiers
748 for (const ModelVolume* volume : cut_mo->volumes)
749 if (!volume->is_model_part())
750 upper->add_volume(*volume);
751
752 cut_object_ptrs.push_back(upper);
753
754 // add lower object to the cut_object_ptrs just to correct delete it from the Model destructor and avoid memory leaks
755 cut_object_ptrs.push_back(lower);
756 }
757 else {
758 // add modifiers if object has any
759 for (const ModelVolume* volume : cut_mo->volumes)
760 if (!volume->is_model_part()) {
761 distribute_modifiers_from_object(cut_mo, m_instance, upper, lower);
762 break;
763 }
764
765 assert(!upper->volumes.empty() && !lower->volumes.empty());
766
767 // Add Upper and Lower parts to cut_object_ptrs
768
769 post_process(upper, lower, cut_object_ptrs);
770
771 // Now merge all model parts together:
772 merge_solid_parts_inside_object(cut_object_ptrs);
773 }
774
775 finalize(cut_object_ptrs, saved_paintings);
776
777 return m_model.objects;
778}
#define M_PI
Definition ExtrusionSimulator.cpp:31
static float calculate_groove_width(const Cut::Groove &groove, const float m_radius)
Definition CutUtils.cpp:780
void translation_transform(Transform3d &transform, const Vec3d &translation)
Definition Geometry.cpp:346
void rotation_transform(Transform3d &transform, const Vec3d &rotation)
Definition Geometry.cpp:359
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68
Eigen::Transform< double, 3, Eigen::Affine, Eigen::DontAlign > Transform3d
Definition Point.hpp:96
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)
Definition CutUtils.cpp:218
ModelObjectCutAttribute
Definition CutUtils.hpp:15

References Cut(), Slic3r::Model::add_object(), Slic3r::ModelObject::add_volume(), Slic3r::Cut::Groove::angle, calculate_groove_width(), Slic3r::ModelObject::clear_volumes(), Slic3r::ModelObject::clone_for_cut(), Slic3r::ModelVolume::cut_info, Slic3r::Cut::Groove::depth, Slic3r::Cut::Groove::depth_tolerance, Slic3r::distribute_modifiers_from_object(), finalize(), Slic3r::Cut::Groove::flaps_angle, Slic3r::ModelObject::instances, Slic3r::ModelVolume::CutInfo::is_from_upper, Slic3r::ModelVolume::is_model_part(), Slic3r::KeepLower, Slic3r::KeepPaint, Slic3r::KeepUpper, m_attributes, m_cut_matrix, m_instance, m_model, M_PI, Slic3r::merge_solid_parts_inside_object(), Slic3r::ModelObject::name, Slic3r::Model::objects, perform_with_plane(), post_process(), Slic3r::ModelVolume::reset_from_upper(), Slic3r::reset_instance_transformation(), Slic3r::Geometry::rotation_transform(), Slic3r::Geometry::translation_transform(), Slic3r::ModelObject::volumes, Slic3r::Cut::Groove::width, and Slic3r::Cut::Groove::width_tolerance.

Referenced by Slic3r::GUI::GLGizmoCut3D::perform_cut(), and Slic3r::GUI::GLGizmoCut3D::process_contours().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ perform_with_plane()

const ModelObjectPtrs & Slic3r::Cut::perform_with_plane ( )
318{
320 m_model.clear_objects();
321 return m_model.objects;
322 }
323
324 ModelObject* mo = m_model.objects.front();
325
326 BOOST_LOG_TRIVIAL(trace) << "ModelObject::cut - start";
327
328 // Clone the object to duplicate instances, materials etc.
329 ModelObject* upper{ nullptr };
331 mo->clone_for_cut(&upper);
332
333 ModelObject* lower{ nullptr };
335 mo->clone_for_cut(&lower);
336
337 std::vector<ModelObject*> dowels;
338
339 // Because transformations are going to be applied to meshes directly,
340 // we reset transformation of all instances and volumes,
341 // except for translation and Z-rotation on instances, which are preserved
342 // in the transformation matrix and not applied to the mesh transform.
343
344 const auto instance_matrix = mo->instances[m_instance]->get_transformation().get_matrix_no_offset();
345 const Transformation cut_transformation = Transformation(m_cut_matrix);
346 const Transform3d inverse_cut_matrix = cut_transformation.get_rotation_matrix().inverse() * translation_transform(-1. * cut_transformation.get_offset());
347
348 std::vector<std::optional<TriangleSelector::SavedPainting>> saved_paintings;
349 for (ModelVolume* volume : mo->volumes) {
350 // Save painting data before reset_extra_facets() discards it.
352 saved_paintings.emplace_back(volume->save_painting());
353 if (saved_paintings.back()) {
354 // Transform mesh to cut space (same transform as process_volume_cut applies)
355 saved_paintings.back()->mesh.transform(instance_matrix * volume->get_matrix(), true);
356 }
357 }
358
359 volume->reset_extra_facets();
360
361 if (!volume->is_model_part()) {
362 if (volume->cut_info.is_processed)
363 process_modifier_cut(volume, instance_matrix, inverse_cut_matrix, m_attributes, upper, lower);
364 else
365 process_connector_cut(volume, instance_matrix, m_cut_matrix, m_attributes, upper, lower, dowels);
366 }
367 else if (!volume->mesh().empty())
368 process_solid_part_cut(volume, instance_matrix, m_cut_matrix, m_attributes, upper, lower);
369 }
370
371 // Post-process cut parts
372
373 if (m_attributes.has(ModelObjectCutAttribute::KeepAsParts) && upper->volumes.empty()) {
374 m_model = Model();
375 m_model.objects.push_back(upper);
376 return m_model.objects;
377 }
378
379 ModelObjectPtrs cut_object_ptrs;
380
381 if (m_attributes.has(ModelObjectCutAttribute::KeepAsParts) && !upper->volumes.empty()) {
383 cut_object_ptrs.push_back(upper);
384 }
385 else {
386 // Delete all modifiers which are not intersecting with solid parts bounding box
387 auto delete_extra_modifiers = [this](ModelObject* mo) {
388 if (!mo) return;
389 const BoundingBoxf3 obj_bb = mo->instance_bounding_box(m_instance);
390 const Transform3d inst_matrix = mo->instances[m_instance]->get_transformation().get_matrix();
391
392 for (int i = int(mo->volumes.size()) - 1; i >= 0; --i)
393 if (const ModelVolume* vol = mo->volumes[i];
394 !vol->is_model_part() && !vol->is_cut_connector()) {
395 auto bb = vol->mesh().transformed_bounding_box(inst_matrix * vol->get_matrix());
396 if (!obj_bb.intersects(bb))
397 mo->delete_volume(i);
398 }
399 };
400
401 post_process(upper, lower, cut_object_ptrs);
402 delete_extra_modifiers(upper);
403 delete_extra_modifiers(lower);
404
405 if (m_attributes.has(ModelObjectCutAttribute::CreateDowels) && !dowels.empty()) {
406 for (auto dowel : dowels) {
408 dowel->name += "-Dowel-" + dowel->volumes[0]->name;
409 cut_object_ptrs.push_back(dowel);
410 }
411 }
412 }
413
414 finalize(cut_object_ptrs, saved_paintings);
415
416 BOOST_LOG_TRIVIAL(trace) << "ModelObject::cut - end";
417
418 return m_model.objects;
419}
void trace(unsigned int level, const char *message)
Definition utils.cpp:247
static void process_connector_cut(ModelVolume *volume, const Transform3d &instance_matrix, const Transform3d &cut_matrix, ModelObjectCutAttributes attributes, ModelObject *upper, ModelObject *lower, std::vector< ModelObject * > &dowels)
Definition CutUtils.cpp:99
@ CreateDowels
Definition CutUtils.hpp:15
@ KeepAsParts
Definition CutUtils.hpp:15
static void process_modifier_cut(ModelVolume *volume, const Transform3d &instance_matrix, const Transform3d &inverse_cut_matrix, ModelObjectCutAttributes attributes, ModelObject *upper, ModelObject *lower)
Definition CutUtils.cpp:170
static void process_solid_part_cut(const ModelVolume *volume, const Transform3d &instance_matrix, const Transform3d &cut_matrix, ModelObjectCutAttributes attributes, ModelObject *upper, ModelObject *lower)
Definition CutUtils.cpp:193

References Slic3r::ModelObject::clone_for_cut(), Slic3r::CreateDowels, Slic3r::ModelVolume::cut_info, Slic3r::ModelObject::delete_volume(), Slic3r::TriangleMesh::empty(), finalize(), Slic3r::ModelVolume::get_matrix(), Slic3r::Geometry::Transformation::get_offset(), Slic3r::Geometry::Transformation::get_rotation_matrix(), Slic3r::ModelObject::instance_bounding_box(), Slic3r::ModelObject::instances, Slic3r::BoundingBox3Base< PointType >::intersects(), Slic3r::ModelVolume::is_model_part(), Slic3r::ModelVolume::CutInfo::is_processed, Slic3r::KeepAsParts, Slic3r::KeepLower, Slic3r::KeepPaint, Slic3r::KeepUpper, m_attributes, m_cut_matrix, m_instance, m_model, Slic3r::ModelVolume::mesh(), post_process(), Slic3r::process_connector_cut(), Slic3r::process_modifier_cut(), Slic3r::process_solid_part_cut(), Slic3r::ModelVolume::reset_extra_facets(), Slic3r::reset_instance_transformation(), Slic3r::ModelVolume::save_painting(), Slic3r::trace(), Slic3r::Geometry::translation_transform(), and Slic3r::ModelObject::volumes.

Referenced by Slic3r::GUI::GLGizmoCut3D::PartSelection::PartSelection(), Slic3r::GUI::cut_model(), perform_by_contour(), Slic3r::GUI::GLGizmoCut3D::perform_cut(), and perform_with_groove().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ post_process() [1/2]

void Slic3r::Cut::post_process ( ModelObject * object,
ModelObjectPtrs & objects,
bool keep,
bool place_on_cut,
bool flip )
private
269{
270 if (!object) return;
271
272 if (keep && !object->volumes.empty()) {
273 reset_instance_transformation(object, m_instance, m_cut_matrix, place_on_cut, flip);
274 cut_object_ptrs.push_back(object);
275 }
276 else
277 m_model.objects.push_back(object); // will be deleted in m_model.clear_objects();
278}

References m_cut_matrix, m_instance, m_model, Slic3r::reset_instance_transformation(), and Slic3r::ModelObject::volumes.

Referenced by perform_by_contour(), perform_with_groove(), perform_with_plane(), and post_process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ post_process() [2/2]

void Slic3r::Cut::post_process ( ModelObject * upper_object,
ModelObject * lower_object,
ModelObjectPtrs & objects )
private

References Slic3r::FlipLower, Slic3r::FlipUpper, Slic3r::KeepLower, Slic3r::KeepUpper, m_attributes, Slic3r::PlaceOnCutLower, Slic3r::PlaceOnCutUpper, and post_process().

Here is the call graph for this function:

Member Data Documentation

◆ m_attributes

◆ m_cut_matrix

const Transform3d Slic3r::Cut::m_cut_matrix
private

◆ m_instance

int Slic3r::Cut::m_instance
private

◆ m_model


The documentation for this class was generated from the following files:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/CutUtils.hpp
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/CutUtils.cpp