fix(build): revert CutUtils to v2.4.2 — ImageMap texture-remap additions broke signatures
The ImageMap fork removed src_object from perform_by_contour and saved_paintings from finalize, making the .cpp incompatible with the v2.4.2 header. Reset both files to v2.4.2 baseline; texture remapping on cut is an ImageMap-only feature not yet ported.
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
#include "Geometry.hpp"
|
||||
#include "libslic3r.h"
|
||||
#include "Model.hpp"
|
||||
#include "ModelTextureDataRemap.hpp"
|
||||
#include "TriangleMeshSlicer.hpp"
|
||||
#include "TriangleSelector.hpp"
|
||||
#include "ObjectID.hpp"
|
||||
@@ -46,59 +45,10 @@ static void apply_tolerance(ModelVolume* vol)
|
||||
vol->set_offset(vol->get_offset() + rot_norm * z_offset);
|
||||
}
|
||||
|
||||
static void apply_cut_texture_data(ModelVolume *volume, const SimplifyTextureDataSnapshot *source_snapshot, const Transform3d &cut_matrix)
|
||||
{
|
||||
if (volume == nullptr || source_snapshot == nullptr ||
|
||||
(source_snapshot->source == SimplifyColorSource::None && !source_snapshot->region_painting_present) ||
|
||||
volume->mesh().empty())
|
||||
return;
|
||||
|
||||
SimplifyTextureDataSnapshot snapshot = *source_snapshot;
|
||||
transform_simplify_texture_data_snapshot(snapshot, cut_matrix);
|
||||
transform_simplify_texture_data_snapshot(snapshot, translation_transform(-volume->get_offset()));
|
||||
|
||||
SimplifyTextureDataResult result = remap_simplify_texture_data(snapshot, volume->mesh().its);
|
||||
apply_simplify_texture_data_result(*volume, std::move(result));
|
||||
}
|
||||
|
||||
static bool volume_has_remappable_color_data(const ModelVolume &volume)
|
||||
{
|
||||
const indexed_triangle_set &its = volume.mesh().its;
|
||||
if (its.vertices.empty() || its.indices.empty())
|
||||
return false;
|
||||
|
||||
if (model_volume_region_painting_needs_remap(volume))
|
||||
return true;
|
||||
|
||||
if (!volume.texture_mapping_color_facets.empty())
|
||||
return true;
|
||||
|
||||
const bool has_valid_uvs = volume.imported_texture_uv_valid.size() == its.indices.size() &&
|
||||
volume.imported_texture_uvs_per_face.size() >= its.indices.size() * 6;
|
||||
const bool has_rgba_texture = volume.imported_texture_width > 0 && volume.imported_texture_height > 0 &&
|
||||
volume.imported_texture_rgba.size() >=
|
||||
size_t(volume.imported_texture_width) * size_t(volume.imported_texture_height) * 4;
|
||||
const bool has_raw_texture = volume.imported_texture_width > 0 && volume.imported_texture_height > 0 &&
|
||||
volume.imported_texture_raw_channels > 0 &&
|
||||
volume.imported_texture_raw_filament_offsets.size() >=
|
||||
size_t(volume.imported_texture_width) * size_t(volume.imported_texture_height) *
|
||||
size_t(volume.imported_texture_raw_channels);
|
||||
if (has_valid_uvs && (has_rgba_texture || has_raw_texture))
|
||||
return true;
|
||||
|
||||
return volume.imported_vertex_colors_rgba.size() == its.vertices.size();
|
||||
}
|
||||
|
||||
static ModelVolume* add_cut_volume(TriangleMesh &mesh,
|
||||
ModelObject *object,
|
||||
const ModelVolume *src_volume,
|
||||
const Transform3d &cut_matrix,
|
||||
const std::string &suffix = {},
|
||||
ModelVolumeType type = ModelVolumeType::MODEL_PART,
|
||||
const SimplifyTextureDataSnapshot *source_snapshot = nullptr)
|
||||
static void add_cut_volume(TriangleMesh& mesh, ModelObject* object, const ModelVolume* src_volume, const Transform3d& cut_matrix, const std::string& suffix = {}, ModelVolumeType type = ModelVolumeType::MODEL_PART)
|
||||
{
|
||||
if (mesh.empty())
|
||||
return nullptr;
|
||||
return;
|
||||
|
||||
mesh.transform(cut_matrix);
|
||||
ModelVolume* vol = object->add_volume(mesh);
|
||||
@@ -111,31 +61,20 @@ static ModelVolume* add_cut_volume(TriangleMesh &mesh,
|
||||
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;
|
||||
apply_cut_texture_data(vol, source_snapshot, cut_matrix);
|
||||
return vol;
|
||||
}
|
||||
|
||||
static void process_volume_cut( ModelVolume* volume, const Transform3d& instance_matrix, const Transform3d& cut_matrix,
|
||||
ModelObjectCutAttributes attributes, TriangleMesh& upper_mesh, TriangleMesh& lower_mesh,
|
||||
SimplifyTextureDataSnapshot *source_snapshot = nullptr,
|
||||
const SimplifyTextureDataSnapshot *volume_snapshot = nullptr)
|
||||
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();
|
||||
|
||||
const Transformation cut_transformation = Transformation(cut_matrix);
|
||||
const Transform3d invert_cut_matrix =
|
||||
cut_transformation.get_rotation_matrix().inverse() * translation_transform(-1 * cut_transformation.get_offset());
|
||||
const Transform3d source_to_cut_matrix = invert_cut_matrix * instance_matrix * volume_matrix;
|
||||
|
||||
if (source_snapshot != nullptr) {
|
||||
*source_snapshot = volume_snapshot != nullptr ? *volume_snapshot : snapshot_simplify_texture_data(*volume);
|
||||
transform_simplify_texture_data_snapshot(*source_snapshot, source_to_cut_matrix);
|
||||
}
|
||||
const Transform3d invert_cut_matrix = cut_transformation.get_rotation_matrix().inverse() * translation_transform(-1 * cut_transformation.get_offset());
|
||||
|
||||
// Transform the mesh by the combined transformation matrix.
|
||||
// Flip the triangles in case the composite transformation is left handed.
|
||||
TriangleMesh mesh(volume->mesh());
|
||||
mesh.transform(source_to_cut_matrix, true);
|
||||
mesh.transform(invert_cut_matrix * instance_matrix * volume_matrix, true);
|
||||
|
||||
indexed_triangle_set upper_its, lower_its;
|
||||
cut_mesh(mesh.its, 0.0f, &upper_its, &lower_its);
|
||||
@@ -147,8 +86,7 @@ static void process_volume_cut( ModelVolume* volume, const Transform3d& instance
|
||||
|
||||
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,
|
||||
const SimplifyTextureDataSnapshot *volume_snapshot = nullptr)
|
||||
std::vector<ModelObject*>& dowels)
|
||||
{
|
||||
assert(volume->cut_info.is_connector);
|
||||
volume->cut_info.set_processed();
|
||||
@@ -205,16 +143,15 @@ static void process_connector_cut( ModelVolume* volume, const Transform3d& inst
|
||||
|
||||
// Perform cut
|
||||
TriangleMesh upper_mesh, lower_mesh;
|
||||
SimplifyTextureDataSnapshot source_snapshot;
|
||||
process_volume_cut(volume, Transform3d::Identity(), cut_matrix, attributes, upper_mesh, lower_mesh, &source_snapshot, volume_snapshot);
|
||||
process_volume_cut(volume, Transform3d::Identity(), cut_matrix, attributes, upper_mesh, lower_mesh);
|
||||
|
||||
// add small Z offset to better preview
|
||||
upper_mesh.translate((-0.05 * Vec3d::UnitZ()).cast<float>());
|
||||
lower_mesh.translate((0.05 * Vec3d::UnitZ()).cast<float>());
|
||||
|
||||
// Add cut parts to the related objects
|
||||
add_cut_volume(upper_mesh, upper, volume, cut_matrix, "_A", volume->type(), &source_snapshot);
|
||||
add_cut_volume(lower_mesh, lower, volume, cut_matrix, "_B", volume->type(), &source_snapshot);
|
||||
add_cut_volume(upper_mesh, upper, volume, cut_matrix, "_A", volume->type());
|
||||
add_cut_volume(lower_mesh, lower, volume, cut_matrix, "_B", volume->type());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,31 +178,29 @@ 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 SimplifyTextureDataSnapshot *volume_snapshot = nullptr)
|
||||
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;
|
||||
SimplifyTextureDataSnapshot source_snapshot;
|
||||
process_volume_cut(volume, instance_matrix, cut_matrix, attributes, upper_mesh, lower_mesh, &source_snapshot, volume_snapshot);
|
||||
process_volume_cut(volume, instance_matrix, cut_matrix, attributes, upper_mesh, lower_mesh);
|
||||
|
||||
// Add required cut parts to the objects
|
||||
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepAsParts)) {
|
||||
add_cut_volume(upper_mesh, upper, volume, cut_matrix, "_A", ModelVolumeType::MODEL_PART, &source_snapshot);
|
||||
add_cut_volume(upper_mesh, upper, volume, cut_matrix, "_A");
|
||||
if (!lower_mesh.empty()) {
|
||||
add_cut_volume(lower_mesh, upper, volume, cut_matrix, "_B", ModelVolumeType::MODEL_PART, &source_snapshot);
|
||||
add_cut_volume(lower_mesh, upper, volume, cut_matrix, "_B");
|
||||
upper->volumes.back()->cut_info.is_from_upper = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepUpper))
|
||||
add_cut_volume(upper_mesh, upper, volume, cut_matrix, {}, ModelVolumeType::MODEL_PART, &source_snapshot);
|
||||
add_cut_volume(upper_mesh, upper, volume, cut_matrix);
|
||||
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepLower) && !lower_mesh.empty())
|
||||
add_cut_volume(lower_mesh, lower, volume, cut_matrix, {}, ModelVolumeType::MODEL_PART, &source_snapshot);
|
||||
add_cut_volume(lower_mesh, lower, volume, cut_matrix);
|
||||
}
|
||||
|
||||
static void reset_instance_transformation(ModelObject* object, size_t src_instance_idx,
|
||||
@@ -344,9 +279,22 @@ void Cut::post_process(ModelObject* upper, ModelObject* lower, ModelObjectPtrs&
|
||||
}
|
||||
|
||||
|
||||
void Cut::finalize(const ModelObjectPtrs& objects)
|
||||
void Cut::finalize(const ModelObjectPtrs& objects, const std::vector<std::optional<TriangleSelector::SavedPainting>>& saved_paintings)
|
||||
{
|
||||
//clear model from temporarry objects
|
||||
// Paint volumes
|
||||
for (const auto& saved_painting : saved_paintings) {
|
||||
if (saved_painting) {
|
||||
for (const auto object : objects) {
|
||||
for (const auto volume : object->volumes) {
|
||||
if (volume->is_model_part() && !volume->is_cut_connector()) {
|
||||
volume->restore_painting(saved_painting, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//clear model from temporary objects
|
||||
m_model.clear_objects();
|
||||
|
||||
// add to model result objects
|
||||
@@ -385,18 +333,27 @@ const ModelObjectPtrs& Cut::perform_with_plane()
|
||||
const Transformation cut_transformation = Transformation(m_cut_matrix);
|
||||
const Transform3d inverse_cut_matrix = cut_transformation.get_rotation_matrix().inverse() * translation_transform(-1. * cut_transformation.get_offset());
|
||||
|
||||
std::vector<std::optional<TriangleSelector::SavedPainting>> saved_paintings;
|
||||
for (ModelVolume* volume : mo->volumes) {
|
||||
SimplifyTextureDataSnapshot volume_snapshot = snapshot_simplify_texture_data(*volume);
|
||||
// Save painting data before reset_extra_facets() discards it.
|
||||
if (m_attributes.has(ModelObjectCutAttribute::KeepPaint)) {
|
||||
saved_paintings.emplace_back(volume->save_painting());
|
||||
if (saved_paintings.back()) {
|
||||
// Transform mesh to cut space (same transform as process_volume_cut applies)
|
||||
saved_paintings.back()->mesh.transform(instance_matrix * volume->get_matrix(), true);
|
||||
}
|
||||
}
|
||||
|
||||
volume->reset_extra_facets();
|
||||
|
||||
if (!volume->is_model_part()) {
|
||||
if (volume->cut_info.is_processed)
|
||||
process_modifier_cut(volume, instance_matrix, inverse_cut_matrix, m_attributes, upper, lower);
|
||||
else
|
||||
process_connector_cut(volume, instance_matrix, m_cut_matrix, m_attributes, upper, lower, dowels, &volume_snapshot);
|
||||
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, &volume_snapshot);
|
||||
process_solid_part_cut(volume, instance_matrix, m_cut_matrix, m_attributes, upper, lower);
|
||||
}
|
||||
|
||||
// Post-process cut parts
|
||||
@@ -442,9 +399,9 @@ const ModelObjectPtrs& Cut::perform_with_plane()
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "ModelObject::cut - end";
|
||||
finalize(cut_object_ptrs, saved_paintings);
|
||||
|
||||
finalize(cut_object_ptrs);
|
||||
BOOST_LOG_TRIVIAL(trace) << "ModelObject::cut - end";
|
||||
|
||||
return m_model.objects;
|
||||
}
|
||||
@@ -472,25 +429,10 @@ static void distribute_modifiers_from_object(ModelObject* from_obj, const int in
|
||||
static void merge_solid_parts_inside_object(ModelObjectPtrs& objects)
|
||||
{
|
||||
for (ModelObject* mo : objects) {
|
||||
bool has_remappable_color_data = false;
|
||||
for (const ModelVolume* mv : mo->volumes) {
|
||||
if (mv->is_model_part() && !mv->is_cut_connector() && volume_has_remappable_color_data(*mv)) {
|
||||
has_remappable_color_data = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (has_remappable_color_data) {
|
||||
mo->sort_volumes(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
TriangleMesh mesh;
|
||||
const ModelVolume *merged_volume_source = nullptr;
|
||||
// Merge all SolidPart but not Connectors
|
||||
for (const ModelVolume* mv : mo->volumes) {
|
||||
if (mv->is_model_part() && !mv->is_cut_connector()) {
|
||||
if (merged_volume_source == nullptr)
|
||||
merged_volume_source = mv;
|
||||
TriangleMesh m = mv->mesh();
|
||||
m.transform(mv->get_matrix());
|
||||
mesh.merge(m);
|
||||
@@ -499,14 +441,6 @@ static void merge_solid_parts_inside_object(ModelObjectPtrs& objects)
|
||||
if (!mesh.empty()) {
|
||||
ModelVolume* new_volume = mo->add_volume(mesh);
|
||||
new_volume->name = mo->name;
|
||||
if (merged_volume_source != nullptr) {
|
||||
new_volume->config.assign_config(merged_volume_source->config);
|
||||
if (ModelMaterial *material = merged_volume_source->material())
|
||||
new_volume->set_material(merged_volume_source->material_id(), *material);
|
||||
else
|
||||
new_volume->set_material_id(merged_volume_source->material_id());
|
||||
new_volume->cut_info = merged_volume_source->cut_info;
|
||||
}
|
||||
// Delete all merged SolidPart but not Connectors
|
||||
for (int i = int(mo->volumes.size()) - 2; i >= 0; --i) {
|
||||
const ModelVolume* mv = mo->volumes[i];
|
||||
@@ -520,7 +454,7 @@ static void merge_solid_parts_inside_object(ModelObjectPtrs& objects)
|
||||
}
|
||||
|
||||
|
||||
const ModelObjectPtrs& Cut::perform_by_contour(std::vector<Part> parts, int dowels_count)
|
||||
const ModelObjectPtrs& Cut::perform_by_contour(const ModelObject* src_object, std::vector<Part> parts, int dowels_count)
|
||||
{
|
||||
ModelObject* cut_mo = m_model.objects.front();
|
||||
|
||||
@@ -535,6 +469,19 @@ const ModelObjectPtrs& Cut::perform_by_contour(std::vector<Part> parts, int dowe
|
||||
lower->name = lower->name + "_B";
|
||||
}
|
||||
|
||||
// Save painting data so we later can remap it.
|
||||
std::vector<std::optional<TriangleSelector::SavedPainting>> saved_paintings;
|
||||
if (m_attributes.has(ModelObjectCutAttribute::KeepPaint)) {
|
||||
const auto instance_matrix = src_object->instances[m_instance]->get_transformation().get_matrix_no_offset();
|
||||
for (const auto volume : src_object->volumes) {
|
||||
saved_paintings.emplace_back(volume->save_painting());
|
||||
if (saved_paintings.back()) {
|
||||
// Transform mesh to cut space (same transform as process_volume_cut applies)
|
||||
saved_paintings.back()->mesh.transform(instance_matrix * volume->get_matrix(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const size_t cut_parts_cnt = parts.size();
|
||||
bool has_modifiers = false;
|
||||
|
||||
@@ -564,7 +511,7 @@ const ModelObjectPtrs& Cut::perform_by_contour(std::vector<Part> parts, int dowe
|
||||
merge_solid_parts_inside_object(cut_object_ptrs);
|
||||
|
||||
// replace initial objects in model with cut object
|
||||
finalize(cut_object_ptrs);
|
||||
finalize(cut_object_ptrs, saved_paintings);
|
||||
}
|
||||
else if (volumes.size() > cut_parts_cnt) {
|
||||
// Means that object is cut with connectors
|
||||
@@ -595,7 +542,7 @@ const ModelObjectPtrs& Cut::perform_by_contour(std::vector<Part> parts, int dowe
|
||||
merge_solid_parts_inside_object(cut_object_ptrs);
|
||||
|
||||
// replace initial objects in model with cut object
|
||||
finalize(cut_object_ptrs);
|
||||
finalize(cut_object_ptrs, saved_paintings);
|
||||
|
||||
// Add Dowel-connectors as separate objects to model
|
||||
if (cut_connectors_obj.size() >= 3)
|
||||
@@ -607,7 +554,12 @@ const ModelObjectPtrs& Cut::perform_by_contour(std::vector<Part> parts, int dowe
|
||||
}
|
||||
|
||||
|
||||
const ModelObjectPtrs& Cut::perform_with_groove(const Groove& groove, const Transform3d& rotation_m, bool keep_as_parts/* = false*/)
|
||||
const ModelObjectPtrs& 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*/)
|
||||
{
|
||||
ModelObject* cut_mo = m_model.objects.front();
|
||||
|
||||
@@ -621,6 +573,20 @@ const ModelObjectPtrs& Cut::perform_with_groove(const Groove& groove, const Tran
|
||||
upper->name = upper->name + "_A";
|
||||
lower->name = lower->name + "_B";
|
||||
}
|
||||
|
||||
// Save painting data so we later can remap it.
|
||||
std::vector<std::optional<TriangleSelector::SavedPainting>> saved_paintings;
|
||||
if (m_attributes.has(ModelObjectCutAttribute::KeepPaint)) {
|
||||
const auto instance_matrix = cut_mo->instances[m_instance]->get_transformation().get_matrix_no_offset();
|
||||
for (const auto volume : cut_mo->volumes) {
|
||||
saved_paintings.emplace_back(volume->save_painting());
|
||||
if (saved_paintings.back()) {
|
||||
// Transform mesh to cut space (same transform as process_volume_cut applies)
|
||||
saved_paintings.back()->mesh.transform(instance_matrix * volume->get_matrix(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const double groove_half_depth = 0.5 * double(groove.depth);
|
||||
|
||||
Model tmp_model_for_cut = Model();
|
||||
@@ -654,61 +620,108 @@ const ModelObjectPtrs& Cut::perform_with_groove(const Groove& groove, const Tran
|
||||
reset_instance_transformation(object, m_instance);
|
||||
};
|
||||
|
||||
// cut by upper plane
|
||||
|
||||
const Transform3d cut_matrix_upper = translation_transform(rotation_m * (groove_half_depth * Vec3d::UnitZ())) * m_cut_matrix;
|
||||
// cut by upper plane (+Z)
|
||||
{
|
||||
const Transform3d cut_matrix_upper = translation_transform(rotation_m * (groove_half_depth * Vec3d::UnitZ())) * m_cut_matrix;
|
||||
|
||||
cut(tmp_object, cut_matrix_upper, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
|
||||
add_volumes_from_cut(upper, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
|
||||
}
|
||||
|
||||
// cut by lower plane
|
||||
|
||||
const Transform3d cut_matrix_lower = translation_transform(rotation_m * (-groove_half_depth * Vec3d::UnitZ())) * m_cut_matrix;
|
||||
// cut by lower plane (-Z)
|
||||
{
|
||||
const Transform3d cut_matrix_lower = translation_transform(rotation_m * (-groove_half_depth * Vec3d::UnitZ())) * m_cut_matrix;
|
||||
|
||||
cut(tmp_object, cut_matrix_lower, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
|
||||
add_volumes_from_cut(lower, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
|
||||
}
|
||||
|
||||
// cut middle part with 2 angles and add parts to related upper/lower objects
|
||||
// Compute same slot outer width used in preview plane
|
||||
const float groove_width = calculate_groove_width(groove, m_radius);
|
||||
|
||||
const double h_side_shift = 0.5 * double(groove.width + groove.depth / tan(groove.flaps_angle));
|
||||
ModelObject* groove_object{nullptr};
|
||||
|
||||
// cut by angle1 plane
|
||||
{
|
||||
const Transform3d cut_matrix_angle1 = translation_transform(rotation_m * (-h_side_shift * Vec3d::UnitX())) * m_cut_matrix * rotation_transform(Vec3d(0, -groove.flaps_angle, -groove.angle));
|
||||
// multiple cuts
|
||||
for (int i = 0; i < groove_count; i++) {
|
||||
bool is_first_groove = i == 0;
|
||||
bool is_last_groove = i == groove_count - 1;
|
||||
|
||||
cut(tmp_object, cut_matrix_angle1, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
|
||||
add_volumes_from_cut(lower, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
|
||||
// Calculate the x-axis offset for this dovetail
|
||||
float groove_offset_factor_start = -.5 * ((groove_count - 1));
|
||||
float groove_offset_factor = groove_offset_factor_start + i;
|
||||
|
||||
float offset_x = groove_offset_factor * (groove_gap + groove_width);
|
||||
|
||||
|
||||
tmp_object->clone_for_cut(&groove_object);
|
||||
for (ModelVolume* volume : tmp_object->volumes) {
|
||||
ModelVolume* new_vol = groove_object->add_volume(*volume);
|
||||
new_vol->reset_from_upper();
|
||||
}
|
||||
|
||||
// isolate area of current groove
|
||||
if (!is_first_groove) {
|
||||
float left_cut_position = (-groove_gap / 2.f) - (groove_width / 2.f) + offset_x;
|
||||
|
||||
const Transform3d cut_matrix_left = translation_transform(rotation_m * (left_cut_position * Vec3d::UnitX())) *
|
||||
m_cut_matrix * rotation_transform(Vec3d(0, M_PI / 2.0, 0));
|
||||
|
||||
cut(groove_object, cut_matrix_left, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
|
||||
}
|
||||
if (!is_last_groove) {
|
||||
float right_cut_position = (groove_gap / 2.f) + (groove_width / 2.f) + offset_x;
|
||||
|
||||
const Transform3d cut_matrix_right = translation_transform(rotation_m * (right_cut_position * Vec3d::UnitX())) *
|
||||
m_cut_matrix * rotation_transform(Vec3d(0, M_PI / 2.0, 0));
|
||||
cut(groove_object, cut_matrix_right, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
|
||||
}
|
||||
|
||||
const Transform3d groove_translation = translation_transform(rotation_m * (offset_x * Vec3d::UnitX()));
|
||||
// cut middle part with 2 angles and add parts to related upper/lower objects
|
||||
const double h_side_shift = 0.5 * double(groove.width + groove.depth / tan(groove.flaps_angle));
|
||||
|
||||
// cut by angle1 plane
|
||||
{
|
||||
const Transform3d cut_matrix_angle1 = groove_translation * translation_transform(rotation_m * (-h_side_shift * Vec3d::UnitX())) *
|
||||
m_cut_matrix * rotation_transform(Vec3d(0, -groove.flaps_angle, -groove.angle));
|
||||
|
||||
cut(groove_object, cut_matrix_angle1, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
|
||||
add_volumes_from_cut(lower, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
|
||||
}
|
||||
|
||||
// cut by angle2 plane
|
||||
{
|
||||
const Transform3d cut_matrix_angle2 = groove_translation * translation_transform(rotation_m * (h_side_shift * Vec3d::UnitX())) *
|
||||
m_cut_matrix * rotation_transform(Vec3d(0, groove.flaps_angle, groove.angle));
|
||||
|
||||
cut(groove_object, cut_matrix_angle2, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
|
||||
add_volumes_from_cut(lower, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
|
||||
}
|
||||
|
||||
// apply tolerance to the middle part
|
||||
{
|
||||
const double h_groove_shift_tolerance = groove_half_depth - (double)groove.depth_tolerance;
|
||||
|
||||
const Transform3d cut_matrix_lower_tolerance = groove_translation * translation_transform(rotation_m * (-h_groove_shift_tolerance * Vec3d::UnitZ())) *
|
||||
m_cut_matrix;
|
||||
cut(groove_object, cut_matrix_lower_tolerance, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
|
||||
|
||||
const double h_side_shift_tolerance = h_side_shift - 0.5 * double(groove.width_tolerance);
|
||||
|
||||
const Transform3d cut_matrix_angle1_tolerance = groove_translation * translation_transform(rotation_m * (-h_side_shift_tolerance * Vec3d::UnitX())) *
|
||||
m_cut_matrix * rotation_transform(Vec3d(0, -groove.flaps_angle, -groove.angle));
|
||||
cut(groove_object, cut_matrix_angle1_tolerance, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
|
||||
|
||||
const Transform3d cut_matrix_angle2_tolerance = groove_translation * translation_transform(rotation_m * (h_side_shift_tolerance * Vec3d::UnitX())) *
|
||||
m_cut_matrix * rotation_transform(Vec3d(0, groove.flaps_angle, groove.angle));
|
||||
cut(groove_object, cut_matrix_angle2_tolerance, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
|
||||
}
|
||||
|
||||
add_volumes_from_cut(upper, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
|
||||
|
||||
groove_object->clear_volumes();
|
||||
}
|
||||
|
||||
// cut by angle2 plane
|
||||
{
|
||||
const Transform3d cut_matrix_angle2 = translation_transform(rotation_m * (h_side_shift * Vec3d::UnitX())) * m_cut_matrix * rotation_transform(Vec3d(0, groove.flaps_angle, groove.angle));
|
||||
|
||||
cut(tmp_object, cut_matrix_angle2, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
|
||||
add_volumes_from_cut(lower, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
|
||||
}
|
||||
|
||||
// apply tolerance to the middle part
|
||||
{
|
||||
const double h_groove_shift_tolerance = groove_half_depth - (double)groove.depth_tolerance;
|
||||
|
||||
const Transform3d cut_matrix_lower_tolerance = translation_transform(rotation_m * (-h_groove_shift_tolerance * Vec3d::UnitZ())) * m_cut_matrix;
|
||||
cut(tmp_object, cut_matrix_lower_tolerance, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
|
||||
|
||||
const double h_side_shift_tolerance = h_side_shift - 0.5 * double(groove.width_tolerance);
|
||||
|
||||
const Transform3d cut_matrix_angle1_tolerance = translation_transform(rotation_m * (-h_side_shift_tolerance * Vec3d::UnitX())) * m_cut_matrix * rotation_transform(Vec3d(0, -groove.flaps_angle, -groove.angle));
|
||||
cut(tmp_object, cut_matrix_angle1_tolerance, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
|
||||
|
||||
const Transform3d cut_matrix_angle2_tolerance = translation_transform(rotation_m * (h_side_shift_tolerance * Vec3d::UnitX())) * m_cut_matrix * rotation_transform(Vec3d(0, groove.flaps_angle, groove.angle));
|
||||
cut(tmp_object, cut_matrix_angle2_tolerance, ModelObjectCutAttribute::KeepUpper, tmp_model_for_cut);
|
||||
}
|
||||
|
||||
// this part can be added to the upper object now
|
||||
add_volumes_from_cut(upper, ModelObjectCutAttribute::KeepLower, tmp_model_for_cut);
|
||||
|
||||
ModelObjectPtrs cut_object_ptrs;
|
||||
|
||||
if (keep_as_parts) {
|
||||
@@ -747,9 +760,24 @@ const ModelObjectPtrs& Cut::perform_with_groove(const Groove& groove, const Tran
|
||||
merge_solid_parts_inside_object(cut_object_ptrs);
|
||||
}
|
||||
|
||||
finalize(cut_object_ptrs);
|
||||
finalize(cut_object_ptrs, saved_paintings);
|
||||
|
||||
return m_model.objects;
|
||||
}
|
||||
|
||||
float Cut::calculate_groove_width (const Cut::Groove& groove, const float m_radius)
|
||||
{
|
||||
// Compute same slot outer width used in preview plane
|
||||
const double flap_width = is_approx(groove.flaps_angle, 0.f) ? groove.depth : groove.depth / sin(groove.flaps_angle);
|
||||
const double total_flap_width = 2.0 * flap_width * cos(groove.flaps_angle);
|
||||
const double slot_neck_half_width = 0.5f * (groove.width);
|
||||
const double slot_mouth_half_width = 0.5 * (groove.width + total_flap_width);
|
||||
const double plane_half_height = 0.5f* (1.5f * (1.5f *m_radius));
|
||||
const double flap_taper_offset = plane_half_height * tan(groove.angle);
|
||||
const double slot_outer_x_max = std::max(slot_mouth_half_width + flap_taper_offset, slot_neck_half_width + flap_taper_offset);
|
||||
|
||||
return float(2.0 * slot_outer_x_max);
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
|
||||
Reference in New Issue
Block a user