mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	height level mismatches seems to be fixed.
This commit is contained in:
		
							parent
							
								
									7482b619b5
								
							
						
					
					
						commit
						d27e22c2c3
					
				
					 8 changed files with 106 additions and 58 deletions
				
			
		|  | @ -2525,6 +2525,13 @@ void PrintConfigDef::init_sla_params() | |||
|     def->min = 0; | ||||
|     def->default_value = new ConfigOptionFloat(5.0); | ||||
| 
 | ||||
|     def = this->add("pad_enable", coBool); | ||||
|     def->label = L("Use pad"); | ||||
|     def->tooltip = L("Add a pad underneath the supported model"); | ||||
|     def->sidetext = L(""); | ||||
|     def->cli = ""; | ||||
|     def->default_value = new ConfigOptionBool(true); | ||||
| 
 | ||||
|     def = this->add("pad_wall_thickness", coFloat); | ||||
|     def->label = L("Pad wall thickness"); | ||||
|     def->tooltip = L(""); | ||||
|  |  | |||
|  | @ -942,6 +942,7 @@ public: | |||
| 
 | ||||
|     // Now for the base pool (pad) /////////////////////////////////////////////
 | ||||
| 
 | ||||
|     ConfigOptionBool  pad_enable; | ||||
|     ConfigOptionFloat pad_wall_thickness /*= 2*/; | ||||
|     ConfigOptionFloat pad_wall_height /*= 5*/; | ||||
|     ConfigOptionFloat pad_max_merge_distance /*= 50*/; | ||||
|  | @ -961,6 +962,7 @@ protected: | |||
|         OPT_PTR(support_critical_angle); | ||||
|         OPT_PTR(support_max_bridge_length); | ||||
|         OPT_PTR(support_object_elevation); | ||||
|         OPT_PTR(pad_enable); | ||||
|         OPT_PTR(pad_wall_thickness); | ||||
|         OPT_PTR(pad_wall_height); | ||||
|         OPT_PTR(pad_max_merge_distance); | ||||
|  |  | |||
|  | @ -23,6 +23,13 @@ struct PoolConfig { | |||
|     double min_wall_height_mm = 5; | ||||
|     double max_merge_distance_mm = 50; | ||||
|     double edge_radius_mm = 1; | ||||
| 
 | ||||
|     inline PoolConfig() {} | ||||
|     inline PoolConfig(double wt, double wh, double md, double er): | ||||
|         min_wall_thickness_mm(wt), | ||||
|         min_wall_height_mm(wh), | ||||
|         max_merge_distance_mm(md), | ||||
|         edge_radius_mm(er) {} | ||||
| }; | ||||
| 
 | ||||
| /// Calculate the pool for the mesh for SLA printing
 | ||||
|  | @ -31,6 +38,15 @@ void create_base_pool(const ExPolygons& base_plate, | |||
|                       const PoolConfig& = PoolConfig() | ||||
|                       ); | ||||
| 
 | ||||
| /// TODO: Currently the base plate of the pool will have half the height of the
 | ||||
| /// whole pool. So the carved out space has also half the height. This is not
 | ||||
| /// a particularly elegant solution, the thickness should be exactly
 | ||||
| /// min_wall_thickness and it should be corrected in the future. This method
 | ||||
| /// will return the correct value for further processing.
 | ||||
| inline double get_pad_elevation(const PoolConfig& cfg) { | ||||
|     return cfg.min_wall_height_mm / 2.0; | ||||
| } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -512,7 +512,7 @@ struct Pad { | |||
|         double ground_level, | ||||
|         const PoolConfig& pcfg) : | ||||
|         cfg(pcfg), | ||||
|         zlevel(ground_level + cfg.min_wall_height_mm/2) | ||||
|         zlevel(ground_level + sla::get_pad_elevation(pcfg)) | ||||
|     { | ||||
|         ExPolygons basep; | ||||
|         base_plate(object_support_mesh, basep, | ||||
|  | @ -1634,7 +1634,7 @@ SlicedSupports SLASupportTree::slice(float layerh, float init_layerh) const | |||
|     const auto modelh = float(stree.full_height()); | ||||
|     auto gndlvl = float(this->m_impl->ground_level); | ||||
|     const Pad& pad = m_impl->pad(); | ||||
|     if(!pad.empty()) gndlvl -= float(pad.cfg.min_wall_height_mm/2); | ||||
|     if(!pad.empty()) gndlvl -= float(get_pad_elevation(pad.cfg)); | ||||
| 
 | ||||
|     std::vector<float> heights = {gndlvl}; | ||||
|     heights.reserve(size_t(modelh/layerh) + 1); | ||||
|  | @ -1673,20 +1673,12 @@ const TriangleMesh &SLASupportTree::get_pad() const | |||
|     return m_impl->pad().tmesh; | ||||
| } | ||||
| 
 | ||||
| double SLASupportTree::get_elevation() const | ||||
| { | ||||
|     double ph = m_impl->pad().empty()? 0 : | ||||
|                                        m_impl->pad().cfg.min_wall_height_mm/2.0; | ||||
|     return m_elevation + ph; | ||||
| } | ||||
| 
 | ||||
| SLASupportTree::SLASupportTree(const PointSet &points, | ||||
|                                const EigenMesh3D& emesh, | ||||
|                                const SupportConfig &cfg, | ||||
|                                const Controller &ctl): | ||||
|     m_impl(new Impl()), m_ctl(ctl) | ||||
| { | ||||
|     m_elevation = cfg.object_elevation_mm; | ||||
|     m_impl->ground_level = emesh.ground_level - cfg.object_elevation_mm; | ||||
|     generate(points, emesh, cfg, ctl); | ||||
| } | ||||
|  |  | |||
|  | @ -118,9 +118,6 @@ class SLASupportTree { | |||
|     std::unique_ptr<Impl> m_impl; | ||||
|     Controller m_ctl; | ||||
| 
 | ||||
|     // the only value from config that is also needed after construction
 | ||||
|     double m_elevation = 0; | ||||
| 
 | ||||
|     Impl& get() { return *m_impl; } | ||||
|     const Impl& get() const { return *m_impl; } | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,6 +3,8 @@ | |||
| #include "SLA/SLABasePool.hpp" | ||||
| 
 | ||||
| #include <tbb/parallel_for.h> | ||||
| #include <boost/log/trivial.hpp> | ||||
| 
 | ||||
| //#include <tbb/spin_mutex.h>//#include "tbb/mutex.h"
 | ||||
| 
 | ||||
| #include "I18N.hpp" | ||||
|  | @ -128,32 +130,36 @@ void SLAPrint::process() | |||
|     // the model objects we have to process and the instances are also filtered
 | ||||
| 
 | ||||
|     // shortcut to initial layer height
 | ||||
|     auto ilh = float(m_material_config.initial_layer_height.getFloat()); | ||||
| 
 | ||||
|     std::cout << "Initial layer height: " << m_material_config.initial_layer_height.getFloat() << std::endl; | ||||
|     double ilhd = m_material_config.initial_layer_height.getFloat(); | ||||
|     auto   ilh  = float(ilhd); | ||||
| 
 | ||||
|     // Slicing the model object. This method is oversimplified and needs to
 | ||||
|     // be compared with the fff slicing algorithm for verification
 | ||||
|     auto slice_model = [this, ilh](SLAPrintObject& po) { | ||||
|         auto lh = float(po.m_config.layer_height.getFloat()); | ||||
|     auto slice_model = [this, ilh, ilhd](SLAPrintObject& po) { | ||||
|         double lh = po.m_config.layer_height.getFloat(); | ||||
| 
 | ||||
|         TriangleMesh mesh = po.transformed_mesh(); | ||||
|         TriangleMeshSlicer slicer(&mesh); | ||||
|         auto bb3d = mesh.bounding_box(); | ||||
| 
 | ||||
|         auto H = bb3d.max(Z) - bb3d.min(Z); | ||||
|         double elevation = po.get_elevation(); | ||||
| 
 | ||||
|         float minZ = float(bb3d.min(Z)) - float(elevation); | ||||
|         float maxZ = float(bb3d.max(Z)) ; | ||||
|         auto flh = float(lh); | ||||
|         auto gnd = float(bb3d.min(Z)); | ||||
| 
 | ||||
|         double elevation = po.m_config.support_object_elevation.getFloat(); | ||||
|         float ih = elevation > 0 ? lh : ilh; | ||||
|         std::vector<float> heights; | ||||
| 
 | ||||
|         std::vector<float> heights = {gnd}; | ||||
|         for(float h = gnd + ih; h < gnd + H; h += lh) heights.emplace_back(h); | ||||
|         // The first layer (the one before the initial height) is added only
 | ||||
|         // if the there is no pad and no elevation value
 | ||||
|         if(minZ >= gnd) heights.emplace_back(minZ); | ||||
| 
 | ||||
|         for(float h = minZ + ilh; h < maxZ; h += flh) | ||||
|             if(h >= gnd) heights.emplace_back(h); | ||||
| 
 | ||||
|         auto& layers = po.m_model_slices; | ||||
|         slicer.slice(heights, &layers, [this](){ | ||||
|             throw_if_canceled(); | ||||
|         }); | ||||
|         slicer.slice(heights, &layers, [this](){ throw_if_canceled(); }); | ||||
|     }; | ||||
| 
 | ||||
|     auto support_points = [](SLAPrintObject& po) { | ||||
|  | @ -216,6 +222,7 @@ void SLAPrint::process() | |||
|         // repeated)
 | ||||
| 
 | ||||
|         if(po.is_step_done(slaposSupportTree) && | ||||
|            po.m_config.pad_enable.getBool() && | ||||
|            po.m_supportdata && | ||||
|            po.m_supportdata->support_tree_ptr) | ||||
|         { | ||||
|  | @ -225,10 +232,12 @@ void SLAPrint::process() | |||
|             double er = po.m_config.pad_edge_radius.getFloat(); | ||||
|             double lh = po.m_config.layer_height.getFloat(); | ||||
|             double elevation = po.m_config.support_object_elevation.getFloat(); | ||||
|             sla::PoolConfig pcfg(wt, h, md, er); | ||||
| 
 | ||||
|             sla::ExPolygons bp; | ||||
|             if(elevation < h/2) sla::base_plate(po.transformed_mesh(), bp, | ||||
|                                                 float(h/2), float(lh)); | ||||
|             double pad_h = sla::get_pad_elevation(pcfg); | ||||
|             if(elevation < pad_h) sla::base_plate(po.transformed_mesh(), bp, | ||||
|                                                   float(pad_h), float(lh)); | ||||
| 
 | ||||
|             po.m_supportdata->support_tree_ptr->add_pad(bp, wt, h, md, er); | ||||
|         } | ||||
|  | @ -246,7 +255,7 @@ void SLAPrint::process() | |||
|     }; | ||||
| 
 | ||||
|     // Rasterizing the model objects, and their supports
 | ||||
|     auto rasterize = [this, ilh]() { | ||||
|     auto rasterize = [this, ilh, ilhd]() { | ||||
|         using Layer = sla::ExPolygons; | ||||
|         using LayerCopies = std::vector<SLAPrintObject::Instance>; | ||||
|         struct LayerRef { | ||||
|  | @ -262,51 +271,60 @@ void SLAPrint::process() | |||
|         // layers according to quantized height levels
 | ||||
|         std::map<LevelID, LayerRefs> levels; | ||||
| 
 | ||||
|         auto sinitlh = LevelID(scale_(ilh)); | ||||
|         auto sih = LevelID(scale_(ilh)); | ||||
| 
 | ||||
|         // For all print objects, go through its initial layers and place them
 | ||||
|         // into the layers hash
 | ||||
|         for(SLAPrintObject *o : m_objects) { | ||||
| 
 | ||||
|             double gndlvl = o->transformed_mesh().bounding_box().min(Z); | ||||
|             double elevation = o->m_config.support_object_elevation.getFloat(); | ||||
| 
 | ||||
|             auto bb = o->transformed_mesh().bounding_box(); | ||||
|             double modelgnd = bb.min(Z); | ||||
|             double elevation = o->get_elevation(); | ||||
|             double lh = o->m_config.layer_height.getFloat(); | ||||
|             double minZ = modelgnd - elevation; | ||||
| 
 | ||||
|             // TODO: this juust misses the support layers with a slight offset...
 | ||||
|             double ih = elevation > 0 ? lh : ilh; | ||||
|             // scaled values:
 | ||||
|             auto sminZ = LevelID(scale_(minZ)); | ||||
|             auto smaxZ = LevelID(scale_(bb.max(Z))); | ||||
|             auto smodelgnd = LevelID(scale_(modelgnd)); | ||||
|             auto slh = LevelID(scale_(lh)); | ||||
| 
 | ||||
|             auto sgl = LevelID(scale_(gndlvl)); | ||||
|             auto slh = LevelID(scale_(lh));    // scaled layer height
 | ||||
|             auto sih = LevelID(scale_(ih)); | ||||
|             // It is important that the next levels math the levels in
 | ||||
|             // model_slice method. Only difference is that here it works with
 | ||||
|             // scaled coordinates
 | ||||
|             std::vector<LevelID> levelids; | ||||
|             if(sminZ >= smodelgnd) levelids.emplace_back(sminZ); | ||||
|             for(LevelID h = sminZ + sih; h < smaxZ; h += slh) | ||||
|                 if(h >= smodelgnd) levelids.emplace_back(h); | ||||
| 
 | ||||
|             SlicedModel & oslices = o->m_model_slices; | ||||
| 
 | ||||
|             // If everything went well this code should not run at all, but
 | ||||
|             // let's be robust...
 | ||||
|             assert(levelids.size() == oslices.size()); | ||||
|             if(levelids.size() < oslices.size()) { // extend the levels until...
 | ||||
| 
 | ||||
|                 BOOST_LOG_TRIVIAL(warning) | ||||
|                         << "Height level mismatch at rasterization!\n"; | ||||
| 
 | ||||
|                 LevelID lastlvl = levelids.back(); | ||||
|                 while(levelids.size() < oslices.size()) { | ||||
|                     lastlvl += slh; | ||||
|                     levelids.emplace_back(lastlvl); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             for(int i = 0; i < oslices.size(); ++i) { | ||||
|                 int a = i == 0 ? 0 : 1; | ||||
|                 int b = i == 0 ? 0 : i - 1; | ||||
| 
 | ||||
|                 LevelID h = sgl + sih * a + b * slh; | ||||
| 
 | ||||
|                 std::cout << "Model layer level: " << h << std::endl; | ||||
| 
 | ||||
|                 LevelID h = levelids[i]; | ||||
|                 auto& lyrs = levels[h]; // this initializes a new record
 | ||||
|                 lyrs.emplace_back(oslices[i], o->m_instances); | ||||
|             } | ||||
| 
 | ||||
|             if(o->m_supportdata) { // deal with the support slices if present
 | ||||
|                 auto& sslices = o->m_supportdata->support_slices; | ||||
| 
 | ||||
|                 // Supports start below the ground level.
 | ||||
|                 // Counting the pad height as well
 | ||||
|                 double el = o->get_elevation(); | ||||
|                 auto sel = LevelID(scale_(el)); | ||||
| 
 | ||||
|                 for(int i = 0; i < sslices.size(); ++i) { | ||||
|                     int a = i == 0 ? 0 : 1; | ||||
|                     int b = i == 0 ? 0 : i - 1; | ||||
| 
 | ||||
|                     LevelID h = sgl - sel + sinitlh * a + b * slh; | ||||
|                     std::cout << "Support layer level: " << h << std::endl; | ||||
|                     LevelID h = sminZ + a * sih + b * slh; | ||||
| 
 | ||||
|                     auto& lyrs = levels[h]; | ||||
|                     lyrs.emplace_back(sslices[i], o->m_instances); | ||||
|  | @ -473,9 +491,23 @@ SLAPrintObject::SLAPrintObject(SLAPrint *print, ModelObject *model_object): | |||
| SLAPrintObject::~SLAPrintObject() {} | ||||
| 
 | ||||
| double SLAPrintObject::get_elevation() const { | ||||
|     return m_supportdata && m_supportdata->support_tree_ptr? | ||||
|                 m_supportdata->support_tree_ptr->get_elevation() : | ||||
|                 0; | ||||
|     double ret = m_config.support_object_elevation.getFloat(); | ||||
| 
 | ||||
|     // if the pad is enabled, then half of the pad height is its base plate
 | ||||
|     if(m_config.pad_enable.getBool()) { | ||||
|         // Normally the elevation for the pad itself would be the thickness of
 | ||||
|         // its walls but currently it is half of its thickness. Whatever it
 | ||||
|         // will be in the future, we provide the config to the get_pad_elevation
 | ||||
|         // method and we will have the correct value
 | ||||
|         sla::PoolConfig pcfg; | ||||
|         pcfg.min_wall_height_mm = m_config.pad_wall_height.getFloat(); | ||||
|         pcfg.min_wall_thickness_mm = m_config.pad_wall_thickness.getFloat(); | ||||
|         pcfg.edge_radius_mm = m_config.pad_edge_radius.getFloat(); | ||||
|         pcfg.max_merge_distance_mm = m_config.pad_max_merge_distance.getFloat(); | ||||
|         ret += sla::get_pad_elevation(pcfg); | ||||
|     } | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| //const std::vector<ExPolygons> &SLAPrintObject::get_support_slices() const
 | ||||
|  |  | |||
|  | @ -412,6 +412,7 @@ const std::vector<std::string>& Preset::sla_print_options() | |||
|             "support_critical_angle", | ||||
|             "support_max_bridge_length", | ||||
|             "support_object_elevation", | ||||
|             "pad_enable", | ||||
|             "pad_wall_thickness", | ||||
|             "pad_wall_height", | ||||
|             "pad_max_merge_distance", | ||||
|  |  | |||
|  | @ -3012,6 +3012,7 @@ void TabSLAPrint::build() | |||
|     optgroup->append_single_option_line("support_max_bridge_length"); | ||||
| 
 | ||||
|     optgroup = page->new_optgroup(_(L("Pad"))); | ||||
|     optgroup->append_single_option_line("pad_enable"); | ||||
|     optgroup->append_single_option_line("pad_wall_thickness"); | ||||
|     optgroup->append_single_option_line("pad_wall_height"); | ||||
|     optgroup->append_single_option_line("pad_max_merge_distance"); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 tamasmeszaros
						tamasmeszaros