mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	FIX: auto-arrange ignores wipe tower due to supports
Wipe tower is needed if support base and interface use different materials. Jira: STUDIO-1336 Change-Id: I006ece952aac1a0f0a57721c2cd1b52b2ceee28a (cherry picked from commit 1a387e4b1607dee36f5abe499892f027e244fbeb)
This commit is contained in:
		
							parent
							
								
									fb4f30a4a4
								
							
						
					
					
						commit
						9f96c8adec
					
				
					 7 changed files with 57 additions and 54 deletions
				
			
		|  | @ -836,7 +836,7 @@ static void process_arrangeable(const ArrangePolygon &arrpoly, | |||
|     item.binId(arrpoly.bed_idx); | ||||
|     item.priority(arrpoly.priority); | ||||
|     item.itemId(arrpoly.itemid); | ||||
|     item.extrude_id = arrpoly.extrude_ids.back(); | ||||
|     item.extrude_id = arrpoly.extrude_ids.front(); | ||||
|     item.height = arrpoly.height; | ||||
|     item.name = arrpoly.name; | ||||
|     //BBS: add virtual object logic
 | ||||
|  |  | |||
|  | @ -2923,7 +2923,7 @@ double ModelInstance::get_auto_brim_width() const | |||
|     return get_auto_brim_width(DeltaT, adhcoeff); | ||||
| } | ||||
| 
 | ||||
| void ModelInstance::get_arrange_polygon(void* ap) const | ||||
| void ModelInstance::get_arrange_polygon(void *ap, const Slic3r::DynamicPrintConfig &config_global) const | ||||
| { | ||||
| //    static const double SIMPLIFY_TOLERANCE_MM = 0.1;
 | ||||
| 
 | ||||
|  | @ -2962,6 +2962,16 @@ void ModelInstance::get_arrange_polygon(void* ap) const | |||
|     ret.extrude_ids = volume->get_extruders(); | ||||
|     if (ret.extrude_ids.empty()) //the default extruder
 | ||||
|         ret.extrude_ids.push_back(1); | ||||
| 
 | ||||
|     // get per-object support extruders
 | ||||
|     auto op = object->get_config_value<ConfigOptionBool>(config_global, "enable_support"); | ||||
|     bool is_support_enabled = op && op->getBool(); | ||||
|     if (is_support_enabled) { | ||||
|         auto op1 = object->get_config_value<ConfigOptionInt>(config_global, "support_filament"); | ||||
|         auto op2 = object->get_config_value<ConfigOptionInt>(config_global, "support_interface_filament"); | ||||
|         if (op1) ret.extrude_ids.push_back(op1->getInt()); | ||||
|         if (op2) ret.extrude_ids.push_back(op2->getInt()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, EnforcerBlockerType type) const | ||||
|  |  | |||
|  | @ -1111,7 +1111,7 @@ public: | |||
| 
 | ||||
|     // Getting the input polygon for arrange
 | ||||
|     // We use void* as input type to avoid including Arrange.hpp in Model.hpp.
 | ||||
|     void get_arrange_polygon(void* arrange_polygon) const; | ||||
|     void get_arrange_polygon(void *arrange_polygon, const Slic3r::DynamicPrintConfig &config = Slic3r::DynamicPrintConfig()) const; | ||||
| 
 | ||||
|     // Apply the arrange result on the ModelInstance
 | ||||
|     void apply_arrange_result(const Vec2d& offs, double rotation) | ||||
|  |  | |||
|  | @ -88,9 +88,9 @@ void duplicate_objects(Model &model, size_t copies_num) | |||
| 
 | ||||
| // Set up arrange polygon for a ModelInstance and Wipe tower
 | ||||
| template<class T> | ||||
| arrangement::ArrangePolygon get_arrange_poly(T obj) | ||||
| arrangement::ArrangePolygon get_arrange_poly(T obj, const Slic3r::DynamicPrintConfig& config) | ||||
| { | ||||
|     ArrangePolygon ap = obj.get_arrange_polygon(); | ||||
|     ArrangePolygon ap = obj.get_arrange_polygon(config); | ||||
|     //BBS: always set bed_idx to 0 to use original transforms with no bed_idx
 | ||||
|     //if this object is not arranged, it can keep the original transforms
 | ||||
|     //ap.bed_idx        = ap.translation.x() / bed_stride_x(plater);
 | ||||
|  | @ -110,14 +110,14 @@ arrangement::ArrangePolygon get_arrange_poly(T obj) | |||
| } | ||||
| 
 | ||||
| template<> | ||||
| arrangement::ArrangePolygon get_arrange_poly(ModelInstance* inst) | ||||
| arrangement::ArrangePolygon get_arrange_poly(ModelInstance* inst, const Slic3r::DynamicPrintConfig& config) | ||||
| { | ||||
|     return get_arrange_poly(PtrWrapper{ inst }); | ||||
|     return get_arrange_poly(PtrWrapper{ inst },config); | ||||
| } | ||||
| 
 | ||||
| ArrangePolygon get_instance_arrange_poly(ModelInstance* instance, const Slic3r::DynamicPrintConfig& config) | ||||
| { | ||||
|     ArrangePolygon ap = get_arrange_poly(PtrWrapper{ instance }); | ||||
|     ArrangePolygon ap = get_arrange_poly(PtrWrapper{ instance }, config); | ||||
|      | ||||
|     //BBS: add temperature information
 | ||||
|     if (config.has("curr_bed_type")) { | ||||
|  | @ -127,20 +127,20 @@ ArrangePolygon get_instance_arrange_poly(ModelInstance* instance, const Slic3r:: | |||
| 
 | ||||
|         const ConfigOptionInts* bed_opt = config.option<ConfigOptionInts>(get_bed_temp_key(curr_bed_type)); | ||||
|         if (bed_opt != nullptr) | ||||
|             ap.bed_temp = bed_opt->get_at(ap.extrude_ids.back()-1); | ||||
|             ap.bed_temp = bed_opt->get_at(ap.extrude_ids.front()-1); | ||||
| 
 | ||||
|         const ConfigOptionInts* bed_opt_1st_layer = config.option<ConfigOptionInts>(get_bed_temp_1st_layer_key(curr_bed_type)); | ||||
|         if (bed_opt_1st_layer != nullptr) | ||||
|             ap.first_bed_temp = bed_opt_1st_layer->get_at(ap.extrude_ids.back()-1); | ||||
|             ap.first_bed_temp = bed_opt_1st_layer->get_at(ap.extrude_ids.front()-1); | ||||
|     } | ||||
| 
 | ||||
|     if (config.has("nozzle_temperature")) //get the print temperature
 | ||||
|         ap.print_temp = config.opt_int("nozzle_temperature", ap.extrude_ids.back() - 1); | ||||
|         ap.print_temp = config.opt_int("nozzle_temperature", ap.extrude_ids.front() - 1); | ||||
|     if (config.has("nozzle_temperature_initial_layer")) //get the nozzle_temperature_initial_layer
 | ||||
|         ap.first_print_temp = config.opt_int("nozzle_temperature_initial_layer", ap.extrude_ids.back() - 1); | ||||
|         ap.first_print_temp = config.opt_int("nozzle_temperature_initial_layer", ap.extrude_ids.front() - 1); | ||||
|      | ||||
|     if (config.has("temperature_vitrification")) { | ||||
|         ap.vitrify_temp = config.opt_int("temperature_vitrification", ap.extrude_ids.back() - 1); | ||||
|         ap.vitrify_temp = config.opt_int("temperature_vitrification", ap.extrude_ids.front() - 1); | ||||
|     } | ||||
| 
 | ||||
|     // get brim width
 | ||||
|  |  | |||
|  | @ -71,10 +71,10 @@ template<class T> struct PtrWrapper | |||
| 
 | ||||
|     explicit PtrWrapper(T* p) : ptr{ p } {} | ||||
| 
 | ||||
|     arrangement::ArrangePolygon get_arrange_polygon() const | ||||
|     arrangement::ArrangePolygon get_arrange_polygon(const Slic3r::DynamicPrintConfig &config = Slic3r::DynamicPrintConfig()) const | ||||
|     { | ||||
|         arrangement::ArrangePolygon ap; | ||||
|         ptr->get_arrange_polygon(&ap); | ||||
|         ptr->get_arrange_polygon(&ap, config); | ||||
|         return ap; | ||||
|     } | ||||
| 
 | ||||
|  | @ -86,12 +86,12 @@ template<class T> struct PtrWrapper | |||
| }; | ||||
| 
 | ||||
| template<class T> | ||||
| arrangement::ArrangePolygon get_arrange_poly(T obj); | ||||
| arrangement::ArrangePolygon get_arrange_poly(T obj, const DynamicPrintConfig &config = DynamicPrintConfig()); | ||||
| 
 | ||||
| template<> | ||||
| arrangement::ArrangePolygon get_arrange_poly(ModelInstance* inst); | ||||
| arrangement::ArrangePolygon get_arrange_poly(ModelInstance* inst, const DynamicPrintConfig& config); | ||||
| 
 | ||||
| ArrangePolygon get_instance_arrange_poly(ModelInstance* instance, const Slic3r::DynamicPrintConfig& config); | ||||
| ArrangePolygon get_instance_arrange_poly(ModelInstance* instance, const DynamicPrintConfig& config); | ||||
| } | ||||
| 
 | ||||
| #endif // MODELARRANGE_HPP
 | ||||
|  |  | |||
|  | @ -237,39 +237,48 @@ void ArrangeJob::prepare_all() { | |||
|     prepare_wipe_tower(); | ||||
| } | ||||
| 
 | ||||
| // 准备料塔。逻辑如下:
 | ||||
| // 1. 如果料塔被禁用,或是逐件打印,则不需要料塔
 | ||||
| // 2. 以下两种情况需要料塔:1)某对象是多色对象;2)打开了支撑,且支撑体与接触面使用的是不同材料
 | ||||
| // 3. 如果允许不同材料落在相同盘,则以下情况也需要料塔:1)所有选定对象中使用了多种热床温度相同的材料(比如颜色不同的PLA)
 | ||||
| void ArrangeJob::prepare_wipe_tower() | ||||
| { | ||||
|     bool need_wipe_tower = false; | ||||
| 
 | ||||
|     // if wipe tower is explicitly disabled, no need to estimate
 | ||||
|     auto &print = wxGetApp().plater()->get_partplate_list().get_current_fff_print(); | ||||
|     if (!print.config().enable_prime_tower) return; | ||||
|     DynamicPrintConfig ¤t_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; | ||||
|     auto                op             = current_config.option("enable_prime_tower"); | ||||
|     if (op && op->getBool() == false || params.is_seq_print) return; | ||||
| 
 | ||||
|     // estimate if we need wipe tower for all plates:
 | ||||
|     // need wipe tower if some object has multiple extruders (has paint-on colors or support material)
 | ||||
|     for (const auto &item : m_selected) { | ||||
|         std::set<int> obj_extruders; | ||||
|         for (int id : item.extrude_ids) obj_extruders.insert(id); | ||||
|         if (obj_extruders.size() > 1) { | ||||
|             need_wipe_tower = true; | ||||
|             BOOST_LOG_TRIVIAL(info) << "arrange: need wipe tower because object " << item.name << " has multiple extruders (has paint-on colors)"; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|       | ||||
|     // if multile extruders have same bed temp, we need wipe tower
 | ||||
|     if (!params.is_seq_print) { | ||||
|         // need wipe tower if some object has multiple extruders (has paint-on colors)
 | ||||
|         if (!params.allow_multi_materials_on_same_plate) { | ||||
|             for (const auto &item : m_selected) | ||||
|                 if (item.extrude_ids.size() > 1) { | ||||
|                     need_wipe_tower = true; | ||||
|                     break; | ||||
|                 } | ||||
|         } else { | ||||
|             std::map<int, std::set<int>> bedTemp2extruderIds; | ||||
|             for (const auto &item : m_selected) | ||||
|                 for (auto id : item.extrude_ids) { bedTemp2extruderIds[item.bed_temp].insert(id); } | ||||
|             for (const auto &be : bedTemp2extruderIds) { | ||||
|                 if (be.second.size() > 1) { | ||||
|                     need_wipe_tower = true; | ||||
|                     break; | ||||
|                 } | ||||
|      if (params.allow_multi_materials_on_same_plate) { | ||||
|         std::map<int, std::set<int>> bedTemp2extruderIds; | ||||
|         for (const auto &item : m_selected) | ||||
|             for (auto id : item.extrude_ids) { bedTemp2extruderIds[item.bed_temp].insert(id); } | ||||
|         for (const auto &be : bedTemp2extruderIds) { | ||||
|             if (be.second.size() > 1) { | ||||
|                 need_wipe_tower = true; | ||||
|                 BOOST_LOG_TRIVIAL(info) << "arrange: need wipe tower because allow_multi_materials_on_same_plate=true and we have multiple extruders of same type"; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     BOOST_LOG_TRIVIAL(info) << "arrange: need_wipe_tower=" << need_wipe_tower; | ||||
| 
 | ||||
|     if (need_wipe_tower) { | ||||
|         // BBS: prepare wipe tower for all possible plates
 | ||||
|         // check all plates to see if wipe tower is already there
 | ||||
|         ArrangePolygon    wipe_tower_ap; | ||||
|         std::vector<bool> plates_have_wipe_tower(MAX_NUM_PLATES, false); | ||||
|         for (int bedid = 0; bedid < MAX_NUM_PLATES; bedid++) | ||||
|  | @ -300,20 +309,6 @@ void ArrangeJob::prepare_wipe_tower() | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| arrangement::ArrangePolygon ArrangeJob::get_arrange_poly_(ModelInstance *mi) | ||||
| { | ||||
|     arrangement::ArrangePolygon ap = get_arrange_poly(mi); | ||||
| 
 | ||||
|     auto setter = ap.setter; | ||||
|     ap.setter = [this, setter, mi](const arrangement::ArrangePolygon &set_ap) { | ||||
|         setter(set_ap); | ||||
|         if (!set_ap.is_arranged()) | ||||
|             m_unarranged.emplace_back(mi); | ||||
|     }; | ||||
| 
 | ||||
|     return ap; | ||||
| } | ||||
| 
 | ||||
| //BBS: prepare current part plate for arranging
 | ||||
| void ArrangeJob::prepare_partplate() { | ||||
|     clear_input(); | ||||
|  |  | |||
|  | @ -38,8 +38,6 @@ class ArrangeJob : public PlaterJob | |||
|     void prepare_partplate(); | ||||
|     void prepare_wipe_tower(); | ||||
| 
 | ||||
|     ArrangePolygon get_arrange_poly_(ModelInstance* mi); | ||||
|      | ||||
|     ArrangePolygon prepare_arrange_polygon(void* instance); | ||||
| 
 | ||||
| protected: | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Arthur
						Arthur