#7258 - Fixed cut of merged object
This commit is contained in:
parent
ce1fbbfa7c
commit
5190a1f425
@ -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));
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user