#7258 - Fixed cut of merged object

This commit is contained in:
enricoturri1966 2021-11-08 12:56:38 +01:00
parent ce1fbbfa7c
commit 5190a1f425
2 changed files with 41 additions and 43 deletions

View File

@ -1263,10 +1263,10 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, ModelObjectCutAttr
instances[instance]->get_mirror() instances[instance]->get_mirror()
); );
z -= instances[instance]->get_offset()(2); z -= instances[instance]->get_offset().z();
// Lower part per-instance bounding boxes // Displacement (in instance coordinates) to be applied to place the upper parts
std::vector<BoundingBoxf3> lower_bboxes { instances.size() }; Vec3d local_displace = Vec3d::Zero();
for (ModelVolume *volume : volumes) { for (ModelVolume *volume : volumes) {
const auto volume_matrix = volume->get_matrix(); const auto volume_matrix = volume->get_matrix();
@ -1287,7 +1287,6 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, ModelObjectCutAttr
lower->add_volume(*volume); lower->add_volume(*volume);
} }
else if (! volume->mesh().empty()) { else if (! volume->mesh().empty()) {
// Transform the mesh by the combined transformation matrix. // Transform the mesh by the combined transformation matrix.
// Flip the triangles in case the composite transformation is left handed. // Flip the triangles in case the composite transformation is left handed.
TriangleMesh mesh(volume->mesh()); TriangleMesh mesh(volume->mesh());
@ -1327,13 +1326,10 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, ModelObjectCutAttr
assert(vol->config.id() != volume->config.id()); assert(vol->config.id() != volume->config.id());
vol->set_material(volume->material_id(), *volume->material()); vol->set_material(volume->material_id(), *volume->material());
// Compute the lower part instances' bounding boxes to figure out where to place // Compute the displacement (in instance coordinates) to be applied to place the upper parts
// the upper part // The upper part displacement is set to half of the lower part bounding box
if (attributes.has(ModelObjectCutAttribute::KeepUpper)) { // this is done in hope at least a part of the upper part will always be visible and draggable
for (size_t i = 0; i < instances.size(); i++) { local_displace = lower->full_raw_mesh_bounding_box().size().cwiseProduct(Vec3d(-0.5, -0.5, 0.0));
lower_bboxes[i].merge(instances[i]->transform_mesh_bounding_box(lower_mesh, true));
}
}
} }
} }
} }
@ -1341,17 +1337,18 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, ModelObjectCutAttr
ModelObjectPtrs res; ModelObjectPtrs res;
if (attributes.has(ModelObjectCutAttribute::KeepUpper) && upper->volumes.size() > 0) { if (attributes.has(ModelObjectCutAttribute::KeepUpper) && upper->volumes.size() > 0) {
upper->invalidate_bounding_box(); if (!upper->origin_translation.isApprox(Vec3d::Zero()) && instances[instance]->get_offset().isApprox(Vec3d::Zero())) {
upper->center_around_origin(); upper->center_around_origin();
upper->translate_instances(-upper->origin_translation);
upper->origin_translation = Vec3d::Zero();
}
// Reset instance transformation except offset and Z-rotation // Reset instance transformation except offset and Z-rotation
for (size_t i = 0; i < instances.size(); i++) { for (size_t i = 0; i < instances.size(); ++i) {
auto &instance = upper->instances[i]; auto &instance = upper->instances[i];
const Vec3d offset = instance->get_offset(); const Vec3d offset = instance->get_offset();
const double rot_z = instance->get_rotation()(2); const double rot_z = instance->get_rotation().z();
// The upper part displacement is set to half of the lower part bounding box const Vec3d displace = Geometry::assemble_transform(Vec3d::Zero(), instance->get_rotation()) * local_displace;
// this is done in hope at least a part of the upper part will always be visible and draggable
const Vec3d displace = lower_bboxes[i].size().cwiseProduct(Vec3d(-0.5, -0.5, 0.0));
instance->set_transformation(Geometry::Transformation()); instance->set_transformation(Geometry::Transformation());
instance->set_offset(offset + displace); instance->set_offset(offset + displace);
@ -1361,14 +1358,16 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, ModelObjectCutAttr
res.push_back(upper); res.push_back(upper);
} }
if (attributes.has(ModelObjectCutAttribute::KeepLower) && lower->volumes.size() > 0) { if (attributes.has(ModelObjectCutAttribute::KeepLower) && lower->volumes.size() > 0) {
lower->invalidate_bounding_box(); if (!lower->origin_translation.isApprox(Vec3d::Zero()) && instances[instance]->get_offset().isApprox(Vec3d::Zero())) {
lower->center_around_origin(); lower->center_around_origin();
lower->translate_instances(-lower->origin_translation);
lower->origin_translation = Vec3d::Zero();
}
// Reset instance transformation except offset and Z-rotation // Reset instance transformation except offset and Z-rotation
for (auto *instance : lower->instances) { for (auto *instance : lower->instances) {
const Vec3d offset = instance->get_offset(); const Vec3d offset = instance->get_offset();
const double rot_z = instance->get_rotation()(2); const double rot_z = instance->get_rotation().z();
instance->set_transformation(Geometry::Transformation()); instance->set_transformation(Geometry::Transformation());
instance->set_offset(offset); instance->set_offset(offset);
instance->set_rotation(Vec3d(attributes.has(ModelObjectCutAttribute::FlipLower) ? 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));

View File

@ -2044,8 +2044,7 @@ void ObjectList::split()
void ObjectList::merge(bool to_multipart_object) void ObjectList::merge(bool to_multipart_object)
{ {
// merge selected objects to the multipart object // merge selected objects to the multipart object
if (to_multipart_object) if (to_multipart_object) {
{
auto get_object_idxs = [this](std::vector<int>& obj_idxs, wxDataViewItemArray& sels) auto get_object_idxs = [this](std::vector<int>& obj_idxs, wxDataViewItemArray& sels)
{ {
// check selections and split instances to the separated objects... // check selections and split instances to the separated objects...
@ -2056,8 +2055,7 @@ void ObjectList::merge(bool to_multipart_object)
break; break;
} }
if (!instance_selection) if (!instance_selection) {
{
for (wxDataViewItem item : sels) { for (wxDataViewItem item : sels) {
assert(m_objects_model->GetItemType(item) & itObject); assert(m_objects_model->GetItemType(item) & itObject);
obj_idxs.emplace_back(m_objects_model->GetIdByItem(item)); obj_idxs.emplace_back(m_objects_model->GetIdByItem(item));
@ -2069,8 +2067,7 @@ void ObjectList::merge(bool to_multipart_object)
std::map<int, std::set<int>> sel_map; std::map<int, std::set<int>> sel_map;
std::set<int> empty_set; std::set<int> empty_set;
for (wxDataViewItem item : sels) { for (wxDataViewItem item : sels) {
if (m_objects_model->GetItemType(item) & itObject) if (m_objects_model->GetItemType(item) & itObject) {
{
int obj_idx = m_objects_model->GetIdByItem(item); int obj_idx = m_objects_model->GetIdByItem(item);
int inst_cnt = (*m_objects)[obj_idx]->instances.size(); int inst_cnt = (*m_objects)[obj_idx]->instances.size();
if (inst_cnt == 1) if (inst_cnt == 1)
@ -2087,8 +2084,7 @@ void ObjectList::merge(bool to_multipart_object)
// all objects, created from the instances will be added to the end of list // all objects, created from the instances will be added to the end of list
int new_objects_cnt = 0; // count of this new objects int new_objects_cnt = 0; // count of this new objects
for (auto map_item : sel_map) for (auto map_item : sel_map) {
{
int obj_idx = map_item.first; int obj_idx = map_item.first;
// object with just 1 instance // object with just 1 instance
if (map_item.second.empty()) { if (map_item.second.empty()) {
@ -2148,37 +2144,36 @@ void ObjectList::merge(bool to_multipart_object)
new_object->name = _u8L("Merged"); new_object->name = _u8L("Merged");
ModelConfig &config = new_object->config; ModelConfig &config = new_object->config;
for (int obj_idx : obj_idxs) for (int obj_idx : obj_idxs) {
{
ModelObject* object = (*m_objects)[obj_idx]; ModelObject* object = (*m_objects)[obj_idx];
const Geometry::Transformation& transformation = object->instances[0]->get_transformation(); const Geometry::Transformation& transformation = object->instances[0]->get_transformation();
Vec3d scale = transformation.get_scaling_factor(); const Vec3d scale = transformation.get_scaling_factor();
Vec3d mirror = transformation.get_mirror(); const Vec3d mirror = transformation.get_mirror();
Vec3d rotation = transformation.get_rotation(); const Vec3d rotation = transformation.get_rotation();
if (object->id() == (*m_objects)[obj_idxs.front()]->id()) if (object->id() == (*m_objects)[obj_idxs.front()]->id())
new_object->add_instance(); new_object->add_instance();
Transform3d volume_offset_correction = new_object->instances[0]->get_transformation().get_matrix().inverse() * transformation.get_matrix(); const Transform3d& volume_offset_correction = transformation.get_matrix();
// merge volumes // merge volumes
for (const ModelVolume* volume : object->volumes) { for (const ModelVolume* volume : object->volumes) {
ModelVolume* new_volume = new_object->add_volume(*volume); ModelVolume* new_volume = new_object->add_volume(*volume);
//set rotation //set rotation
Vec3d vol_rot = new_volume->get_rotation() + rotation; const Vec3d vol_rot = new_volume->get_rotation() + rotation;
new_volume->set_rotation(vol_rot); new_volume->set_rotation(vol_rot);
// set scale // set scale
Vec3d vol_sc_fact = new_volume->get_scaling_factor().cwiseProduct(scale); const Vec3d vol_sc_fact = new_volume->get_scaling_factor().cwiseProduct(scale);
new_volume->set_scaling_factor(vol_sc_fact); new_volume->set_scaling_factor(vol_sc_fact);
// set mirror // set mirror
Vec3d vol_mirror = new_volume->get_mirror().cwiseProduct(mirror); const Vec3d vol_mirror = new_volume->get_mirror().cwiseProduct(mirror);
new_volume->set_mirror(vol_mirror); new_volume->set_mirror(vol_mirror);
// set offset // set offset
Vec3d vol_offset = volume_offset_correction* new_volume->get_offset(); const Vec3d vol_offset = volume_offset_correction* new_volume->get_offset();
new_volume->set_offset(vol_offset); new_volume->set_offset(vol_offset);
} }
new_object->sort_volumes(wxGetApp().app_config->get("order_volumes") == "1"); new_object->sort_volumes(wxGetApp().app_config->get("order_volumes") == "1");
@ -2211,6 +2206,11 @@ void ObjectList::merge(bool to_multipart_object)
for (const auto& range : object->layer_config_ranges) for (const auto& range : object->layer_config_ranges)
new_object->layer_config_ranges.emplace(range); new_object->layer_config_ranges.emplace(range);
} }
new_object->center_around_origin();
new_object->translate_instances(-new_object->origin_translation);
new_object->origin_translation = Vec3d::Zero();
// remove selected objects // remove selected objects
remove(); remove();
@ -2221,8 +2221,7 @@ void ObjectList::merge(bool to_multipart_object)
} }
// merge all parts to the one single object // merge all parts to the one single object
// all part's settings will be lost // all part's settings will be lost
else else {
{
wxDataViewItem item = GetSelection(); wxDataViewItem item = GetSelection();
if (!item) if (!item)
return; return;