mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Implemented estimated printing time for the SLA printing
This commit is contained in:
		
							parent
							
								
									f0cee79170
								
							
						
					
					
						commit
						c04be58648
					
				
					 5 changed files with 196 additions and 2 deletions
				
			
		|  | @ -1863,7 +1863,7 @@ std::string Print::output_filename() const | |||
|     DynamicConfig config = this->finished() ? this->print_statistics().config() : this->print_statistics().placeholders(); | ||||
|     return this->PrintBase::output_filename(m_config.output_filename_format.value, "gcode", &config); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| // Shorten the dhms time by removing the seconds, rounding the dhm to full minutes
 | ||||
| // and removing spaces.
 | ||||
| static std::string short_time(const std::string &time) | ||||
|  | @ -1903,7 +1903,7 @@ static std::string short_time(const std::string &time) | |||
|         ::sprintf(buffer, "%ds", seconds); | ||||
|     return buffer; | ||||
| } | ||||
| 
 | ||||
| */ | ||||
| DynamicConfig PrintStatistics::config() const | ||||
| { | ||||
|     DynamicConfig config; | ||||
|  |  | |||
|  | @ -966,6 +966,9 @@ void SLAPrint::process() | |||
|         st += unsigned(PRINT_STEP_LEVELS[currentstep] * pstd); | ||||
|     } | ||||
| 
 | ||||
|     // Fill statistics
 | ||||
|     fill_statistics(); | ||||
| 
 | ||||
|     // If everything vent well
 | ||||
|     report_status(*this, 100, L("Slicing done")); | ||||
| } | ||||
|  | @ -1027,6 +1030,46 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt | |||
|     return invalidated; | ||||
| } | ||||
| 
 | ||||
| void SLAPrint::fill_statistics() | ||||
| { | ||||
|     int max_layers_cnt = 0; | ||||
|     for (SLAPrintObject * po : m_objects) { | ||||
|         if (max_layers_cnt < po->get_slice_index().size()) | ||||
|             max_layers_cnt = po->get_slice_index().size(); | ||||
|     } | ||||
|     if (max_layers_cnt == 0) | ||||
|         return; | ||||
| 
 | ||||
|     float init_exp_time = m_material_config.initial_exposure_time.getFloat();//35;
 | ||||
|     float exp_time = m_material_config.exposure_time.getFloat();//8;
 | ||||
| 
 | ||||
|     // TODO : fade_layers_cnt should be filled in the future
 | ||||
|     // This variable will be a part of the print(material) preset
 | ||||
|     const int fade_layers_cnt = 10; // [3;20]
 | ||||
| 
 | ||||
|     // TODO : tilt_delay_before_time & tilt_delay_after_time should be filled in the future
 | ||||
|     // These values are received from the printer after a printing start
 | ||||
|     const float tilt_delay_before_time = 0.0; | ||||
|     const float tilt_delay_after_time = 0.0; | ||||
|     if (tilt_delay_before_time + tilt_delay_after_time > 0.0) | ||||
|     { | ||||
|         init_exp_time += tilt_delay_before_time + tilt_delay_after_time; | ||||
|         exp_time += tilt_delay_before_time + tilt_delay_after_time; | ||||
|     } | ||||
| 
 | ||||
|     float estim_time = init_exp_time * 3 + exp_time * (max_layers_cnt - 3 - fade_layers_cnt); | ||||
| 
 | ||||
|     const float delta_time = (init_exp_time - exp_time) / (fade_layers_cnt+1); | ||||
|     double fade_layer_time = init_exp_time; | ||||
|     while (fade_layer_time > exp_time) | ||||
|     { | ||||
|         fade_layer_time -= delta_time; | ||||
|         estim_time += fade_layer_time; | ||||
|     } | ||||
| 
 | ||||
|     m_print_statistics.estimated_print_time = get_time_dhms(estim_time); | ||||
| } | ||||
| 
 | ||||
| // Returns true if an object step is done on all objects and there's at least one object.
 | ||||
| bool SLAPrint::is_step_done(SLAPrintObjectStep step) const | ||||
| { | ||||
|  | @ -1257,4 +1300,41 @@ std::vector<Vec3d> SLAPrintObject::transformed_support_points() const | |||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| DynamicConfig SLAPrintStatistics::config() const | ||||
| { | ||||
|     DynamicConfig config; | ||||
|     const std::string print_time = Slic3r::short_time(this->estimated_print_time); | ||||
|     config.set_key_value("print_time", new ConfigOptionString(print_time)); | ||||
|     config.set_key_value("used_material", new ConfigOptionFloat(this->total_used_material/* / 1000.*/)); | ||||
|     config.set_key_value("total_cost", new ConfigOptionFloat(this->total_cost)); | ||||
|     config.set_key_value("total_weight", new ConfigOptionFloat(this->total_weight)); | ||||
|     return config; | ||||
| } | ||||
| 
 | ||||
| DynamicConfig SLAPrintStatistics::placeholders() | ||||
| { | ||||
|     DynamicConfig config; | ||||
|     for (const std::string &key : { | ||||
|         "print_time", "used_material", "total_cost", "total_weight" }) | ||||
|         config.set_key_value(key, new ConfigOptionString(std::string("{") + key + "}")); | ||||
|         return config; | ||||
| } | ||||
| 
 | ||||
| std::string SLAPrintStatistics::finalize_output_path(const std::string &path_in) const | ||||
| { | ||||
|     std::string final_path; | ||||
|     try { | ||||
|         boost::filesystem::path path(path_in); | ||||
|         DynamicConfig cfg = this->config(); | ||||
|         PlaceholderParser pp; | ||||
|         std::string new_stem = pp.process(path.stem().string(), 0, &cfg); | ||||
|         final_path = (path.parent_path() / (new_stem + path.extension().string())).string(); | ||||
|     } | ||||
|     catch (const std::exception &ex) { | ||||
|         BOOST_LOG_TRIVIAL(error) << "Failed to apply the print statistics to the export file name: " << ex.what(); | ||||
|         final_path = path_in; | ||||
|     } | ||||
|     return final_path; | ||||
| } | ||||
| 
 | ||||
| } // namespace Slic3r
 | ||||
|  |  | |||
|  | @ -171,6 +171,29 @@ using PrintObjects = std::vector<SLAPrintObject*>; | |||
| 
 | ||||
| class TriangleMesh; | ||||
| 
 | ||||
| struct SLAPrintStatistics | ||||
| { | ||||
|     SLAPrintStatistics() { clear(); } | ||||
|     std::string                     estimated_print_time; | ||||
|     double                          total_used_material; | ||||
|     double                          total_cost; | ||||
|     double                          total_weight; | ||||
| 
 | ||||
|     // Config with the filled in print statistics.
 | ||||
|     DynamicConfig           config() const; | ||||
|     // Config with the statistics keys populated with placeholder strings.
 | ||||
|     static DynamicConfig    placeholders(); | ||||
|     // Replace the print statistics placeholders in the path.
 | ||||
|     std::string             finalize_output_path(const std::string &path_in) const; | ||||
| 
 | ||||
|     void clear() { | ||||
|         estimated_print_time.clear(); | ||||
|         total_used_material = 0.; | ||||
|         total_cost = 0.; | ||||
|         total_weight = 0.; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief This class is the high level FSM for the SLA printing process. | ||||
|  * | ||||
|  | @ -208,6 +231,8 @@ public: | |||
| 	std::string         output_filename() const override  | ||||
|         { return this->PrintBase::output_filename(m_print_config.output_filename_format.value, "zip"); } | ||||
| 
 | ||||
|     const SLAPrintStatistics&      print_statistics() const { return m_print_statistics; } | ||||
| 
 | ||||
| private: | ||||
|     using SLAPrinter = FilePrinter<FilePrinterFormat::SLA_PNGZIP>; | ||||
|     using SLAPrinterPtr = std::unique_ptr<SLAPrinter>; | ||||
|  | @ -215,6 +240,8 @@ private: | |||
|     // Invalidate steps based on a set of parameters changed.
 | ||||
|     bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys); | ||||
| 
 | ||||
|     void fill_statistics(); | ||||
| 
 | ||||
|     SLAPrintConfig                  m_print_config; | ||||
|     SLAPrinterConfig                m_printer_config; | ||||
|     SLAMaterialConfig               m_material_config; | ||||
|  | @ -246,6 +273,9 @@ private: | |||
|     // The printer itself
 | ||||
|     SLAPrinterPtr                           m_printer; | ||||
| 
 | ||||
|     // Estimated print time, material consumed.
 | ||||
|     SLAPrintStatistics                      m_print_statistics; | ||||
| 
 | ||||
| 	friend SLAPrintObject; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -206,6 +206,69 @@ public: | |||
|     void reset() { closure = Closure(); } | ||||
| }; | ||||
| 
 | ||||
| // Shorten the dhms time by removing the seconds, rounding the dhm to full minutes
 | ||||
| // and removing spaces.
 | ||||
| static std::string short_time(const std::string &time) | ||||
| { | ||||
|     // Parse the dhms time format.
 | ||||
|     int days = 0; | ||||
|     int hours = 0; | ||||
|     int minutes = 0; | ||||
|     int seconds = 0; | ||||
|     if (time.find('d') != std::string::npos) | ||||
|         ::sscanf(time.c_str(), "%dd %dh %dm %ds", &days, &hours, &minutes, &seconds); | ||||
|     else if (time.find('h') != std::string::npos) | ||||
|         ::sscanf(time.c_str(), "%dh %dm %ds", &hours, &minutes, &seconds); | ||||
|     else if (time.find('m') != std::string::npos) | ||||
|         ::sscanf(time.c_str(), "%dm %ds", &minutes, &seconds); | ||||
|     else if (time.find('s') != std::string::npos) | ||||
|         ::sscanf(time.c_str(), "%ds", &seconds); | ||||
|     // Round to full minutes.
 | ||||
|     if (days + hours + minutes > 0 && seconds >= 30) { | ||||
|         if (++minutes == 60) { | ||||
|             minutes = 0; | ||||
|             if (++hours == 24) { | ||||
|                 hours = 0; | ||||
|                 ++days; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     // Format the dhm time.
 | ||||
|     char buffer[64]; | ||||
|     if (days > 0) | ||||
|         ::sprintf(buffer, "%dd%dh%dm", days, hours, minutes); | ||||
|     else if (hours > 0) | ||||
|         ::sprintf(buffer, "%dh%dm", hours, minutes); | ||||
|     else if (minutes > 0) | ||||
|         ::sprintf(buffer, "%dm", minutes); | ||||
|     else | ||||
|         ::sprintf(buffer, "%ds", seconds); | ||||
|     return buffer; | ||||
| } | ||||
| 
 | ||||
| // Returns the given time is seconds in format DDd HHh MMm SSs
 | ||||
| static std::string get_time_dhms(float time_in_secs) | ||||
| { | ||||
|     int days = (int)(time_in_secs / 86400.0f); | ||||
|     time_in_secs -= (float)days * 86400.0f; | ||||
|     int hours = (int)(time_in_secs / 3600.0f); | ||||
|     time_in_secs -= (float)hours * 3600.0f; | ||||
|     int minutes = (int)(time_in_secs / 60.0f); | ||||
|     time_in_secs -= (float)minutes * 60.0f; | ||||
| 
 | ||||
|     char buffer[64]; | ||||
|     if (days > 0) | ||||
|         ::sprintf(buffer, "%dd %dh %dm %ds", days, hours, minutes, (int)time_in_secs); | ||||
|     else if (hours > 0) | ||||
|         ::sprintf(buffer, "%dh %dm %ds", hours, minutes, (int)time_in_secs); | ||||
|     else if (minutes > 0) | ||||
|         ::sprintf(buffer, "%dm %ds", minutes, (int)time_in_secs); | ||||
|     else | ||||
|         ::sprintf(buffer, "%ds", (int)time_in_secs); | ||||
| 
 | ||||
|     return buffer; | ||||
| } | ||||
| 
 | ||||
| } // namespace Slic3r
 | ||||
| 
 | ||||
| #if WIN32 | ||||
|  |  | |||
|  | @ -153,6 +153,7 @@ enum SlisedInfoIdx | |||
|     siFilament_m, | ||||
|     siFilament_mm3, | ||||
|     siFilament_g, | ||||
|     siMateril_unit, | ||||
|     siCost, | ||||
|     siEstimatedTime, | ||||
|     siWTNumbetOfToolchanges, | ||||
|  | @ -193,6 +194,7 @@ SlicedInfo::SlicedInfo(wxWindow *parent) : | |||
|     init_info_label(_(L("Used Filament (m)"))); | ||||
|     init_info_label(_(L("Used Filament (mm³)"))); | ||||
|     init_info_label(_(L("Used Filament (g)"))); | ||||
|     init_info_label(_(L("Used Material (unit)"))); | ||||
|     init_info_label(_(L("Cost"))); | ||||
|     init_info_label(_(L("Estimated printing time"))); | ||||
|     init_info_label(_(L("Number of tool changes"))); | ||||
|  | @ -817,6 +819,21 @@ void Sidebar::show_sliced_info_sizer(const bool show) | |||
| 
 | ||||
|     p->sliced_info->Show(show); | ||||
|     if (show) { | ||||
|         if (p->plater->printer_technology() == ptSLA) | ||||
|         { | ||||
|             const SLAPrintStatistics& ps = p->plater->sla_print().print_statistics(); | ||||
|             p->sliced_info->SetTextAndShow(siMateril_unit, wxString::Format("%.2f", ps.total_used_material)); | ||||
|             p->sliced_info->SetTextAndShow(siCost, wxString::Format("%.2f", ps.total_cost)); | ||||
|             p->sliced_info->SetTextAndShow(siEstimatedTime, ps.estimated_print_time, _(L("Estimated printing time")) + " :"); | ||||
| 
 | ||||
|             // Hide non-SLA sliced info parameters
 | ||||
|             p->sliced_info->SetTextAndShow(siFilament_m, "N/A"); | ||||
|             p->sliced_info->SetTextAndShow(siFilament_mm3, "N/A"); | ||||
|             p->sliced_info->SetTextAndShow(siFilament_g, "N/A"); | ||||
|             p->sliced_info->SetTextAndShow(siWTNumbetOfToolchanges, "N/A"); | ||||
|         } | ||||
|         else | ||||
|         {  | ||||
|         const PrintStatistics& ps = p->plater->fff_print().print_statistics(); | ||||
|         const bool is_wipe_tower = ps.total_wipe_tower_filament > 0; | ||||
| 
 | ||||
|  | @ -864,6 +881,10 @@ void Sidebar::show_sliced_info_sizer(const bool show) | |||
| 
 | ||||
|         // if there is a wipe tower, insert number of toolchanges info into the array:
 | ||||
|         p->sliced_info->SetTextAndShow(siWTNumbetOfToolchanges, is_wipe_tower ? wxString::Format("%.d", p->plater->fff_print().wipe_tower_data().number_of_toolchanges) : "N/A"); | ||||
| 
 | ||||
|         // Hide non-FFF sliced info parameters
 | ||||
|         p->sliced_info->SetTextAndShow(siMateril_unit, "N/A"); | ||||
|         }     | ||||
|     } | ||||
| 
 | ||||
|     Layout(); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 YuSanka
						YuSanka