mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	#7258 - Fixed cut of merged object
This commit is contained in:
		
							parent
							
								
									ce1fbbfa7c
								
							
						
					
					
						commit
						5190a1f425
					
				
					 2 changed files with 41 additions and 43 deletions
				
			
		|  | @ -1263,10 +1263,10 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, ModelObjectCutAttr | |||
|         instances[instance]->get_mirror() | ||||
|     ); | ||||
| 
 | ||||
|     z -= instances[instance]->get_offset()(2); | ||||
|     z -= instances[instance]->get_offset().z(); | ||||
| 
 | ||||
|     // Lower part per-instance bounding boxes
 | ||||
|     std::vector<BoundingBoxf3> lower_bboxes { instances.size() }; | ||||
|     // Displacement (in instance coordinates) to be applied to place the upper parts
 | ||||
|     Vec3d local_displace = Vec3d::Zero(); | ||||
| 
 | ||||
|     for (ModelVolume *volume : volumes) { | ||||
|         const auto volume_matrix = volume->get_matrix(); | ||||
|  | @ -1286,8 +1286,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, ModelObjectCutAttr | |||
|             if (attributes.has(ModelObjectCutAttribute::KeepLower)) | ||||
|                 lower->add_volume(*volume); | ||||
|         } | ||||
|         else if (! volume->mesh().empty()) { | ||||
|              | ||||
|         else if (! volume->mesh().empty()) {             | ||||
|             // Transform the mesh by the combined transformation matrix.
 | ||||
|             // Flip the triangles in case the composite transformation is left handed.
 | ||||
| 			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()); | ||||
|                 vol->set_material(volume->material_id(), *volume->material()); | ||||
| 
 | ||||
|                 // Compute the lower part instances' bounding boxes to figure out where to place
 | ||||
|                 // the upper part
 | ||||
|                 if (attributes.has(ModelObjectCutAttribute::KeepUpper)) { | ||||
|                     for (size_t i = 0; i < instances.size(); i++) { | ||||
|                         lower_bboxes[i].merge(instances[i]->transform_mesh_bounding_box(lower_mesh, true)); | ||||
|                     } | ||||
|                 } | ||||
|                 // Compute the displacement (in instance coordinates) to be applied to place the upper parts
 | ||||
|                 // The upper part displacement is set to half of the lower part bounding box
 | ||||
|                 // this is done in hope at least a part of the upper part will always be visible and draggable
 | ||||
|                 local_displace = lower->full_raw_mesh_bounding_box().size().cwiseProduct(Vec3d(-0.5, -0.5, 0.0)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -1341,17 +1337,18 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, ModelObjectCutAttr | |||
|     ModelObjectPtrs res; | ||||
| 
 | ||||
|     if (attributes.has(ModelObjectCutAttribute::KeepUpper) && upper->volumes.size() > 0) { | ||||
|         upper->invalidate_bounding_box(); | ||||
|         upper->center_around_origin(); | ||||
|         if (!upper->origin_translation.isApprox(Vec3d::Zero()) && instances[instance]->get_offset().isApprox(Vec3d::Zero())) { | ||||
|             upper->center_around_origin(); | ||||
|             upper->translate_instances(-upper->origin_translation); | ||||
|             upper->origin_translation = Vec3d::Zero(); | ||||
|         } | ||||
| 
 | ||||
|         // 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]; | ||||
|             const Vec3d offset = instance->get_offset(); | ||||
|             const double rot_z = instance->get_rotation()(2); | ||||
|             // The upper part displacement is set to half of the lower part bounding box
 | ||||
|             // 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)); | ||||
|             const double rot_z = instance->get_rotation().z(); | ||||
|             const Vec3d displace = Geometry::assemble_transform(Vec3d::Zero(), instance->get_rotation()) * local_displace; | ||||
| 
 | ||||
|             instance->set_transformation(Geometry::Transformation()); | ||||
|             instance->set_offset(offset + displace); | ||||
|  | @ -1361,14 +1358,16 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, ModelObjectCutAttr | |||
|         res.push_back(upper); | ||||
|     } | ||||
|     if (attributes.has(ModelObjectCutAttribute::KeepLower) && lower->volumes.size() > 0) { | ||||
|         lower->invalidate_bounding_box(); | ||||
|         lower->center_around_origin(); | ||||
|         if (!lower->origin_translation.isApprox(Vec3d::Zero()) && instances[instance]->get_offset().isApprox(Vec3d::Zero())) { | ||||
|             lower->center_around_origin(); | ||||
|             lower->translate_instances(-lower->origin_translation); | ||||
|             lower->origin_translation = Vec3d::Zero(); | ||||
|         } | ||||
| 
 | ||||
|         // Reset instance transformation except offset and Z-rotation
 | ||||
|         for (auto *instance : lower->instances) { | ||||
|             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_offset(offset); | ||||
|             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) | ||||
| { | ||||
|     // 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) | ||||
|         { | ||||
|             // check selections and split instances to the separated objects...
 | ||||
|  | @ -2056,8 +2055,7 @@ void ObjectList::merge(bool to_multipart_object) | |||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|             if (!instance_selection) | ||||
|             { | ||||
|             if (!instance_selection) { | ||||
|                 for (wxDataViewItem item : sels) { | ||||
|                     assert(m_objects_model->GetItemType(item) & itObject); | ||||
|                     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::set<int> empty_set; | ||||
|             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 inst_cnt = (*m_objects)[obj_idx]->instances.size(); | ||||
|                     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
 | ||||
|             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; | ||||
|                 // object with just 1 instance
 | ||||
|                 if (map_item.second.empty()) { | ||||
|  | @ -2148,37 +2144,36 @@ void ObjectList::merge(bool to_multipart_object) | |||
|         new_object->name = _u8L("Merged"); | ||||
|         ModelConfig &config = new_object->config; | ||||
| 
 | ||||
|         for (int obj_idx : obj_idxs) | ||||
|         { | ||||
|         for (int obj_idx : obj_idxs) { | ||||
|             ModelObject* object = (*m_objects)[obj_idx]; | ||||
| 
 | ||||
|             const Geometry::Transformation& transformation = object->instances[0]->get_transformation(); | ||||
|             Vec3d scale     = transformation.get_scaling_factor(); | ||||
|             Vec3d mirror    = transformation.get_mirror(); | ||||
|             Vec3d rotation  = transformation.get_rotation(); | ||||
|             const Vec3d scale     = transformation.get_scaling_factor(); | ||||
|             const Vec3d mirror    = transformation.get_mirror(); | ||||
|             const Vec3d rotation  = transformation.get_rotation(); | ||||
| 
 | ||||
|             if (object->id() == (*m_objects)[obj_idxs.front()]->id()) | ||||
|                 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
 | ||||
|             for (const ModelVolume* volume : object->volumes) { | ||||
|                 ModelVolume* new_volume = new_object->add_volume(*volume); | ||||
| 
 | ||||
|                 //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); | ||||
| 
 | ||||
|                 // 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); | ||||
| 
 | ||||
|                 // 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); | ||||
| 
 | ||||
|                 // 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_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) | ||||
|                 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(); | ||||
| 
 | ||||
|  | @ -2221,8 +2221,7 @@ void ObjectList::merge(bool to_multipart_object) | |||
|     } | ||||
|     // merge all parts to the one single object
 | ||||
|     // all part's settings will be lost
 | ||||
|     else | ||||
|     { | ||||
|     else { | ||||
|         wxDataViewItem item = GetSelection(); | ||||
|         if (!item) | ||||
|             return; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 enricoturri1966
						enricoturri1966