mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 12:41:18 -07:00 
			
		
		
		
	Merge remote-tracking branch 'origin/tm_slice_index'
This commit is contained in:
		
						commit
						8003dd4991
					
				
					 7 changed files with 517 additions and 206 deletions
				
			
		| 
						 | 
					@ -56,6 +56,113 @@ public:
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<class Vector,
 | 
				
			||||||
 | 
					         class Value = typename Vector::value_type>
 | 
				
			||||||
 | 
					class IndexBasedIterator {
 | 
				
			||||||
 | 
					    static const size_t NONE = size_t(-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::reference_wrapper<Vector> m_index_ref;
 | 
				
			||||||
 | 
					    size_t m_idx = NONE;
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using value_type = Value;
 | 
				
			||||||
 | 
					    using pointer = Value *;
 | 
				
			||||||
 | 
					    using reference = Value &;
 | 
				
			||||||
 | 
					    using difference_type = long;
 | 
				
			||||||
 | 
					    using iterator_category = std::random_access_iterator_tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline explicit
 | 
				
			||||||
 | 
					    IndexBasedIterator(Vector& index, size_t idx):
 | 
				
			||||||
 | 
					        m_index_ref(index), m_idx(idx) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Post increment
 | 
				
			||||||
 | 
					    inline IndexBasedIterator operator++(int) {
 | 
				
			||||||
 | 
					        IndexBasedIterator cpy(*this); ++m_idx; return cpy;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline IndexBasedIterator operator--(int) {
 | 
				
			||||||
 | 
					        IndexBasedIterator cpy(*this); --m_idx; return cpy;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline IndexBasedIterator& operator++() {
 | 
				
			||||||
 | 
					        ++m_idx; return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline IndexBasedIterator& operator--() {
 | 
				
			||||||
 | 
					        --m_idx; return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline IndexBasedIterator& operator+=(difference_type l) {
 | 
				
			||||||
 | 
					        m_idx += size_t(l); return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline IndexBasedIterator operator+(difference_type l) {
 | 
				
			||||||
 | 
					        auto cpy = *this; cpy += l; return cpy;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline IndexBasedIterator& operator-=(difference_type l) {
 | 
				
			||||||
 | 
					        m_idx -= size_t(l); return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline IndexBasedIterator operator-(difference_type l) {
 | 
				
			||||||
 | 
					        auto cpy = *this; cpy -= l; return cpy;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator difference_type() { return difference_type(m_idx); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline bool is_end() const { return m_idx >= m_index_ref.get().size();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline Value & operator*() const {
 | 
				
			||||||
 | 
					        assert(m_idx < m_index_ref.get().size());
 | 
				
			||||||
 | 
					        return m_index_ref.get().operator[](m_idx);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline Value * operator->() const {
 | 
				
			||||||
 | 
					        assert(m_idx < m_index_ref.get().size());
 | 
				
			||||||
 | 
					        return &m_index_ref.get().operator[](m_idx);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline bool operator ==(const IndexBasedIterator& other) {
 | 
				
			||||||
 | 
					        size_t e = m_index_ref.get().size();
 | 
				
			||||||
 | 
					        return m_idx == other.m_idx || (m_idx >= e && other.m_idx >= e);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline bool operator !=(const IndexBasedIterator& other) {
 | 
				
			||||||
 | 
					        return !(*this == other);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline bool operator <=(const IndexBasedIterator& other) {
 | 
				
			||||||
 | 
					        return (m_idx < other.m_idx) || (*this == other);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline bool operator <(const IndexBasedIterator& other) {
 | 
				
			||||||
 | 
					        return m_idx < other.m_idx && (*this != other);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline bool operator >=(const IndexBasedIterator& other) {
 | 
				
			||||||
 | 
					        return m_idx > other.m_idx || *this == other;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline bool operator >(const IndexBasedIterator& other) {
 | 
				
			||||||
 | 
					        return m_idx > other.m_idx && *this != other;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<class It> class Range {
 | 
				
			||||||
 | 
					    It from, to;
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    It begin() const { return from; }
 | 
				
			||||||
 | 
					    It end() const { return to; }
 | 
				
			||||||
 | 
					    using Type = It;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Range() = default;
 | 
				
			||||||
 | 
					    Range(It &&b, It &&e):
 | 
				
			||||||
 | 
					        from(std::forward<It>(b)), to(std::forward<It>(e)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline size_t size() const { return end() - begin(); }
 | 
				
			||||||
 | 
					    inline bool empty() const { return size() == 0; }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif // MTUTILS_HPP
 | 
					#endif // MTUTILS_HPP
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2240,6 +2240,18 @@ SlicedSupports SLASupportTree::slice(float layerh, float init_layerh) const
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SlicedSupports SLASupportTree::slice(const std::vector<float> &heights,
 | 
				
			||||||
 | 
					                                     float cr) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TriangleMesh fullmesh = m_impl->merged_mesh();
 | 
				
			||||||
 | 
					    fullmesh.merge(get_pad());
 | 
				
			||||||
 | 
					    TriangleMeshSlicer slicer(&fullmesh);
 | 
				
			||||||
 | 
					    SlicedSupports ret;
 | 
				
			||||||
 | 
					    slicer.slice(heights, cr, &ret, get().ctl().cancelfn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const TriangleMesh &SLASupportTree::add_pad(const SliceLayer& baseplate,
 | 
					const TriangleMesh &SLASupportTree::add_pad(const SliceLayer& baseplate,
 | 
				
			||||||
                                            const PoolConfig& pcfg) const
 | 
					                                            const PoolConfig& pcfg) const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -181,6 +181,8 @@ public:
 | 
				
			||||||
    /// Get the sliced 2d layers of the support geometry.
 | 
					    /// Get the sliced 2d layers of the support geometry.
 | 
				
			||||||
    SlicedSupports slice(float layerh, float init_layerh = -1.0) const;
 | 
					    SlicedSupports slice(float layerh, float init_layerh = -1.0) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SlicedSupports slice(const std::vector<float>&, float closing_radius) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Adding the "pad" (base pool) under the supports
 | 
					    /// Adding the "pad" (base pool) under the supports
 | 
				
			||||||
    const TriangleMesh& add_pad(const SliceLayer& baseplate,
 | 
					    const TriangleMesh& add_pad(const SliceLayer& baseplate,
 | 
				
			||||||
                                const PoolConfig& pcfg) const;
 | 
					                                const PoolConfig& pcfg) const;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,6 @@ public:
 | 
				
			||||||
    std::vector<sla::SupportPoint> support_points;     // all the support points (manual/auto)
 | 
					    std::vector<sla::SupportPoint> support_points;     // all the support points (manual/auto)
 | 
				
			||||||
    SupportTreePtr   support_tree_ptr;   // the supports
 | 
					    SupportTreePtr   support_tree_ptr;   // the supports
 | 
				
			||||||
    SlicedSupports   support_slices;     // sliced supports
 | 
					    SlicedSupports   support_slices;     // sliced supports
 | 
				
			||||||
    std::vector<LevelID>    level_ids;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    inline SupportData(const TriangleMesh& trmesh): emesh(trmesh) {}
 | 
					    inline SupportData(const TriangleMesh& trmesh): emesh(trmesh) {}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -567,6 +566,18 @@ sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c) {
 | 
				
			||||||
    return scfg;
 | 
					    return scfg;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sla::PoolConfig make_pool_config(const SLAPrintObjectConfig& c) {
 | 
				
			||||||
 | 
					    sla::PoolConfig pcfg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pcfg.min_wall_thickness_mm = c.pad_wall_thickness.getFloat();
 | 
				
			||||||
 | 
					    pcfg.wall_slope = c.pad_wall_slope.getFloat();
 | 
				
			||||||
 | 
					    pcfg.edge_radius_mm = c.pad_edge_radius.getFloat();
 | 
				
			||||||
 | 
					    pcfg.max_merge_distance_mm = c.pad_max_merge_distance.getFloat();
 | 
				
			||||||
 | 
					    pcfg.min_wall_height_mm = c.pad_wall_height.getFloat();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return pcfg;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void swapXY(ExPolygon& expoly) {
 | 
					void swapXY(ExPolygon& expoly) {
 | 
				
			||||||
    for(auto& p : expoly.contour.points) std::swap(p(X), p(Y));
 | 
					    for(auto& p : expoly.contour.points) std::swap(p(X), p(Y));
 | 
				
			||||||
    for(auto& h : expoly.holes) for(auto& p : h.points) std::swap(p(X), p(Y));
 | 
					    for(auto& h : expoly.holes) for(auto& p : h.points) std::swap(p(X), p(Y));
 | 
				
			||||||
| 
						 | 
					@ -591,25 +602,9 @@ std::string SLAPrint::validate() const
 | 
				
			||||||
    return "";
 | 
					    return "";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::vector<float> SLAPrint::calculate_heights(const BoundingBoxf3& bb3d,
 | 
					 | 
				
			||||||
                                               float elevation,
 | 
					 | 
				
			||||||
                                               float initial_layer_height,
 | 
					 | 
				
			||||||
                                               float layer_height) const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    std::vector<float> heights;
 | 
					 | 
				
			||||||
    float minZ = float(bb3d.min(Z)) - float(elevation);
 | 
					 | 
				
			||||||
    float maxZ = float(bb3d.max(Z));
 | 
					 | 
				
			||||||
    auto flh = float(layer_height);
 | 
					 | 
				
			||||||
    auto gnd = float(bb3d.min(Z));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for(float h = minZ + initial_layer_height; h < maxZ; h += flh)
 | 
					 | 
				
			||||||
        if(h >= gnd) heights.emplace_back(h);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return heights;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
template<class...Args>
 | 
					template<class...Args>
 | 
				
			||||||
void report_status(SLAPrint& p, int st, const std::string& msg, Args&&...args) {
 | 
					void report_status(SLAPrint& p, int st, const std::string& msg, Args&&...args)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
    BOOST_LOG_TRIVIAL(info) << st << "% " << msg;
 | 
					    BOOST_LOG_TRIVIAL(info) << st << "% " << msg;
 | 
				
			||||||
    p.set_status(st, msg, std::forward<Args>(args)...);
 | 
					    p.set_status(st, msg, std::forward<Args>(args)...);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -620,12 +615,19 @@ void SLAPrint::process()
 | 
				
			||||||
    using namespace sla;
 | 
					    using namespace sla;
 | 
				
			||||||
    using ExPolygon = Slic3r::ExPolygon;
 | 
					    using ExPolygon = Slic3r::ExPolygon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(m_objects.empty()) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Assumption: at this point the print objects should be populated only with
 | 
					    // Assumption: at this point the print objects should be populated only with
 | 
				
			||||||
    // the model objects we have to process and the instances are also filtered
 | 
					    // the model objects we have to process and the instances are also filtered
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // shortcut to initial layer height
 | 
					    // shortcut to initial layer height
 | 
				
			||||||
    double ilhd = m_material_config.initial_layer_height.getFloat();
 | 
					    double ilhd = m_material_config.initial_layer_height.getFloat();
 | 
				
			||||||
    auto   ilh  = float(ilhd);
 | 
					    auto   ilh  = float(ilhd);
 | 
				
			||||||
 | 
					    double lhd  = m_objects.front()->m_config.layer_height.getFloat();
 | 
				
			||||||
 | 
					    float  lh   = float(lhd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto ilhs = LevelID(ilhd / SCALING_FACTOR);
 | 
				
			||||||
 | 
					    auto lhs  = LevelID(lhd  / SCALING_FACTOR);
 | 
				
			||||||
    const size_t objcount = m_objects.size();
 | 
					    const size_t objcount = m_objects.size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const unsigned min_objstatus = 0;   // where the per object operations start
 | 
					    const unsigned min_objstatus = 0;   // where the per object operations start
 | 
				
			||||||
| 
						 | 
					@ -646,24 +648,59 @@ void SLAPrint::process()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Slicing the model object. This method is oversimplified and needs to
 | 
					    // Slicing the model object. This method is oversimplified and needs to
 | 
				
			||||||
    // be compared with the fff slicing algorithm for verification
 | 
					    // be compared with the fff slicing algorithm for verification
 | 
				
			||||||
    auto slice_model = [this, ilh](SLAPrintObject& po) {
 | 
					    auto slice_model = [this, ilhs, lhs, ilh, lh](SLAPrintObject& po) {
 | 
				
			||||||
        double lh = po.m_config.layer_height.getFloat();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        TriangleMesh mesh = po.transformed_mesh();
 | 
					        TriangleMesh mesh = po.transformed_mesh();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // We need to prepare the slice index...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto&& bb3d = mesh.bounding_box();
 | 
				
			||||||
 | 
					        double minZ = bb3d.min(Z) - po.get_elevation();
 | 
				
			||||||
 | 
					        double maxZ = bb3d.max(Z);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto minZs = LevelID(minZ / SCALING_FACTOR);
 | 
				
			||||||
 | 
					        auto maxZs = LevelID(maxZ / SCALING_FACTOR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        po.m_slice_index.clear();
 | 
				
			||||||
 | 
					        po.m_slice_index.reserve(size_t(maxZs - (minZs + ilhs) / lhs) + 1);
 | 
				
			||||||
 | 
					        po.m_slice_index.emplace_back(minZs + ilhs, float(minZ) + ilh / 2.f, ilh);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for(LevelID h = minZs + ilhs + lhs; h <= maxZs; h += lhs) {
 | 
				
			||||||
 | 
					            po.m_slice_index.emplace_back(h, float(h*SCALING_FACTOR) - lh / 2.f, lh);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto slindex_it = po.search_slice_index(float(bb3d.min(Z)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(slindex_it == po.m_slice_index.end())
 | 
				
			||||||
 | 
					            throw std::runtime_error(L("Slicing had to be stopped "
 | 
				
			||||||
 | 
					                                       "due to an internal error."));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        po.m_model_height_levels.clear();
 | 
				
			||||||
 | 
					        po.m_model_height_levels.reserve(po.m_slice_index.size());
 | 
				
			||||||
 | 
					        for(auto it = slindex_it; it != po.m_slice_index.end(); ++it)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            po.m_model_height_levels.emplace_back(it->slice_level());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TriangleMeshSlicer slicer(&mesh);
 | 
					        TriangleMeshSlicer slicer(&mesh);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // The 1D grid heights
 | 
					        po.m_model_slices.clear();
 | 
				
			||||||
        std::vector<float> heights = calculate_heights(mesh.bounding_box(),
 | 
					        slicer.slice(po.m_model_height_levels,
 | 
				
			||||||
                                                       float(po.get_elevation()),
 | 
					                     float(po.config().slice_closing_radius.value),
 | 
				
			||||||
                                                       ilh, float(lh));
 | 
					                     &po.m_model_slices,
 | 
				
			||||||
 | 
					                     [this](){ throw_if_canceled(); });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto& layers = po.m_model_slices; layers.clear();
 | 
					        auto mit = slindex_it;
 | 
				
			||||||
		slicer.slice(heights, float(po.config().slice_closing_radius.value), &layers, [this](){ throw_if_canceled(); });
 | 
					        for(size_t id = 0;
 | 
				
			||||||
 | 
					            id < po.m_model_slices.size() && mit != po.m_slice_index.end();
 | 
				
			||||||
 | 
					            id++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            mit->set_model_slice_idx(id); ++mit;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // In this step we check the slices, identify island and cover them with
 | 
					    // In this step we check the slices, identify island and cover them with
 | 
				
			||||||
    // support points. Then we sprinkle the rest of the mesh.
 | 
					    // support points. Then we sprinkle the rest of the mesh.
 | 
				
			||||||
    auto support_points = [this, ilh](SLAPrintObject& po) {
 | 
					    auto support_points = [this](SLAPrintObject& po) {
 | 
				
			||||||
        const ModelObject& mo = *po.m_model_object;
 | 
					        const ModelObject& mo = *po.m_model_object;
 | 
				
			||||||
        po.m_supportdata.reset(
 | 
					        po.m_supportdata.reset(
 | 
				
			||||||
                    new SLAPrintObject::SupportData(po.transformed_mesh()) );
 | 
					                    new SLAPrintObject::SupportData(po.transformed_mesh()) );
 | 
				
			||||||
| 
						 | 
					@ -680,12 +717,7 @@ void SLAPrint::process()
 | 
				
			||||||
        if (mo.sla_points_status != sla::PointsStatus::UserModified) {
 | 
					        if (mo.sla_points_status != sla::PointsStatus::UserModified) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // calculate heights of slices (slices are calculated already)
 | 
					            // calculate heights of slices (slices are calculated already)
 | 
				
			||||||
            double lh = po.m_config.layer_height.getFloat();
 | 
					            const std::vector<float>& heights = po.m_model_height_levels;
 | 
				
			||||||
 | 
					 | 
				
			||||||
            std::vector<float> heights =
 | 
					 | 
				
			||||||
                    calculate_heights(po.transformed_mesh().bounding_box(),
 | 
					 | 
				
			||||||
                                      float(po.get_elevation()),
 | 
					 | 
				
			||||||
                                      ilh, float(lh));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this->throw_if_canceled();
 | 
					            this->throw_if_canceled();
 | 
				
			||||||
            SLAAutoSupports::Config config;
 | 
					            SLAAutoSupports::Config config;
 | 
				
			||||||
| 
						 | 
					@ -831,86 +863,34 @@ void SLAPrint::process()
 | 
				
			||||||
    // Slicing the support geometries similarly to the model slicing procedure.
 | 
					    // Slicing the support geometries similarly to the model slicing procedure.
 | 
				
			||||||
    // If the pad had been added previously (see step "base_pool" than it will
 | 
					    // If the pad had been added previously (see step "base_pool" than it will
 | 
				
			||||||
    // be part of the slices)
 | 
					    // be part of the slices)
 | 
				
			||||||
    auto slice_supports = [ilh](SLAPrintObject& po) {
 | 
					    auto slice_supports = [](SLAPrintObject& po) {
 | 
				
			||||||
        auto& sd = po.m_supportdata;
 | 
					        auto& sd = po.m_supportdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(sd) sd->support_slices.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(sd && sd->support_tree_ptr) {
 | 
					        if(sd && sd->support_tree_ptr) {
 | 
				
			||||||
            auto lh = float(po.m_config.layer_height.getFloat());
 | 
					
 | 
				
			||||||
            sd->support_slices = sd->support_tree_ptr->slice(lh, ilh);
 | 
					            std::vector<float> heights; heights.reserve(po.m_slice_index.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for(auto& rec : po.m_slice_index) {
 | 
				
			||||||
 | 
					                heights.emplace_back(rec.slice_level());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            sd->support_slices = sd->support_tree_ptr->slice(
 | 
				
			||||||
 | 
					                        heights, float(po.config().slice_closing_radius.value));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for(size_t i = 0;
 | 
				
			||||||
 | 
					            i < sd->support_slices.size() && i < po.m_slice_index.size();
 | 
				
			||||||
 | 
					            ++i)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            po.m_slice_index[i].set_support_slice_idx(i);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // We have the layer polygon collection but we need to unite them into
 | 
					    // We have the layer polygon collection but we need to unite them into
 | 
				
			||||||
    // an index where the key is the height level in discrete levels (clipper)
 | 
					    // an index where the key is the height level in discrete levels (clipper)
 | 
				
			||||||
    auto index_slices = [this, ilhd](SLAPrintObject& po) {
 | 
					    auto index_slices = [this/*, ilhd*/](SLAPrintObject& /*po*/) {
 | 
				
			||||||
        po.m_slice_index.clear();
 | 
					 | 
				
			||||||
        auto sih = LevelID(scale_(ilhd));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Establish the slice grid boundaries
 | 
					 | 
				
			||||||
        auto bb = po.transformed_mesh().bounding_box();
 | 
					 | 
				
			||||||
        double modelgnd = bb.min(Z);
 | 
					 | 
				
			||||||
        double elevation = po.get_elevation();
 | 
					 | 
				
			||||||
        double lh = po.m_config.layer_height.getFloat();
 | 
					 | 
				
			||||||
        double minZ = modelgnd - elevation;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // scaled values:
 | 
					 | 
				
			||||||
        auto sminZ = LevelID(scale_(minZ));
 | 
					 | 
				
			||||||
        auto smaxZ = LevelID(scale_(bb.max(Z)));
 | 
					 | 
				
			||||||
        auto smodelgnd = LevelID(scale_(modelgnd));
 | 
					 | 
				
			||||||
        auto slh = LevelID(scale_(lh));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // It is important that the next levels match the levels in
 | 
					 | 
				
			||||||
        // model_slice method. Only difference is that here it works with
 | 
					 | 
				
			||||||
        // scaled coordinates
 | 
					 | 
				
			||||||
        po.m_level_ids.clear();
 | 
					 | 
				
			||||||
        for(LevelID h = sminZ + sih; h < smaxZ; h += slh)
 | 
					 | 
				
			||||||
            if(h >= smodelgnd) po.m_level_ids.emplace_back(h);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::vector<ExPolygons>& oslices = po.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(po.m_level_ids.size() < oslices.size()) { // extend the levels until...
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            BOOST_LOG_TRIVIAL(warning)
 | 
					 | 
				
			||||||
                    << "Height level mismatch at rasterization!\n";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            LevelID lastlvl = po.m_level_ids.back();
 | 
					 | 
				
			||||||
            while(po.m_level_ids.size() < oslices.size()) {
 | 
					 | 
				
			||||||
                lastlvl += slh;
 | 
					 | 
				
			||||||
                po.m_level_ids.emplace_back(lastlvl);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for(size_t i = 0; i < oslices.size(); ++i) {
 | 
					 | 
				
			||||||
            LevelID h = po.m_level_ids[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            float fh = float(double(h) * SCALING_FACTOR);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // now for the public slice index:
 | 
					 | 
				
			||||||
            SLAPrintObject::SliceRecord& sr = po.m_slice_index[fh];
 | 
					 | 
				
			||||||
            // There should be only one slice layer for each print object
 | 
					 | 
				
			||||||
            assert(sr.model_slices_idx == SLAPrintObject::SliceRecord::NONE);
 | 
					 | 
				
			||||||
            sr.model_slices_idx = i;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(po.m_supportdata) { // deal with the support slices if present
 | 
					 | 
				
			||||||
            std::vector<ExPolygons>& sslices = po.m_supportdata->support_slices;
 | 
					 | 
				
			||||||
            po.m_supportdata->level_ids.clear();
 | 
					 | 
				
			||||||
            po.m_supportdata->level_ids.reserve(sslices.size());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            for(int i = 0; i < int(sslices.size()); ++i) {
 | 
					 | 
				
			||||||
                LevelID h = sminZ + sih + i * slh;
 | 
					 | 
				
			||||||
                po.m_supportdata->level_ids.emplace_back(h);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                float fh = float(double(h) * SCALING_FACTOR);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                SLAPrintObject::SliceRecord& sr = po.m_slice_index[fh];
 | 
					 | 
				
			||||||
                assert(sr.support_slices_idx == SLAPrintObject::SliceRecord::NONE);
 | 
					 | 
				
			||||||
                sr.support_slices_idx = SLAPrintObject::SliceRecord::Idx(i);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Using RELOAD_SLA_PREVIEW to tell the Plater to pass the update status to the 3D preview to load the SLA slices.
 | 
					        // Using RELOAD_SLA_PREVIEW to tell the Plater to pass the update status to the 3D preview to load the SLA slices.
 | 
				
			||||||
        report_status(*this, -2, "", SlicingStatus::RELOAD_SLA_PREVIEW);
 | 
					        report_status(*this, -2, "", SlicingStatus::RELOAD_SLA_PREVIEW);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
| 
						 | 
					@ -923,30 +903,18 @@ void SLAPrint::process()
 | 
				
			||||||
        m_printer_input.clear();
 | 
					        m_printer_input.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for(SLAPrintObject * o : m_objects) {
 | 
					        for(SLAPrintObject * o : m_objects) {
 | 
				
			||||||
            auto& po = *o;
 | 
					            LevelID gndlvl = o->get_slice_index().front().key();
 | 
				
			||||||
            std::vector<ExPolygons>& oslices = po.m_model_slices;
 | 
					            for(auto& slicerecord : o->get_slice_index()) {
 | 
				
			||||||
 | 
					                auto& lyrs = m_printer_input[slicerecord.key() - gndlvl];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // We need to adjust the min Z level of the slices to be zero
 | 
					                const ExPolygons& objslices = o->get_slices_from_record(slicerecord, soModel);
 | 
				
			||||||
            LevelID smfirst =
 | 
					                const ExPolygons& supslices = o->get_slices_from_record(slicerecord, soSupport);
 | 
				
			||||||
                    po.m_supportdata && !po.m_supportdata->level_ids.empty() ?
 | 
					 | 
				
			||||||
                        po.m_supportdata->level_ids.front() : 0;
 | 
					 | 
				
			||||||
            LevelID mfirst = po.m_level_ids.empty()? 0 : po.m_level_ids.front();
 | 
					 | 
				
			||||||
            LevelID gndlvl = -(std::min(smfirst, mfirst));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // now merge this object's support and object slices with the rest
 | 
					                if(!objslices.empty())
 | 
				
			||||||
            // of the print object slices
 | 
					                    lyrs.emplace_back(objslices, o->instances());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for(size_t i = 0; i < oslices.size(); ++i) {
 | 
					                if(!supslices.empty())
 | 
				
			||||||
                auto& lyrs = m_printer_input[gndlvl + po.m_level_ids[i]];
 | 
					                    lyrs.emplace_back(supslices, o->instances());
 | 
				
			||||||
                lyrs.emplace_back(oslices[i], po.m_instances);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if(!po.m_supportdata) continue;
 | 
					 | 
				
			||||||
            std::vector<ExPolygons>& sslices = po.m_supportdata->support_slices;
 | 
					 | 
				
			||||||
            for(size_t i = 0; i < sslices.size(); ++i) {
 | 
					 | 
				
			||||||
                LayerRefs& lyrs =
 | 
					 | 
				
			||||||
                       m_printer_input[gndlvl + po.m_supportdata->level_ids[i]];
 | 
					 | 
				
			||||||
                lyrs.emplace_back(sslices[i], po.m_instances);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1249,13 +1217,13 @@ void SLAPrint::fill_statistics()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // find highest object
 | 
					    // find highest object
 | 
				
			||||||
    // Which is a better bet? To compare by max_z or by number of layers in the index?
 | 
					    // Which is a better bet? To compare by max_z or by number of layers in the index?
 | 
				
			||||||
    double max_z = 0.;
 | 
					    float max_z = 0.;
 | 
				
			||||||
	size_t max_layers_cnt = 0;
 | 
						size_t max_layers_cnt = 0;
 | 
				
			||||||
    size_t highest_obj_idx = 0;
 | 
					    size_t highest_obj_idx = 0;
 | 
				
			||||||
	for (SLAPrintObject *&po : m_objects) {
 | 
						for (SLAPrintObject *&po : m_objects) {
 | 
				
			||||||
        const SLAPrintObject::SliceIndex& slice_index = po->get_slice_index();
 | 
					        const SLAPrintObject::SliceIndex& slice_index = po->get_slice_index();
 | 
				
			||||||
        if (! slice_index.empty()) {
 | 
					        if (! slice_index.empty()) {
 | 
				
			||||||
            double z = (-- slice_index.end())->first;
 | 
					            float z = (-- slice_index.end())->slice_level();
 | 
				
			||||||
            size_t cnt = slice_index.size();
 | 
					            size_t cnt = slice_index.size();
 | 
				
			||||||
            //if (z > max_z) {
 | 
					            //if (z > max_z) {
 | 
				
			||||||
            if (cnt > max_layers_cnt) {
 | 
					            if (cnt > max_layers_cnt) {
 | 
				
			||||||
| 
						 | 
					@ -1275,7 +1243,7 @@ void SLAPrint::fill_statistics()
 | 
				
			||||||
    int sliced_layer_cnt = 0;
 | 
					    int sliced_layer_cnt = 0;
 | 
				
			||||||
    for (const auto& layer : highest_obj_slice_index)
 | 
					    for (const auto& layer : highest_obj_slice_index)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        const double l_height = (layer.first == highest_obj_slice_index.begin()->first) ? init_layer_height : layer_height;
 | 
					        const double l_height = (layer.key() == highest_obj_slice_index.begin()->key()) ? init_layer_height : layer_height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Calculation of the consumed material 
 | 
					        // Calculation of the consumed material 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1284,21 +1252,22 @@ void SLAPrint::fill_statistics()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (SLAPrintObject * po : m_objects)
 | 
					        for (SLAPrintObject * po : m_objects)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            const SLAPrintObject::SliceRecord *record = nullptr;
 | 
					            const SLAPrintObject::_SliceRecord *record = nullptr;
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                const SLAPrintObject::SliceIndex& index = po->get_slice_index();
 | 
					                const SLAPrintObject::SliceIndex& index = po->get_slice_index();
 | 
				
			||||||
                auto key = layer.first;
 | 
					                auto it = po->search_slice_index(layer.slice_level() - float(EPSILON));
 | 
				
			||||||
				const SLAPrintObject::SliceIndex::const_iterator it_key = index.lower_bound(key - float(EPSILON));
 | 
					                if (it == index.end() || it->slice_level() > layer.slice_level() + float(EPSILON))
 | 
				
			||||||
                if (it_key == index.end() || it_key->first > key + EPSILON)
 | 
					 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                record = &it_key->second;
 | 
					                record = &(*it);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (record->model_slices_idx != SLAPrintObject::SliceRecord::NONE)
 | 
					            const ExPolygons &modelslices = po->get_slices_from_record(*record, soModel);
 | 
				
			||||||
                append(model_polygons, get_all_polygons(po->get_model_slices()[record->model_slices_idx], po->instances()));
 | 
					            if (!modelslices.empty())
 | 
				
			||||||
 | 
					                append(model_polygons, get_all_polygons(modelslices, po->instances()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (record->support_slices_idx != SLAPrintObject::SliceRecord::NONE)
 | 
					            const ExPolygons &supportslices = po->get_slices_from_record(*record, soSupport);
 | 
				
			||||||
                append(supports_polygons, get_all_polygons(po->get_support_slices()[record->support_slices_idx], po->instances()));
 | 
					            if (!supportslices.empty())
 | 
				
			||||||
 | 
					                append(supports_polygons, get_all_polygons(supportslices, po->instances()));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        model_polygons = union_(model_polygons);
 | 
					        model_polygons = union_(model_polygons);
 | 
				
			||||||
| 
						 | 
					@ -1394,11 +1363,15 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
 | 
				
			||||||
    for (const t_config_option_key &opt_key : opt_keys) {
 | 
					    for (const t_config_option_key &opt_key : opt_keys) {
 | 
				
			||||||
		if (   opt_key == "layer_height"
 | 
							if (   opt_key == "layer_height"
 | 
				
			||||||
            || opt_key == "faded_layers"
 | 
					            || opt_key == "faded_layers"
 | 
				
			||||||
 | 
					            || opt_key == "pad_enable"
 | 
				
			||||||
 | 
					            || opt_key == "pad_wall_thickness"
 | 
				
			||||||
 | 
					            || opt_key == "supports_enable"
 | 
				
			||||||
 | 
					            || opt_key == "support_object_elevation"
 | 
				
			||||||
            || opt_key == "slice_closing_radius") {
 | 
					            || opt_key == "slice_closing_radius") {
 | 
				
			||||||
			steps.emplace_back(slaposObjectSlice);
 | 
								steps.emplace_back(slaposObjectSlice);
 | 
				
			||||||
        } else if (
 | 
					        } else if (
 | 
				
			||||||
               opt_key == "supports_enable"
 | 
					
 | 
				
			||||||
            || opt_key == "support_points_density_relative"
 | 
					               opt_key == "support_points_density_relative"
 | 
				
			||||||
            || opt_key == "support_points_minimal_distance") {
 | 
					            || opt_key == "support_points_minimal_distance") {
 | 
				
			||||||
            steps.emplace_back(slaposSupportPoints);
 | 
					            steps.emplace_back(slaposSupportPoints);
 | 
				
			||||||
		} else if (
 | 
							} else if (
 | 
				
			||||||
| 
						 | 
					@ -1413,12 +1386,10 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
 | 
				
			||||||
            || opt_key == "support_critical_angle"
 | 
					            || opt_key == "support_critical_angle"
 | 
				
			||||||
            || opt_key == "support_max_bridge_length"
 | 
					            || opt_key == "support_max_bridge_length"
 | 
				
			||||||
            || opt_key == "support_max_pillar_link_distance"
 | 
					            || opt_key == "support_max_pillar_link_distance"
 | 
				
			||||||
            || opt_key == "support_object_elevation") {
 | 
					            ) {
 | 
				
			||||||
            steps.emplace_back(slaposSupportTree);
 | 
					            steps.emplace_back(slaposSupportTree);
 | 
				
			||||||
        } else if (
 | 
					        } else if (
 | 
				
			||||||
               opt_key == "pad_enable"
 | 
					               opt_key == "pad_wall_height"
 | 
				
			||||||
            || opt_key == "pad_wall_thickness"
 | 
					 | 
				
			||||||
            || opt_key == "pad_wall_height"
 | 
					 | 
				
			||||||
            || opt_key == "pad_max_merge_distance"
 | 
					            || opt_key == "pad_max_merge_distance"
 | 
				
			||||||
            || opt_key == "pad_wall_slope"
 | 
					            || opt_key == "pad_wall_slope"
 | 
				
			||||||
            || opt_key == "pad_edge_radius") {
 | 
					            || opt_key == "pad_edge_radius") {
 | 
				
			||||||
| 
						 | 
					@ -1474,11 +1445,7 @@ double SLAPrintObject::get_elevation() const {
 | 
				
			||||||
        // its walls but currently it is half of its thickness. Whatever it
 | 
					        // 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
 | 
					        // will be in the future, we provide the config to the get_pad_elevation
 | 
				
			||||||
        // method and we will have the correct value
 | 
					        // method and we will have the correct value
 | 
				
			||||||
        sla::PoolConfig pcfg;
 | 
					        sla::PoolConfig pcfg = make_pool_config(m_config);
 | 
				
			||||||
        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);
 | 
					        ret += sla::get_pad_elevation(pcfg);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1502,6 +1469,7 @@ double SLAPrintObject::get_current_elevation() const
 | 
				
			||||||
namespace { // dummy empty static containers for return values in some methods
 | 
					namespace { // dummy empty static containers for return values in some methods
 | 
				
			||||||
const std::vector<ExPolygons> EMPTY_SLICES;
 | 
					const std::vector<ExPolygons> EMPTY_SLICES;
 | 
				
			||||||
const TriangleMesh EMPTY_MESH;
 | 
					const TriangleMesh EMPTY_MESH;
 | 
				
			||||||
 | 
					const ExPolygons EMPTY_SLICE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const std::vector<sla::SupportPoint>& SLAPrintObject::get_support_points() const
 | 
					const std::vector<sla::SupportPoint>& SLAPrintObject::get_support_points() const
 | 
				
			||||||
| 
						 | 
					@ -1509,6 +1477,72 @@ const std::vector<sla::SupportPoint>& SLAPrintObject::get_support_points() const
 | 
				
			||||||
    return m_supportdata->support_points;
 | 
					    return m_supportdata->support_points;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SLAPrintObject::SliceIndex::iterator
 | 
				
			||||||
 | 
					SLAPrintObject::search_slice_index(float slice_level)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    _SliceRecord query(0, slice_level, 0);
 | 
				
			||||||
 | 
					    auto it = std::lower_bound(m_slice_index.begin(), m_slice_index.end(),
 | 
				
			||||||
 | 
					                               query,
 | 
				
			||||||
 | 
					                               [](const _SliceRecord& r1, const _SliceRecord& r2)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return r1.slice_level() < r2.slice_level();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return it;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SLAPrintObject::SliceIndex::const_iterator
 | 
				
			||||||
 | 
					SLAPrintObject::search_slice_index(float slice_level) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    _SliceRecord query(0, slice_level, 0);
 | 
				
			||||||
 | 
					    auto it = std::lower_bound(m_slice_index.cbegin(), m_slice_index.cend(),
 | 
				
			||||||
 | 
					                               query,
 | 
				
			||||||
 | 
					                               [](const _SliceRecord& r1, const _SliceRecord& r2)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return r1.slice_level() < r2.slice_level();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return it;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SLAPrintObject::SliceIndex::iterator
 | 
				
			||||||
 | 
					SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key,
 | 
				
			||||||
 | 
					                                   bool exact)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    _SliceRecord query(key, 0.f, 0.f);
 | 
				
			||||||
 | 
					    auto it = std::lower_bound(m_slice_index.begin(), m_slice_index.end(),
 | 
				
			||||||
 | 
					                               query,
 | 
				
			||||||
 | 
					                               [](const _SliceRecord& r1, const _SliceRecord& r2)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return r1.key() < r2.key();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Return valid iterator only if the keys really match
 | 
				
			||||||
 | 
					    if(exact && it != m_slice_index.end() && it->key() != key)
 | 
				
			||||||
 | 
					        it = m_slice_index.end();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return it;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SLAPrintObject::SliceIndex::const_iterator
 | 
				
			||||||
 | 
					SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key,
 | 
				
			||||||
 | 
					                                   bool exact) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    _SliceRecord query(key, 0.f, 0.f);
 | 
				
			||||||
 | 
					    auto it = std::lower_bound(m_slice_index.cbegin(), m_slice_index.cend(),
 | 
				
			||||||
 | 
					                               query,
 | 
				
			||||||
 | 
					                               [](const _SliceRecord& r1, const _SliceRecord& r2)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return r1.key() < r2.key();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Return valid iterator only if the keys really match
 | 
				
			||||||
 | 
					    if(exact && it != m_slice_index.end() && it->key() != key)
 | 
				
			||||||
 | 
					        it = m_slice_index.end();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return it;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const std::vector<ExPolygons> &SLAPrintObject::get_support_slices() const
 | 
					const std::vector<ExPolygons> &SLAPrintObject::get_support_slices() const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // assert(is_step_done(slaposSliceSupports));
 | 
					    // assert(is_step_done(slaposSliceSupports));
 | 
				
			||||||
| 
						 | 
					@ -1516,7 +1550,30 @@ const std::vector<ExPolygons> &SLAPrintObject::get_support_slices() const
 | 
				
			||||||
    return m_supportdata->support_slices;
 | 
					    return m_supportdata->support_slices;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const SLAPrintObject::SliceIndex &SLAPrintObject::get_slice_index() const
 | 
					const ExPolygons &SLAPrintObject::get_slices_from_record(
 | 
				
			||||||
 | 
					        const _SliceRecord &rec,
 | 
				
			||||||
 | 
					        SliceOrigin o) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    size_t idx = o == soModel ? rec.get_model_slice_idx() :
 | 
				
			||||||
 | 
					                                rec.get_support_slice_idx();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const std::vector<ExPolygons>& v = o == soModel? get_model_slices() :
 | 
				
			||||||
 | 
					                                                     get_support_slices();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(idx >= v.size()) return EMPTY_SLICE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return idx >= v.size() ? EMPTY_SLICE : v[idx];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ExPolygons &SLAPrintObject::get_slices_from_record(
 | 
				
			||||||
 | 
					        SLAPrintObject::SliceRecordConstIterator it, SliceOrigin o) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(it.is_end()) return EMPTY_SLICE;
 | 
				
			||||||
 | 
					    return get_slices_from_record(*it, o);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const std::vector<SLAPrintObject::_SliceRecord>&
 | 
				
			||||||
 | 
					SLAPrintObject::get_slice_index() const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // assert(is_step_done(slaposIndexSlices));
 | 
					    // assert(is_step_done(slaposIndexSlices));
 | 
				
			||||||
    return m_slice_index;
 | 
					    return m_slice_index;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@
 | 
				
			||||||
#include "PrintExport.hpp"
 | 
					#include "PrintExport.hpp"
 | 
				
			||||||
#include "Point.hpp"
 | 
					#include "Point.hpp"
 | 
				
			||||||
#include "MTUtils.hpp"
 | 
					#include "MTUtils.hpp"
 | 
				
			||||||
 | 
					#include <iterator>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Slic3r {
 | 
					namespace Slic3r {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,12 +36,19 @@ using _SLAPrintObjectBase =
 | 
				
			||||||
// the printer (rasterizer) in the SLAPrint class.
 | 
					// the printer (rasterizer) in the SLAPrint class.
 | 
				
			||||||
using LevelID = long long;
 | 
					using LevelID = long long;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum SliceOrigin { soSupport, soModel };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SLAPrintObject : public _SLAPrintObjectBase
 | 
					class SLAPrintObject : public _SLAPrintObjectBase
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
private: // Prevents erroneous use by other classes.
 | 
					private: // Prevents erroneous use by other classes.
 | 
				
			||||||
    using Inherited = _SLAPrintObjectBase;
 | 
					    using Inherited = _SLAPrintObjectBase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // I refuse to grantee copying (Tamas)
 | 
				
			||||||
 | 
					    SLAPrintObject(const SLAPrintObject&) = delete;
 | 
				
			||||||
 | 
					    SLAPrintObject& operator=(const SLAPrintObject&) = delete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const SLAPrintObjectConfig& config() const { return m_config; }
 | 
					    const SLAPrintObjectConfig& config() const { return m_config; }
 | 
				
			||||||
    const Transform3d&          trafo()  const { return m_trafo; }
 | 
					    const Transform3d&          trafo()  const { return m_trafo; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,40 +90,146 @@ public:
 | 
				
			||||||
    // pad is not, then without the pad, otherwise the full value is returned.
 | 
					    // pad is not, then without the pad, otherwise the full value is returned.
 | 
				
			||||||
    double get_current_elevation() const;
 | 
					    double get_current_elevation() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // These two methods should be callable on the client side (e.g. UI thread)
 | 
					 | 
				
			||||||
    // when the appropriate steps slaposObjectSlice and slaposSliceSupports
 | 
					 | 
				
			||||||
    // are ready. All the print objects are processed before slapsRasterize so
 | 
					 | 
				
			||||||
    // it is safe to call them during and/or after slapsRasterize.
 | 
					 | 
				
			||||||
    const std::vector<ExPolygons>& get_model_slices() const;
 | 
					 | 
				
			||||||
    const std::vector<ExPolygons>& get_support_slices() const;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // This method returns the support points of this SLAPrintObject.
 | 
					    // This method returns the support points of this SLAPrintObject.
 | 
				
			||||||
    const std::vector<sla::SupportPoint>& get_support_points() const;
 | 
					    const std::vector<sla::SupportPoint>& get_support_points() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // The public Slice record structure. It corresponds to one printable layer.
 | 
				
			||||||
 | 
					    // To get the sliced polygons, use SLAPrintObject::get_slices_from_record
 | 
				
			||||||
 | 
					    class SliceRecord {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        using Key = LevelID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					        Key   m_print_z = 0;      // Top of the layer
 | 
				
			||||||
 | 
					        float m_slice_z = 0.f;    // Exact level of the slice
 | 
				
			||||||
 | 
					        float m_height = 0.f;     // Height of the sliced layer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected:
 | 
				
			||||||
 | 
					        SliceRecord(Key key, float slicez, float height):
 | 
				
			||||||
 | 
					            m_print_z(key), m_slice_z(slicez), m_height(height) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // The key will be the integer height level of the top of the layer.
 | 
				
			||||||
 | 
					        inline Key key() const { return m_print_z; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Returns the exact floating point Z coordinate of the slice
 | 
				
			||||||
 | 
					        inline float slice_level() const { return m_slice_z; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Returns the current layer height
 | 
				
			||||||
 | 
					        inline float layer_height() const { return m_height; }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // An index record referencing the slices
 | 
					    // An index record referencing the slices
 | 
				
			||||||
    // (get_model_slices(), get_support_slices()) where the keys are the height
 | 
					    // (get_model_slices(), get_support_slices()) where the keys are the height
 | 
				
			||||||
    // levels of the model in scaled-clipper coordinates. The levels correspond
 | 
					    // levels of the model in scaled-clipper coordinates. The levels correspond
 | 
				
			||||||
    // to the z coordinate of the object coordinate system.
 | 
					    // to the z coordinate of the object coordinate system.
 | 
				
			||||||
    struct SliceRecord {
 | 
					    class _SliceRecord: public SliceRecord {
 | 
				
			||||||
        using Key = float;
 | 
					    public:
 | 
				
			||||||
 | 
					        static const size_t NONE = size_t(-1); // this will be the max limit of size_t
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					        size_t m_model_slices_idx = NONE;
 | 
				
			||||||
 | 
					        size_t m_support_slices_idx = NONE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        using Idx = size_t;
 | 
					    public:
 | 
				
			||||||
        static const Idx NONE = Idx(-1); // this will be the max limit of size_t
 | 
					        _SliceRecord(Key key, float slicez, float height):
 | 
				
			||||||
 | 
					            SliceRecord(key, slicez, height) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Idx model_slices_idx = NONE;
 | 
					        // Methods for setting the indices into the slice vectors.
 | 
				
			||||||
        Idx support_slices_idx = NONE;
 | 
					        void set_model_slice_idx(size_t id) { m_model_slices_idx = id; }
 | 
				
			||||||
 | 
					        void set_support_slice_idx(size_t id) { m_support_slices_idx = id; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inline size_t get_model_slice_idx() const { return m_model_slices_idx; }
 | 
				
			||||||
 | 
					        inline size_t get_support_slice_idx() const { return m_support_slices_idx; }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    using SliceIndex = std::map<SliceRecord::Key, SliceRecord>;
 | 
					    // Slice index will be a plain vector sorted by the integer height levels
 | 
				
			||||||
 | 
					    using SliceIndex = std::vector<_SliceRecord>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Retrieve the slice index which is readable only after slaposIndexSlices
 | 
					    // Retrieve the slice index which is readable only after slaposIndexSlices
 | 
				
			||||||
    // is done.
 | 
					    // is done.
 | 
				
			||||||
    const SliceIndex& get_slice_index() const;
 | 
					    const SliceIndex& get_slice_index() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // I refuse to grantee copying (Tamas)
 | 
					    // Search slice index for the closest slice to the given level
 | 
				
			||||||
    SLAPrintObject(const SLAPrintObject&) = delete;
 | 
					    SliceIndex::iterator search_slice_index(float slice_level);
 | 
				
			||||||
    SLAPrintObject& operator=(const SLAPrintObject&) = delete;
 | 
					    SliceIndex::const_iterator search_slice_index(float slice_level) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Search the slice index for a particular level in integer coordinates.
 | 
				
			||||||
 | 
					    // If no such layer is present, it will return m_slice_index.end()
 | 
				
			||||||
 | 
					    // This behavior can be suppressed by the second parameter. If it is true
 | 
				
			||||||
 | 
					    // the method will return the closest (non-equal) record
 | 
				
			||||||
 | 
					    SliceIndex::iterator search_slice_index(_SliceRecord::Key key, bool exact = false);
 | 
				
			||||||
 | 
					    SliceIndex::const_iterator search_slice_index(_SliceRecord::Key key, bool = false) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const std::vector<ExPolygons>& get_model_slices() const;
 | 
				
			||||||
 | 
					    const std::vector<ExPolygons>& get_support_slices() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Should work as a polymorphic bidirectional iterator to the slice records
 | 
				
			||||||
 | 
					    using SliceRecordConstIterator =
 | 
				
			||||||
 | 
					        IndexBasedIterator<const SliceIndex, const _SliceRecord>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // /////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // These two methods should be callable on the client side (e.g. UI thread)
 | 
				
			||||||
 | 
					    // when the appropriate steps slaposObjectSlice and slaposSliceSupports
 | 
				
			||||||
 | 
					    // are ready. All the print objects are processed before slapsRasterize so
 | 
				
			||||||
 | 
					    // it is safe to call them during and/or after slapsRasterize.
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // /////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Get the slice records from a range of slice levels (inclusive). Floating
 | 
				
			||||||
 | 
					    // point keys are the levels where the model was sliced with the mesh
 | 
				
			||||||
 | 
					    // slicer. Integral keys are the keys of the slice records, which
 | 
				
			||||||
 | 
					    // correspond to the top of each layer.. The end() method of the returned
 | 
				
			||||||
 | 
					    // range points *after* the last valid element. This is for being
 | 
				
			||||||
 | 
					    // consistent with std and makeing range based for loops work. use
 | 
				
			||||||
 | 
					    // std::prev(range.end()) or --range.end() to get the last element.
 | 
				
			||||||
 | 
					    template<class Key> Range<SliceRecordConstIterator>
 | 
				
			||||||
 | 
					    get_slice_records(Key from, Key to = std::numeric_limits<Key>::max()) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        SliceIndex::const_iterator it_from, it_to;
 | 
				
			||||||
 | 
					        if(std::is_integral<Key>::value) {
 | 
				
			||||||
 | 
					            it_from = search_slice_index(SliceRecord::Key(from));
 | 
				
			||||||
 | 
					            it_to   = search_slice_index(SliceRecord::Key(to));
 | 
				
			||||||
 | 
					        } else if(std::is_floating_point<Key>::value) {
 | 
				
			||||||
 | 
					            it_from = search_slice_index(float(from));
 | 
				
			||||||
 | 
					            it_to   = search_slice_index(float(to));
 | 
				
			||||||
 | 
					        } else return {
 | 
				
			||||||
 | 
					            SliceRecordConstIterator(m_slice_index, _SliceRecord::NONE ),
 | 
				
			||||||
 | 
					            SliceRecordConstIterator(m_slice_index, _SliceRecord::NONE ),
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto start = m_slice_index.begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        size_t bidx = it_from == m_slice_index.end() ? _SliceRecord::NONE :
 | 
				
			||||||
 | 
					                                                        size_t(it_from - start);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        size_t eidx = it_to   == m_slice_index.end() ? _SliceRecord::NONE :
 | 
				
			||||||
 | 
					                                                       size_t(it_to - start) + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            SliceRecordConstIterator(m_slice_index, bidx),
 | 
				
			||||||
 | 
					            SliceRecordConstIterator(m_slice_index, eidx),
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Get all the slice records as a range.
 | 
				
			||||||
 | 
					    inline Range<SliceRecordConstIterator> get_slice_records() const {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            SliceRecordConstIterator(m_slice_index, 0),
 | 
				
			||||||
 | 
					            SliceRecordConstIterator(m_slice_index, m_slice_index.size())
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const ExPolygons& get_slices_from_record(SliceRecordConstIterator it,
 | 
				
			||||||
 | 
					                                             SliceOrigin o) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const ExPolygons& get_slices_from_record(const _SliceRecord& rec,
 | 
				
			||||||
 | 
					                                             SliceOrigin o) const;
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
    // to be called from SLAPrint only.
 | 
					    // to be called from SLAPrint only.
 | 
				
			||||||
    friend class SLAPrint;
 | 
					    friend class SLAPrint;
 | 
				
			||||||
| 
						 | 
					@ -145,8 +259,10 @@ protected:
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    // Object specific configuration, pulled from the configuration layer.
 | 
					    // Object specific configuration, pulled from the configuration layer.
 | 
				
			||||||
    SLAPrintObjectConfig                    m_config;
 | 
					    SLAPrintObjectConfig                    m_config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Translation in Z + Rotation by Y and Z + Scaling / Mirroring.
 | 
					    // Translation in Z + Rotation by Y and Z + Scaling / Mirroring.
 | 
				
			||||||
    Transform3d                             m_trafo = Transform3d::Identity();
 | 
					    Transform3d                             m_trafo = Transform3d::Identity();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::vector<Instance> 					m_instances;
 | 
					    std::vector<Instance> 					m_instances;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Individual 2d slice polygons from lower z to higher z levels
 | 
					    // Individual 2d slice polygons from lower z to higher z levels
 | 
				
			||||||
| 
						 | 
					@ -154,11 +270,9 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Exact (float) height levels mapped to the slices. Each record contains
 | 
					    // Exact (float) height levels mapped to the slices. Each record contains
 | 
				
			||||||
    // the index to the model and the support slice vectors.
 | 
					    // the index to the model and the support slice vectors.
 | 
				
			||||||
    SliceIndex                              m_slice_index;
 | 
					    std::vector<_SliceRecord>               m_slice_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The height levels corrected and scaled up in integer values. This will
 | 
					    std::vector<float>                      m_model_height_levels;
 | 
				
			||||||
    // be used at rasterization.
 | 
					 | 
				
			||||||
    std::vector<LevelID>                    m_level_ids;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Caching the transformed (m_trafo) raw mesh of the object
 | 
					    // Caching the transformed (m_trafo) raw mesh of the object
 | 
				
			||||||
    mutable CachedObject<TriangleMesh>      m_transformed_rmesh;
 | 
					    mutable CachedObject<TriangleMesh>      m_transformed_rmesh;
 | 
				
			||||||
| 
						 | 
					@ -249,11 +363,6 @@ private:
 | 
				
			||||||
    // Invalidate steps based on a set of parameters changed.
 | 
					    // Invalidate steps based on a set of parameters changed.
 | 
				
			||||||
    bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
 | 
					    bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::vector<float> calculate_heights(const BoundingBoxf3& bb,
 | 
					 | 
				
			||||||
                                         float elevation,
 | 
					 | 
				
			||||||
                                         float initial_layer_height,
 | 
					 | 
				
			||||||
                                         float layer_height) const;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void fill_statistics();
 | 
					    void fill_statistics();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SLAPrintConfig                  m_print_config;
 | 
					    SLAPrintConfig                  m_print_config;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5013,32 +5013,56 @@ void GLCanvas3D::_render_sla_slices() const
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((bottom_obj_triangles.empty() || bottom_sup_triangles.empty() || top_obj_triangles.empty() || top_sup_triangles.empty()) && obj->is_step_done(slaposIndexSlices))
 | 
					        if ((bottom_obj_triangles.empty() || bottom_sup_triangles.empty() || top_obj_triangles.empty() || top_sup_triangles.empty()) && obj->is_step_done(slaposIndexSlices))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            const std::vector<ExPolygons>& model_slices = obj->get_model_slices();
 | 
					            // FIXME: is this all right (by Tamas)?
 | 
				
			||||||
            const std::vector<ExPolygons>& support_slices = obj->get_support_slices();
 | 
					            auto slice_range = obj->get_slice_records(coord_t(min_z / SCALING_FACTOR),
 | 
				
			||||||
 | 
					                                                      coord_t(max_z / SCALING_FACTOR));
 | 
				
			||||||
 | 
					            const ExPolygons& obj_bottom = obj->get_slices_from_record(slice_range.begin(), soModel);
 | 
				
			||||||
 | 
					            const ExPolygons& obj_top = obj->get_slices_from_record(std::prev(slice_range.end()), soModel);
 | 
				
			||||||
 | 
					            const ExPolygons& sup_bottom = obj->get_slices_from_record(slice_range.begin(), soSupport);
 | 
				
			||||||
 | 
					            const ExPolygons& sup_top = obj->get_slices_from_record(std::prev(slice_range.end()), soSupport);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const SLAPrintObject::SliceIndex& index = obj->get_slice_index();
 | 
					 | 
				
			||||||
            SLAPrintObject::SliceIndex::const_iterator it_min_z = std::find_if(index.begin(), index.end(), [min_z](const SLAPrintObject::SliceIndex::value_type& id) -> bool { return std::abs(min_z - id.first) < EPSILON; });
 | 
					 | 
				
			||||||
            SLAPrintObject::SliceIndex::const_iterator it_max_z = std::find_if(index.begin(), index.end(), [max_z](const SLAPrintObject::SliceIndex::value_type& id) -> bool { return std::abs(max_z - id.first) < EPSILON; });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (it_min_z != index.end())
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
            // calculate model bottom cap
 | 
					            // calculate model bottom cap
 | 
				
			||||||
                if (bottom_obj_triangles.empty() && (it_min_z->second.model_slices_idx < model_slices.size()))
 | 
					            if(bottom_obj_triangles.empty() && !obj_bottom.empty())
 | 
				
			||||||
                    bottom_obj_triangles = triangulate_expolygons_3d(model_slices[it_min_z->second.model_slices_idx], min_z, true);
 | 
					                bottom_obj_triangles = triangulate_expolygons_3d(obj_bottom, min_z, true);
 | 
				
			||||||
                // calculate support bottom cap
 | 
					
 | 
				
			||||||
                if (bottom_sup_triangles.empty() && (it_min_z->second.support_slices_idx < support_slices.size()))
 | 
					            // calculate support bottom cap
 | 
				
			||||||
                    bottom_sup_triangles = triangulate_expolygons_3d(support_slices[it_min_z->second.support_slices_idx], min_z, true);
 | 
					            if(bottom_sup_triangles.empty() && !sup_bottom.empty())
 | 
				
			||||||
            }
 | 
					                bottom_sup_triangles = triangulate_expolygons_3d(sup_bottom, min_z, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (it_max_z != index.end())
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
            // calculate model top cap
 | 
					            // calculate model top cap
 | 
				
			||||||
                if (top_obj_triangles.empty() && (it_max_z->second.model_slices_idx < model_slices.size()))
 | 
					            if(top_obj_triangles.empty() && !obj_top.empty())
 | 
				
			||||||
                    top_obj_triangles = triangulate_expolygons_3d(model_slices[it_max_z->second.model_slices_idx], max_z, false);
 | 
					                top_obj_triangles = triangulate_expolygons_3d(obj_top, max_z, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // calculate support top cap
 | 
					            // calculate support top cap
 | 
				
			||||||
                if (top_sup_triangles.empty() && (it_max_z->second.support_slices_idx < support_slices.size()))
 | 
					            if(top_sup_triangles.empty() && !sup_top.empty())
 | 
				
			||||||
					top_sup_triangles = triangulate_expolygons_3d(support_slices[it_max_z->second.support_slices_idx], max_z, false);
 | 
					                top_sup_triangles = triangulate_expolygons_3d(sup_top, max_z, false);
 | 
				
			||||||
            }
 | 
					
 | 
				
			||||||
 | 
					//            const std::vector<ExPolygons>& model_slices = obj->get_model_slices();
 | 
				
			||||||
 | 
					//            const std::vector<ExPolygons>& support_slices = obj->get_support_slices();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//            const SLAPrintObject::SliceIndex& index = obj->get_slice_index();
 | 
				
			||||||
 | 
					//            SLAPrintObject::SliceIndex::const_iterator it_min_z = std::find_if(index.begin(), index.end(), [min_z](const SLAPrintObject::SliceIndex::value_type& id) -> bool { return std::abs(min_z - id.first) < EPSILON; });
 | 
				
			||||||
 | 
					//            SLAPrintObject::SliceIndex::const_iterator it_max_z = std::find_if(index.begin(), index.end(), [max_z](const SLAPrintObject::SliceIndex::value_type& id) -> bool { return std::abs(max_z - id.first) < EPSILON; });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//            if (it_min_z != index.end())
 | 
				
			||||||
 | 
					//            {
 | 
				
			||||||
 | 
					//                // calculate model bottom cap
 | 
				
			||||||
 | 
					//                if (bottom_obj_triangles.empty() && (it_min_z->second.model_slices_idx < model_slices.size()))
 | 
				
			||||||
 | 
					//                    bottom_obj_triangles = triangulate_expolygons_3d(model_slices[it_min_z->second.model_slices_idx], min_z, true);
 | 
				
			||||||
 | 
					//                // calculate support bottom cap
 | 
				
			||||||
 | 
					//                if (bottom_sup_triangles.empty() && (it_min_z->second.support_slices_idx < support_slices.size()))
 | 
				
			||||||
 | 
					//                    bottom_sup_triangles = triangulate_expolygons_3d(support_slices[it_min_z->second.support_slices_idx], min_z, true);
 | 
				
			||||||
 | 
					//            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//            if (it_max_z != index.end())
 | 
				
			||||||
 | 
					//            {
 | 
				
			||||||
 | 
					//                // calculate model top cap
 | 
				
			||||||
 | 
					//                if (top_obj_triangles.empty() && (it_max_z->second.model_slices_idx < model_slices.size()))
 | 
				
			||||||
 | 
					//                    top_obj_triangles = triangulate_expolygons_3d(model_slices[it_max_z->second.model_slices_idx], max_z, false);
 | 
				
			||||||
 | 
					//                // calculate support top cap
 | 
				
			||||||
 | 
					//                if (top_sup_triangles.empty() && (it_max_z->second.support_slices_idx < support_slices.size()))
 | 
				
			||||||
 | 
					//					top_sup_triangles = triangulate_expolygons_3d(support_slices[it_max_z->second.support_slices_idx], max_z, false);
 | 
				
			||||||
 | 
					//            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!bottom_obj_triangles.empty() || !top_obj_triangles.empty() || !bottom_sup_triangles.empty() || !top_sup_triangles.empty())
 | 
					        if (!bottom_obj_triangles.empty() || !top_obj_triangles.empty() || !bottom_sup_triangles.empty() || !top_sup_triangles.empty())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -775,10 +775,10 @@ void Preview::load_print_as_sla()
 | 
				
			||||||
        double shift_z = obj->get_current_elevation();
 | 
					        double shift_z = obj->get_current_elevation();
 | 
				
			||||||
        if (obj->is_step_done(slaposIndexSlices))
 | 
					        if (obj->is_step_done(slaposIndexSlices))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            const SLAPrintObject::SliceIndex& index = obj->get_slice_index();
 | 
					            auto slicerecords = obj->get_slice_records();
 | 
				
			||||||
            for (const SLAPrintObject::SliceIndex::value_type& id : index)
 | 
					            for (auto& rec : slicerecords)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                zs.insert(shift_z + id.first);
 | 
					                zs.insert(shift_z + /*rec.slice_level()*/ rec.key() * SCALING_FACTOR);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue