From 19a96336ffad44ad3c38383e0d7c93047c4258ad Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 20 Mar 2019 18:03:11 +0100 Subject: [PATCH 1/7] WIP on slice indexing --- src/libslic3r/SLAPrint.cpp | 300 +++++++++++++++++++++++++------------ src/libslic3r/SLAPrint.hpp | 112 ++++++++++---- 2 files changed, 289 insertions(+), 123 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 83fa61fdd..62ddba84b 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -567,6 +567,18 @@ sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c) { 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) { 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)); @@ -647,18 +659,58 @@ void SLAPrint::process() // 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) { - double lh = po.m_config.layer_height.getFloat(); - TriangleMesh mesh = po.transformed_mesh(); + + // We need to prepare the slice index... + + auto&& bb3d = mesh.bounding_box(); + float minZ = float(bb3d.min(Z)) - float(po.get_elevation()); + float maxZ = float(bb3d.max(Z)); + auto flh = float(po.m_config.layer_height.getFloat()); + + auto slh = [](float h) { return LevelID( double(h) / SCALING_FACTOR); }; + + po.m_slice_index.clear(); + po.m_slice_index.reserve(size_t(maxZ - (minZ + ilh) / flh) + 1); + po.m_slice_index.emplace_back(slh(minZ + ilh), minZ + ilh / 2.f, ilh); + + for(float h = minZ + ilh + flh; h <= maxZ; h += flh) { + po.m_slice_index.emplace_back(slh(h), h - flh / 2.f, flh); + } + + + using SlRec = SLAPrintObject::SliceRecord; + auto slindex_it = std::lower_bound(po.m_slice_index.begin(), + po.m_slice_index.end(), + float(bb3d.min(Z)), // model start z + [](const SlRec& sr1, const SlRec& sr2){ + return sr1.slice_level() < sr2.slice_level(); + }); + + 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_height_levels.clear(); + po.m_height_levels.reserve(po.m_slice_index.size()); + for(auto it = slindex_it; it != po.m_slice_index.end(); ++it) + po.m_height_levels.emplace_back(it->slice_level()); + TriangleMeshSlicer slicer(&mesh); - // The 1D grid heights - std::vector heights = calculate_heights(mesh.bounding_box(), - float(po.get_elevation()), - ilh, float(lh)); + po.m_model_slices.clear(); + slicer.slice(po.m_height_levels, + float(po.config().slice_closing_radius.value), + &po.m_model_slices, + [this](){ throw_if_canceled(); }); - auto& layers = po.m_model_slices; layers.clear(); - slicer.slice(heights, float(po.config().slice_closing_radius.value), &layers, [this](){ throw_if_canceled(); }); + auto mit = slindex_it; + 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 @@ -680,12 +732,8 @@ void SLAPrint::process() if (mo.sla_points_status != sla::PointsStatus::UserModified) { // calculate heights of slices (slices are calculated already) - double lh = po.m_config.layer_height.getFloat(); - - std::vector heights = - calculate_heights(po.transformed_mesh().bounding_box(), - float(po.get_elevation()), - ilh, float(lh)); + auto&& bb = po.transformed_mesh().bounding_box(); + std::vector heights = po.get_slice_levels(float(bb.min(Z))); this->throw_if_canceled(); SLAAutoSupports::Config config; @@ -837,79 +885,86 @@ void SLAPrint::process() auto lh = float(po.m_config.layer_height.getFloat()); sd->support_slices = sd->support_tree_ptr->slice(lh, ilh); } + + 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 // an index where the key is the height level in discrete levels (clipper) auto index_slices = [this, ilhd](SLAPrintObject& po) { - po.m_slice_index.clear(); - auto sih = LevelID(scale_(ilhd)); +// 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; +// // 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)); +// // 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); +// // 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& oslices = po.m_model_slices; +// std::vector& 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... +// // 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"; +// 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); - } - } +// 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]; +// for(size_t i = 0; i < oslices.size(); ++i) { +// LevelID h = po.m_level_ids[i]; - float fh = float(double(h) * SCALING_FACTOR); +// 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; - } +// // 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& sslices = po.m_supportdata->support_slices; - po.m_supportdata->level_ids.clear(); - po.m_supportdata->level_ids.reserve(sslices.size()); +// if(po.m_supportdata) { // deal with the support slices if present +// std::vector& 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); +// 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); +// 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); - } - } +// 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. report_status(*this, -2, "", SlicingStatus::RELOAD_SLA_PREVIEW); @@ -923,31 +978,33 @@ void SLAPrint::process() m_printer_input.clear(); for(SLAPrintObject * o : m_objects) { - auto& po = *o; - std::vector& oslices = po.m_model_slices; +// auto& po = *o; +// std::vector& oslices = po.m_model_slices; - // We need to adjust the min Z level of the slices to be zero - LevelID smfirst = - 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)); +// // We need to adjust the min Z level of the slices to be zero +// LevelID smfirst = +// 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 - // of the print object slices +// // now merge this object's support and object slices with the rest +// // of the print object slices - for(size_t i = 0; i < oslices.size(); ++i) { - auto& lyrs = m_printer_input[gndlvl + po.m_level_ids[i]]; - lyrs.emplace_back(oslices[i], po.m_instances); - } +// for(size_t i = 0; i < oslices.size(); ++i) { +// auto& lyrs = m_printer_input[gndlvl + po.m_level_ids[i]]; +// lyrs.emplace_back(oslices[i], po.m_instances); +// } - if(!po.m_supportdata) continue; - std::vector& 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); - } +// if(!po.m_supportdata) continue; +// std::vector& 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); +// } + +// for(size_t i = 0; i < o->m_sli) } // collect all the keys @@ -1474,11 +1531,7 @@ double SLAPrintObject::get_elevation() const { // 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(); + sla::PoolConfig pcfg = make_pool_config(m_config); ret += sla::get_pad_elevation(pcfg); } @@ -1509,6 +1562,33 @@ const std::vector& SLAPrintObject::get_support_points() const return m_supportdata->support_points; } +SliceIterator SLAPrintObject::get_slices(SliceOrigin so, LevelID k) const +{ + SliceIterator ret = so == soModel ? get_model_slices().end() : + get_support_slices().end(); + + auto it = std::lower_bound(m_slice_index.begin(), + m_slice_index.end(), + k, + SliceRecord::cmpfn); + + if(it != m_slice_index.end()) { + ret = it->get_slices(*this, so); + } + + return ret; +} + +SliceRange SLAPrintObject::get_slices(SliceOrigin so, + float from_level, + float to_level) const +{ + auto from = LevelID(double(from_level) / SCALING_FACTOR); + auto to = LevelID(double(to_level) / SCALING_FACTOR); + + return SliceRange(get_slices(so, from), get_slices(so, to)); +} + const std::vector &SLAPrintObject::get_support_slices() const { // assert(is_step_done(slaposSliceSupports)); @@ -1516,12 +1596,28 @@ const std::vector &SLAPrintObject::get_support_slices() const return m_supportdata->support_slices; } -const SLAPrintObject::SliceIndex &SLAPrintObject::get_slice_index() const +const std::vector& +SLAPrintObject::get_slice_index() const { // assert(is_step_done(slaposIndexSlices)); return m_slice_index; } +std::vector SLAPrintObject::get_slice_levels(float from_eq) const +{ + using SlRec = SLAPrintObject::SliceRecord; + auto it = std::lower_bound(m_slice_index.begin(), + m_slice_index.end(), + from_eq, // model start z + [](const SlRec& sr1, const SlRec& sr2){ + return sr1.slice_level() < sr2.slice_level(); + }); + + std::vector heights; heights.reserve(m_slice_index.size()); + for(; it != m_slice_index.end(); ++it) + heights.emplace_back(it->slice_level()); +} + const std::vector &SLAPrintObject::get_model_slices() const { // assert(is_step_done(slaposObjectSlice)); @@ -1639,4 +1735,18 @@ std::string SLAPrintStatistics::finalize_output_path(const std::string &path_in) return final_path; } +SliceIterator SLAPrintObject::SliceRecord::get_slices(const SLAPrintObject &po, + SliceOrigin so) const +{ + + const std::vector& v = so == soModel? po.get_model_slices() : + po.get_support_slices(); + + Idx idx = so == soModel ? m_model_slices_idx : m_support_slices_idx; + + using DiffT = std::vector::const_iterator::difference_type; + + return idx == NONE? v.end() : v.begin() + DiffT(idx); +} + } // namespace Slic3r diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index c06e2fc77..4d5f1d0da 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -35,12 +35,34 @@ using _SLAPrintObjectBase = // the printer (rasterizer) in the SLAPrint class. using LevelID = long long; +template struct Range { + It from, to; + It begin() const { return from; } + It end() const { return to; } + using Type = It; + + Range() = default; + explicit Range(It &&b, It &&e): + from(std::forward(b)), to(std::forward(e)) {} +}; + +enum SliceOrigin { soSlice, soModel }; + +using SliceStore = std::vector; +using SliceIterator = SliceStore::const_iterator; +using SliceRange = Range; + class SLAPrintObject : public _SLAPrintObjectBase { private: // Prevents erroneous use by other classes. using Inherited = _SLAPrintObjectBase; public: + + // I refuse to grantee copying (Tamas) + SLAPrintObject(const SLAPrintObject&) = delete; + SLAPrintObject& operator=(const SLAPrintObject&) = delete; + const SLAPrintObjectConfig& config() const { return m_config; } const Transform3d& trafo() const { return m_trafo; } @@ -82,6 +104,66 @@ public: // pad is not, then without the pad, otherwise the full value is returned. double get_current_elevation() const; + // This method returns the support points of this SLAPrintObject. + const std::vector& get_support_points() const; + +private: + + // An index record referencing the slices + // (get_model_slices(), get_support_slices()) where the keys are the height + // levels of the model in scaled-clipper coordinates. The levels correspond + // to the z coordinate of the object coordinate system. + class SliceRecord { + public: + using Key = LevelID; + + private: + using Idx = size_t; + static const Idx NONE = Idx(-1); // this will be the max limit of size_t + + LevelID 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 + Idx m_model_slices_idx = NONE; + Idx m_support_slices_idx = NONE; + + public: + + SliceRecord(Key key, float slicez, float height): + m_print_z(key), m_slice_z(slicez), m_height(height) {} + + inline static bool cmpfn(const SliceRecord& sr1, const SliceRecord& sr2) + { + return sr1.key() < sr2.key(); + } + + inline Key key() const { return m_print_z; } + inline float slice_level() const { return m_slice_z; } + inline float layer_height() const { return m_height; } + + SliceIterator get_slices(const SLAPrintObject& po, + SliceOrigin so) const; + + void set_model_slice_idx(Idx id) { m_model_slices_idx = id; } + void set_support_slice_idx(Idx id) { m_support_slices_idx = id; } + }; + + + // Retrieve the slice index which is readable only after slaposIndexSlices + // is done. + const std::vector& get_slice_index() const; + + std::vector get_slice_levels(float from_eq) const; + +public: + + SliceIterator get_slices(SliceOrigin so, LevelID k) const; + + SliceRange get_slices( + SliceOrigin so, + float from_level, + float to_level = std::numeric_limits::infinity()) 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 @@ -89,33 +171,6 @@ public: const std::vector& get_model_slices() const; const std::vector& get_support_slices() const; - // This method returns the support points of this SLAPrintObject. - const std::vector& get_support_points() const; - - // An index record referencing the slices - // (get_model_slices(), get_support_slices()) where the keys are the height - // levels of the model in scaled-clipper coordinates. The levels correspond - // to the z coordinate of the object coordinate system. - struct SliceRecord { - using Key = float; - - using Idx = size_t; - static const Idx NONE = Idx(-1); // this will be the max limit of size_t - - Idx model_slices_idx = NONE; - Idx support_slices_idx = NONE; - }; - - using SliceIndex = std::map; - - // Retrieve the slice index which is readable only after slaposIndexSlices - // is done. - const SliceIndex& get_slice_index() const; - - // I refuse to grantee copying (Tamas) - SLAPrintObject(const SLAPrintObject&) = delete; - SLAPrintObject& operator=(const SLAPrintObject&) = delete; - protected: // to be called from SLAPrint only. friend class SLAPrint; @@ -154,11 +209,12 @@ private: // Exact (float) height levels mapped to the slices. Each record contains // the index to the model and the support slice vectors. - SliceIndex m_slice_index; + std::vector m_slice_index; // The height levels corrected and scaled up in integer values. This will // be used at rasterization. std::vector m_level_ids; + std::vector m_height_levels; // Caching the transformed (m_trafo) raw mesh of the object mutable CachedObject m_transformed_rmesh; From d4dde12d0d031970113706a5dd954907776216ed Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 21 Mar 2019 12:25:33 +0100 Subject: [PATCH 2/7] Slic3r compiles with the new slice index interface. --- src/libslic3r/SLAPrint.cpp | 151 +++++++++++++++++++++++---------- src/libslic3r/SLAPrint.hpp | 32 ++++--- src/slic3r/GUI/GLCanvas3D.cpp | 66 +++++++++----- src/slic3r/GUI/GUI_Preview.cpp | 6 +- 4 files changed, 172 insertions(+), 83 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 62ddba84b..938f148a3 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -678,14 +678,7 @@ void SLAPrint::process() po.m_slice_index.emplace_back(slh(h), h - flh / 2.f, flh); } - - using SlRec = SLAPrintObject::SliceRecord; - auto slindex_it = std::lower_bound(po.m_slice_index.begin(), - po.m_slice_index.end(), - float(bb3d.min(Z)), // model start z - [](const SlRec& sr1, const SlRec& sr2){ - return sr1.slice_level() < sr2.slice_level(); - }); + 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 " @@ -715,7 +708,7 @@ void SLAPrint::process() // In this step we check the slices, identify island and cover them with // 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; po.m_supportdata.reset( new SLAPrintObject::SupportData(po.transformed_mesh()) ); @@ -732,8 +725,7 @@ void SLAPrint::process() if (mo.sla_points_status != sla::PointsStatus::UserModified) { // calculate heights of slices (slices are calculated already) - auto&& bb = po.transformed_mesh().bounding_box(); - std::vector heights = po.get_slice_levels(float(bb.min(Z))); + const std::vector& heights = po.m_height_levels; this->throw_if_canceled(); SLAAutoSupports::Config config; @@ -896,7 +888,7 @@ void SLAPrint::process() // 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) - auto index_slices = [this, ilhd](SLAPrintObject& po) { + auto index_slices = [this/*, ilhd*/](SLAPrintObject& /*po*/) { // po.m_slice_index.clear(); // auto sih = LevelID(scale_(ilhd)); @@ -978,6 +970,19 @@ void SLAPrint::process() m_printer_input.clear(); for(SLAPrintObject * o : m_objects) { + LevelID gndlvl = o->get_slice_index().front().key(); + for(auto& slicerecord : o->get_slice_index()) { + auto& lyrs = m_printer_input[slicerecord.key() - gndlvl]; + auto objslit = slicerecord.get_slices(*o, soModel); + auto supslit = slicerecord.get_slices(*o, soSupport); + + if(objslit != o->get_model_slices().end()) + lyrs.emplace_back(*objslit, o->instances()); + + if(supslit != o->get_support_slices().end()) + lyrs.emplace_back(*supslit, o->instances()); + } + // auto& po = *o; // std::vector& oslices = po.m_model_slices; @@ -1003,8 +1008,6 @@ void SLAPrint::process() // m_printer_input[gndlvl + po.m_supportdata->level_ids[i]]; // lyrs.emplace_back(sslices[i], po.m_instances); // } - -// for(size_t i = 0; i < o->m_sli) } // collect all the keys @@ -1306,13 +1309,13 @@ void SLAPrint::fill_statistics() // find highest object // 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 highest_obj_idx = 0; for (SLAPrintObject *&po : m_objects) { const SLAPrintObject::SliceIndex& slice_index = po->get_slice_index(); if (! slice_index.empty()) { - double z = (-- slice_index.end())->first; + float z = (-- slice_index.end())->slice_level(); size_t cnt = slice_index.size(); //if (z > max_z) { if (cnt > max_layers_cnt) { @@ -1332,7 +1335,7 @@ void SLAPrint::fill_statistics() int sliced_layer_cnt = 0; 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 @@ -1344,18 +1347,19 @@ void SLAPrint::fill_statistics() const SLAPrintObject::SliceRecord *record = nullptr; { const SLAPrintObject::SliceIndex& index = po->get_slice_index(); - auto key = layer.first; - const SLAPrintObject::SliceIndex::const_iterator it_key = index.lower_bound(key - float(EPSILON)); - if (it_key == index.end() || it_key->first > key + EPSILON) + auto it = po->search_slice_index(layer.slice_level() - float(EPSILON)); + if (it == index.end() || it->slice_level() > layer.slice_level() + float(EPSILON)) continue; - record = &it_key->second; + record = &(*it); } - if (record->model_slices_idx != SLAPrintObject::SliceRecord::NONE) - append(model_polygons, get_all_polygons(po->get_model_slices()[record->model_slices_idx], po->instances())); + auto modelslice_it = record->get_slices(*po, soModel); + if (modelslice_it != po->get_model_slices().end()) + append(model_polygons, get_all_polygons(*modelslice_it, po->instances())); - if (record->support_slices_idx != SLAPrintObject::SliceRecord::NONE) - append(supports_polygons, get_all_polygons(po->get_support_slices()[record->support_slices_idx], po->instances())); + auto supportslice_it = record->get_slices(*po, soSupport); + if (supportslice_it != po->get_support_slices().end()) + append(supports_polygons, get_all_polygons(*supportslice_it, po->instances())); } model_polygons = union_(model_polygons); @@ -1562,15 +1566,74 @@ const std::vector& SLAPrintObject::get_support_points() const 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) +{ + 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(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) 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(it != m_slice_index.end() && it->key() != key) it = m_slice_index.end(); + + return it; +} + SliceIterator SLAPrintObject::get_slices(SliceOrigin so, LevelID k) const { SliceIterator ret = so == soModel ? get_model_slices().end() : get_support_slices().end(); - auto it = std::lower_bound(m_slice_index.begin(), - m_slice_index.end(), - k, - SliceRecord::cmpfn); + auto it = search_slice_index(k); if(it != m_slice_index.end()) { ret = it->get_slices(*this, so); @@ -1603,20 +1666,22 @@ SLAPrintObject::get_slice_index() const return m_slice_index; } -std::vector SLAPrintObject::get_slice_levels(float from_eq) const -{ - using SlRec = SLAPrintObject::SliceRecord; - auto it = std::lower_bound(m_slice_index.begin(), - m_slice_index.end(), - from_eq, // model start z - [](const SlRec& sr1, const SlRec& sr2){ - return sr1.slice_level() < sr2.slice_level(); - }); +//std::vector SLAPrintObject::get_slice_levels(float from_eq) const +//{ +// using SlRec = SLAPrintObject::SliceRecord; +// auto it = std::lower_bound(m_slice_index.begin(), +// m_slice_index.end(), +// from_eq, // model start z +// [](const SlRec& sr1, const SlRec& sr2){ +// return sr1.slice_level() < sr2.slice_level(); +// }); - std::vector heights; heights.reserve(m_slice_index.size()); - for(; it != m_slice_index.end(); ++it) - heights.emplace_back(it->slice_level()); -} +// std::vector heights; heights.reserve(m_slice_index.size()); +// for(; it != m_slice_index.end(); ++it) +// heights.emplace_back(it->slice_level()); + + +//} const std::vector &SLAPrintObject::get_model_slices() const { @@ -1742,7 +1807,7 @@ SliceIterator SLAPrintObject::SliceRecord::get_slices(const SLAPrintObject &po, const std::vector& v = so == soModel? po.get_model_slices() : po.get_support_slices(); - Idx idx = so == soModel ? m_model_slices_idx : m_support_slices_idx; + size_t idx = so == soModel ? m_model_slices_idx : m_support_slices_idx; using DiffT = std::vector::const_iterator::difference_type; diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 4d5f1d0da..620462875 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -46,7 +46,7 @@ template struct Range { from(std::forward(b)), to(std::forward(e)) {} }; -enum SliceOrigin { soSlice, soModel }; +enum SliceOrigin { soSupport, soModel }; using SliceStore = std::vector; using SliceIterator = SliceStore::const_iterator; @@ -118,25 +118,19 @@ private: using Key = LevelID; private: - using Idx = size_t; - static const Idx NONE = Idx(-1); // this will be the max limit of size_t + static const size_t NONE = size_t(-1); // this will be the max limit of size_t + size_t m_model_slices_idx = NONE; + size_t m_support_slices_idx = NONE; LevelID 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 - Idx m_model_slices_idx = NONE; - Idx m_support_slices_idx = NONE; public: SliceRecord(Key key, float slicez, float height): m_print_z(key), m_slice_z(slicez), m_height(height) {} - inline static bool cmpfn(const SliceRecord& sr1, const SliceRecord& sr2) - { - return sr1.key() < sr2.key(); - } - inline Key key() const { return m_print_z; } inline float slice_level() const { return m_slice_z; } inline float layer_height() const { return m_height; } @@ -144,16 +138,22 @@ private: SliceIterator get_slices(const SLAPrintObject& po, SliceOrigin so) const; - void set_model_slice_idx(Idx id) { m_model_slices_idx = id; } - void set_support_slice_idx(Idx id) { m_support_slices_idx = id; } + + 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; } + }; + using SliceIndex = std::vector; // Retrieve the slice index which is readable only after slaposIndexSlices // is done. - const std::vector& get_slice_index() const; + const SliceIndex& get_slice_index() const; - std::vector get_slice_levels(float from_eq) const; + SliceIndex::iterator search_slice_index(float slice_level); + SliceIndex::const_iterator search_slice_index(float slice_level) const; + SliceIndex::iterator search_slice_index(SliceRecord::Key key); + SliceIndex::const_iterator search_slice_index(SliceRecord::Key key) const; public: @@ -171,6 +171,10 @@ public: const std::vector& get_model_slices() const; const std::vector& get_support_slices() const; + inline const std::vector& get_height_levels() const { + return m_height_levels; + } + protected: // to be called from SLAPrint only. friend class SLAPrint; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 1c09096a8..7bd63aa3c 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4937,32 +4937,52 @@ 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)) { - const std::vector& model_slices = obj->get_model_slices(); - const std::vector& support_slices = obj->get_support_slices(); + // FIXME: is this all right (by Tamas)? + SliceRange model_slices = obj->get_slices(soModel, float(min_z), float(max_z)); + SliceRange support_slices = obj->get_slices(soSupport, float(min_z), float(max_z)); - 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; }); + // calculate model bottom cap + if(bottom_obj_triangles.empty() && model_slices.from != obj->get_model_slices().end()) + bottom_obj_triangles = triangulate_expolygons_3d(*model_slices.from, min_z, true); - 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); - } + // calculate support bottom cap + if(bottom_sup_triangles.empty() && support_slices.from != obj->get_support_slices().end()) + bottom_sup_triangles = triangulate_expolygons_3d(*support_slices.from, 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); - } + // calculate model top cap + if(top_obj_triangles.empty() && model_slices.to != obj->get_model_slices().end()) + top_obj_triangles = triangulate_expolygons_3d(*model_slices.to, max_z, true); + + // calculate support top cap + if(top_sup_triangles.empty() && support_slices.to != obj->get_support_slices().end()) + top_sup_triangles = triangulate_expolygons_3d(*support_slices.to, max_z, true); + +// const std::vector& model_slices = obj->get_model_slices(); +// const std::vector& 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()) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index be3fad9ec..f691850b4 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -776,10 +776,10 @@ void Preview::load_print_as_sla() double shift_z = obj->get_current_elevation(); if (obj->is_step_done(slaposIndexSlices)) { - const SLAPrintObject::SliceIndex& index = obj->get_slice_index(); - for (const SLAPrintObject::SliceIndex::value_type& id : index) + const std::vector& hlvls = obj->get_height_levels(); + for (float h : hlvls) { - zs.insert(shift_z + id.first); + zs.insert(shift_z + double(h)); } } } From 24a5dd4235764cd767e0bdfd7f69ee45f85deba2 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 21 Mar 2019 15:16:33 +0100 Subject: [PATCH 3/7] FIx for broken slice preview --- src/libslic3r/SLAPrint.cpp | 46 ++++++++++++++-------------------- src/libslic3r/SLAPrint.hpp | 12 ++++----- src/slic3r/GUI/GLCanvas3D.cpp | 22 ++++++++-------- src/slic3r/GUI/GUI_Preview.cpp | 6 ++--- 4 files changed, 40 insertions(+), 46 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 938f148a3..e12dc7f23 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -30,7 +30,6 @@ public: std::vector support_points; // all the support points (manual/auto) SupportTreePtr support_tree_ptr; // the supports SlicedSupports support_slices; // sliced supports - std::vector level_ids; inline SupportData(const TriangleMesh& trmesh): emesh(trmesh) {} }; @@ -603,25 +602,9 @@ std::string SLAPrint::validate() const return ""; } -std::vector SLAPrint::calculate_heights(const BoundingBoxf3& bb3d, - float elevation, - float initial_layer_height, - float layer_height) const -{ - std::vector 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 -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; p.set_status(st, msg, std::forward(args)...); } @@ -684,15 +667,17 @@ void SLAPrint::process() throw std::runtime_error(L("Slicing had to be stopped " "due to an internal error.")); - po.m_height_levels.clear(); - po.m_height_levels.reserve(po.m_slice_index.size()); + 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_height_levels.emplace_back(it->slice_level()); + { + po.m_model_height_levels.emplace_back(it->slice_level()); + } TriangleMeshSlicer slicer(&mesh); po.m_model_slices.clear(); - slicer.slice(po.m_height_levels, + slicer.slice(po.m_model_height_levels, float(po.config().slice_closing_radius.value), &po.m_model_slices, [this](){ throw_if_canceled(); }); @@ -725,7 +710,7 @@ void SLAPrint::process() if (mo.sla_points_status != sla::PointsStatus::UserModified) { // calculate heights of slices (slices are calculated already) - const std::vector& heights = po.m_height_levels; + const std::vector& heights = po.m_model_height_levels; this->throw_if_canceled(); SLAAutoSupports::Config config; @@ -1646,10 +1631,17 @@ SliceRange SLAPrintObject::get_slices(SliceOrigin so, float from_level, float to_level) const { - auto from = LevelID(double(from_level) / SCALING_FACTOR); - auto to = LevelID(double(to_level) / SCALING_FACTOR); + auto it_from = search_slice_index(from_level); + auto it_to = search_slice_index(to_level); - return SliceRange(get_slices(so, from), get_slices(so, to)); + SliceRange ret; + + auto endit = so == soModel? get_model_slices().end() : get_support_slices().end(); + + ret.from = it_from == m_slice_index.end() ? endit : it_from->get_slices(*this, so); + ret.to = it_to == m_slice_index.end() ? endit : it_to->get_slices(*this, so); + + return ret; } const std::vector &SLAPrintObject::get_support_slices() const diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 620462875..e86080963 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -171,8 +171,9 @@ public: const std::vector& get_model_slices() const; const std::vector& get_support_slices() const; - inline const std::vector& get_height_levels() const { - return m_height_levels; + inline size_t get_slice_count() const { return m_slice_index.size(); } + inline float get_slice_level(size_t idx) const { + return m_slice_index[idx].slice_level(); } protected: @@ -204,8 +205,10 @@ protected: private: // Object specific configuration, pulled from the configuration layer. SLAPrintObjectConfig m_config; + // Translation in Z + Rotation by Y and Z + Scaling / Mirroring. Transform3d m_trafo = Transform3d::Identity(); + std::vector m_instances; // Individual 2d slice polygons from lower z to higher z levels @@ -215,10 +218,7 @@ private: // the index to the model and the support slice vectors. std::vector m_slice_index; - // The height levels corrected and scaled up in integer values. This will - // be used at rasterization. - std::vector m_level_ids; - std::vector m_height_levels; + std::vector m_model_height_levels; // Caching the transformed (m_trafo) raw mesh of the object mutable CachedObject m_transformed_rmesh; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 7bd63aa3c..90656c93b 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4938,24 +4938,26 @@ 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)) { // FIXME: is this all right (by Tamas)? - SliceRange model_slices = obj->get_slices(soModel, float(min_z), float(max_z)); - SliceRange support_slices = obj->get_slices(soSupport, float(min_z), float(max_z)); + SliceRange obj_range = obj->get_slices(soModel, float(min_z), float(max_z)); + SliceRange sup_range = obj->get_slices(soSupport, float(min_z), float(max_z)); + auto obj_end = obj->get_model_slices().end(); + auto sup_end = obj->get_support_slices().end(); // calculate model bottom cap - if(bottom_obj_triangles.empty() && model_slices.from != obj->get_model_slices().end()) - bottom_obj_triangles = triangulate_expolygons_3d(*model_slices.from, min_z, true); + if(bottom_obj_triangles.empty() && obj_range.from != obj_end) + bottom_obj_triangles = triangulate_expolygons_3d(*obj_range.from, min_z, true); // calculate support bottom cap - if(bottom_sup_triangles.empty() && support_slices.from != obj->get_support_slices().end()) - bottom_sup_triangles = triangulate_expolygons_3d(*support_slices.from, min_z, true); + if(bottom_sup_triangles.empty() && sup_range.from != sup_end) + bottom_sup_triangles = triangulate_expolygons_3d(*sup_range.from, min_z, true); // calculate model top cap - if(top_obj_triangles.empty() && model_slices.to != obj->get_model_slices().end()) - top_obj_triangles = triangulate_expolygons_3d(*model_slices.to, max_z, true); + if(top_obj_triangles.empty() && obj_range.to != obj_end) + top_obj_triangles = triangulate_expolygons_3d(*obj_range.to, max_z, false); // calculate support top cap - if(top_sup_triangles.empty() && support_slices.to != obj->get_support_slices().end()) - top_sup_triangles = triangulate_expolygons_3d(*support_slices.to, max_z, true); + if(top_sup_triangles.empty() && sup_range.to != sup_end) + top_sup_triangles = triangulate_expolygons_3d(*sup_range.to, max_z, false); // const std::vector& model_slices = obj->get_model_slices(); // const std::vector& support_slices = obj->get_support_slices(); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index f691850b4..477673342 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -776,10 +776,10 @@ void Preview::load_print_as_sla() double shift_z = obj->get_current_elevation(); if (obj->is_step_done(slaposIndexSlices)) { - const std::vector& hlvls = obj->get_height_levels(); - for (float h : hlvls) + size_t cnt = obj->get_slice_count(); + for (size_t i = 0; i < cnt; i++) { - zs.insert(shift_z + double(h)); + zs.insert(shift_z + double(obj->get_slice_level(i))); } } } From 63a899b239a6ee8717102871aaea0122aab1ed34 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 21 Mar 2019 16:14:26 +0100 Subject: [PATCH 4/7] Using same slicing grid for the supports and the model. --- src/libslic3r/SLA/SLASupportTree.cpp | 12 ++++++++ src/libslic3r/SLA/SLASupportTree.hpp | 2 ++ src/libslic3r/SLAPrint.cpp | 45 +++++++--------------------- src/libslic3r/SLAPrint.hpp | 35 ++++++++++++++++++---- 4 files changed, 54 insertions(+), 40 deletions(-) diff --git a/src/libslic3r/SLA/SLASupportTree.cpp b/src/libslic3r/SLA/SLASupportTree.cpp index df9990822..34dd80cee 100644 --- a/src/libslic3r/SLA/SLASupportTree.cpp +++ b/src/libslic3r/SLA/SLASupportTree.cpp @@ -2240,6 +2240,18 @@ SlicedSupports SLASupportTree::slice(float layerh, float init_layerh) const return ret; } +SlicedSupports SLASupportTree::slice(const std::vector &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 PoolConfig& pcfg) const { diff --git a/src/libslic3r/SLA/SLASupportTree.hpp b/src/libslic3r/SLA/SLASupportTree.hpp index 74d7da9ca..66677e4d7 100644 --- a/src/libslic3r/SLA/SLASupportTree.hpp +++ b/src/libslic3r/SLA/SLASupportTree.hpp @@ -181,6 +181,8 @@ public: /// Get the sliced 2d layers of the support geometry. SlicedSupports slice(float layerh, float init_layerh = -1.0) const; + SlicedSupports slice(const std::vector&, float closing_radius) const; + /// Adding the "pad" (base pool) under the supports const TriangleMesh& add_pad(const SliceLayer& baseplate, const PoolConfig& pcfg) const; diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index e12dc7f23..bbf53ef7e 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -856,11 +856,19 @@ void SLAPrint::process() // Slicing the support geometries similarly to the model slicing procedure. // If the pad had been added previously (see step "base_pool" than it will // be part of the slices) - auto slice_supports = [ilh](SLAPrintObject& po) { + auto slice_supports = [](SLAPrintObject& po) { auto& sd = po.m_supportdata; 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); + sd->support_slices.clear(); + + std::vector 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; @@ -1613,20 +1621,6 @@ SLAPrintObject::search_slice_index(SLAPrintObject::SliceRecord::Key key) const return it; } -SliceIterator SLAPrintObject::get_slices(SliceOrigin so, LevelID k) const -{ - SliceIterator ret = so == soModel ? get_model_slices().end() : - get_support_slices().end(); - - auto it = search_slice_index(k); - - if(it != m_slice_index.end()) { - ret = it->get_slices(*this, so); - } - - return ret; -} - SliceRange SLAPrintObject::get_slices(SliceOrigin so, float from_level, float to_level) const @@ -1658,23 +1652,6 @@ SLAPrintObject::get_slice_index() const return m_slice_index; } -//std::vector SLAPrintObject::get_slice_levels(float from_eq) const -//{ -// using SlRec = SLAPrintObject::SliceRecord; -// auto it = std::lower_bound(m_slice_index.begin(), -// m_slice_index.end(), -// from_eq, // model start z -// [](const SlRec& sr1, const SlRec& sr2){ -// return sr1.slice_level() < sr2.slice_level(); -// }); - -// std::vector heights; heights.reserve(m_slice_index.size()); -// for(; it != m_slice_index.end(); ++it) -// heights.emplace_back(it->slice_level()); - - -//} - const std::vector &SLAPrintObject::get_model_slices() const { // assert(is_step_done(slaposObjectSlice)); diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index e86080963..3e0a0c5e3 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -122,7 +122,7 @@ private: size_t m_model_slices_idx = NONE; size_t m_support_slices_idx = NONE; - LevelID m_print_z = 0; // Top of the layer + LevelID 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 @@ -131,34 +131,54 @@ private: SliceRecord(Key key, float slicez, float height): m_print_z(key), m_slice_z(slicez), m_height(height) {} + // 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; } - SliceIterator get_slices(const SLAPrintObject& po, - SliceOrigin so) const; - + // Returns the slices for eighter the model or the supports. The return + // value is an iterator to po.get_model_slices() or po.get_support_slices + // depending on the SliceOrigin parameter. + SliceIterator get_slices(const SLAPrintObject& po, SliceOrigin so) const; + // Methods for setting the indixes into the slice vectors. 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; } - }; + // Slice index will be a plain vector sorted by the integer height levels using SliceIndex = std::vector; // Retrieve the slice index which is readable only after slaposIndexSlices // is done. const SliceIndex& get_slice_index() const; + // Search slice index for the closest slice to the given level SliceIndex::iterator search_slice_index(float slice_level); 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() SliceIndex::iterator search_slice_index(SliceRecord::Key key); SliceIndex::const_iterator search_slice_index(SliceRecord::Key key) const; public: - SliceIterator get_slices(SliceOrigin so, LevelID k) const; + // ///////////////////////////////////////////////////////////////////////// + // The following methods can be used after the model and the support slicing + // steps have been succesfully finished. + // ///////////////////////////////////////////////////////////////////////// + // Getting slices for either the model or the supports for a particular + // height ID. +// SliceIterator get_slices(SliceOrigin so, LevelID k) const; + + // Getting slices (model or supports) for a Z coordinate range. The returned + // iterators should include the slices for the given boundaries as well. SliceRange get_slices( SliceOrigin so, float from_level, @@ -171,7 +191,10 @@ public: const std::vector& get_model_slices() const; const std::vector& get_support_slices() const; + // Returns the total number of slices in the slice grid (model and supports) inline size_t get_slice_count() const { return m_slice_index.size(); } + + // One can query the Z coordinate of the slice for a given inline float get_slice_level(size_t idx) const { return m_slice_index[idx].slice_level(); } From 5e646562cd2194cb03c80f68b871a6b3f9636d52 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 21 Mar 2019 18:01:41 +0100 Subject: [PATCH 5/7] Fixes for the duplicated layer issues... --- src/libslic3r/SLAPrint.cpp | 51 ++++++++++++++++++++-------------- src/libslic3r/SLAPrint.hpp | 51 ++++++++++++++++++---------------- src/slic3r/GUI/GUI_Preview.cpp | 2 +- 3 files changed, 58 insertions(+), 46 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index bbf53ef7e..58386c0bd 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -615,12 +615,19 @@ void SLAPrint::process() using namespace sla; using ExPolygon = Slic3r::ExPolygon; + if(m_objects.empty()) return; + // 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 // shortcut to initial layer height double ilhd = m_material_config.initial_layer_height.getFloat(); auto ilh = float(ilhd); + double lhd = m_objects.front()->m_config.layer_height.getFloat(); + float lh = float(lhd); + + LevelID ilhs = ilhd / SCALING_FACTOR; + LevelID lhs = lhd / SCALING_FACTOR; const size_t objcount = m_objects.size(); const unsigned min_objstatus = 0; // where the per object operations start @@ -641,24 +648,26 @@ void SLAPrint::process() // 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 slice_model = [this, ilhs, lhs, ilh, lh](SLAPrintObject& po) { TriangleMesh mesh = po.transformed_mesh(); // We need to prepare the slice index... auto&& bb3d = mesh.bounding_box(); - float minZ = float(bb3d.min(Z)) - float(po.get_elevation()); - float maxZ = float(bb3d.max(Z)); - auto flh = float(po.m_config.layer_height.getFloat()); + double minZ = bb3d.min(Z) - po.get_elevation(); + double maxZ = bb3d.max(Z); + + LevelID minZs = minZ / SCALING_FACTOR; + LevelID maxZs = maxZ / SCALING_FACTOR; auto slh = [](float h) { return LevelID( double(h) / SCALING_FACTOR); }; po.m_slice_index.clear(); - po.m_slice_index.reserve(size_t(maxZ - (minZ + ilh) / flh) + 1); - po.m_slice_index.emplace_back(slh(minZ + ilh), minZ + ilh / 2.f, ilh); + po.m_slice_index.reserve(size_t(maxZs - (minZs + ilhs) / lhs) + 1); + po.m_slice_index.emplace_back(minZs + ilhs, minZ + ilh / 2.f, ilh); - for(float h = minZ + ilh + flh; h <= maxZ; h += flh) { - po.m_slice_index.emplace_back(slh(h), h - flh / 2.f, flh); + for(LevelID h = minZs + ilhs + lhs; h <= maxZs; h += lhs) { + po.m_slice_index.emplace_back(h, h*SCALING_FACTOR - lh / 2.f, lh); } auto slindex_it = po.search_slice_index(float(bb3d.min(Z))); @@ -1337,7 +1346,7 @@ void SLAPrint::fill_statistics() for (SLAPrintObject * po : m_objects) { - const SLAPrintObject::SliceRecord *record = nullptr; + const SLAPrintObject::_SliceRecord *record = nullptr; { const SLAPrintObject::SliceIndex& index = po->get_slice_index(); auto it = po->search_slice_index(layer.slice_level() - float(EPSILON)); @@ -1562,10 +1571,10 @@ const std::vector& SLAPrintObject::get_support_points() const SLAPrintObject::SliceIndex::iterator SLAPrintObject::search_slice_index(float slice_level) { - SliceRecord query(0, slice_level, 0); + _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) + [](const _SliceRecord& r1, const _SliceRecord& r2) { return r1.slice_level() < r2.slice_level(); }); @@ -1576,10 +1585,10 @@ SLAPrintObject::search_slice_index(float slice_level) SLAPrintObject::SliceIndex::const_iterator SLAPrintObject::search_slice_index(float slice_level) const { - SliceRecord query(0, slice_level, 0); + _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) + [](const _SliceRecord& r1, const _SliceRecord& r2) { return r1.slice_level() < r2.slice_level(); }); @@ -1588,12 +1597,12 @@ SLAPrintObject::search_slice_index(float slice_level) const } SLAPrintObject::SliceIndex::iterator -SLAPrintObject::search_slice_index(SLAPrintObject::SliceRecord::Key key) +SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) { - SliceRecord query(key, 0.f, 0.f); + _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) + [](const _SliceRecord& r1, const _SliceRecord& r2) { return r1.key() < r2.key(); }); @@ -1605,12 +1614,12 @@ SLAPrintObject::search_slice_index(SLAPrintObject::SliceRecord::Key key) } SLAPrintObject::SliceIndex::const_iterator -SLAPrintObject::search_slice_index(SLAPrintObject::SliceRecord::Key key) const +SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) const { - SliceRecord query(key, 0.f, 0.f); + _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) + [](const _SliceRecord& r1, const _SliceRecord& r2) { return r1.key() < r2.key(); }); @@ -1645,7 +1654,7 @@ const std::vector &SLAPrintObject::get_support_slices() const return m_supportdata->support_slices; } -const std::vector& +const std::vector& SLAPrintObject::get_slice_index() const { // assert(is_step_done(slaposIndexSlices)); @@ -1769,7 +1778,7 @@ std::string SLAPrintStatistics::finalize_output_path(const std::string &path_in) return final_path; } -SliceIterator SLAPrintObject::SliceRecord::get_slices(const SLAPrintObject &po, +SliceIterator SLAPrintObject::_SliceRecord::get_slices(const SLAPrintObject &po, SliceOrigin so) const { diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 3e0a0c5e3..b33bfdeb0 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -107,30 +107,21 @@ public: // This method returns the support points of this SLAPrintObject. const std::vector& get_support_points() const; -private: - - // An index record referencing the slices - // (get_model_slices(), get_support_slices()) where the keys are the height - // levels of the model in scaled-clipper coordinates. The levels correspond - // to the z coordinate of the object coordinate system. class SliceRecord { public: using Key = LevelID; private: - static const size_t NONE = size_t(-1); // this will be the max limit of size_t - size_t m_model_slices_idx = NONE; - size_t m_support_slices_idx = NONE; - LevelID 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 - public: - + 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; } @@ -139,8 +130,25 @@ private: // Returns the current layer height inline float layer_height() const { return m_height; } + }; - // Returns the slices for eighter the model or the supports. The return +private: + + // An index record referencing the slices + // (get_model_slices(), get_support_slices()) where the keys are the height + // levels of the model in scaled-clipper coordinates. The levels correspond + // to the z coordinate of the object coordinate system. + class _SliceRecord: public SliceRecord { + private: + static const size_t NONE = size_t(-1); // this will be the max limit of size_t + size_t m_model_slices_idx = NONE; + size_t m_support_slices_idx = NONE; + + public: + _SliceRecord(Key key, float slicez, float height): + SliceRecord(key, slicez, height) {} + + // Returns the slices for either the model or the supports. The return // value is an iterator to po.get_model_slices() or po.get_support_slices // depending on the SliceOrigin parameter. SliceIterator get_slices(const SLAPrintObject& po, SliceOrigin so) const; @@ -151,7 +159,7 @@ private: }; // Slice index will be a plain vector sorted by the integer height levels - using SliceIndex = std::vector; + using SliceIndex = std::vector<_SliceRecord>; // Retrieve the slice index which is readable only after slaposIndexSlices // is done. @@ -163,8 +171,8 @@ private: // Search the slice index for a particular level in integer coordinates. // If no such layer is present, it will return m_slice_index.end() - SliceIndex::iterator search_slice_index(SliceRecord::Key key); - SliceIndex::const_iterator search_slice_index(SliceRecord::Key key) const; + SliceIndex::iterator search_slice_index(_SliceRecord::Key key); + SliceIndex::const_iterator search_slice_index(_SliceRecord::Key key) const; public: @@ -173,10 +181,6 @@ public: // steps have been succesfully finished. // ///////////////////////////////////////////////////////////////////////// - // Getting slices for either the model or the supports for a particular - // height ID. -// SliceIterator get_slices(SliceOrigin so, LevelID k) const; - // Getting slices (model or supports) for a Z coordinate range. The returned // iterators should include the slices for the given boundaries as well. SliceRange get_slices( @@ -194,9 +198,8 @@ public: // Returns the total number of slices in the slice grid (model and supports) inline size_t get_slice_count() const { return m_slice_index.size(); } - // One can query the Z coordinate of the slice for a given - inline float get_slice_level(size_t idx) const { - return m_slice_index[idx].slice_level(); + inline const SliceRecord& get_slice_record(size_t idx) const { + return m_slice_index[idx]; } protected: @@ -239,7 +242,7 @@ private: // Exact (float) height levels mapped to the slices. Each record contains // the index to the model and the support slice vectors. - std::vector m_slice_index; + std::vector<_SliceRecord> m_slice_index; std::vector m_model_height_levels; diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 148b83081..10a4a12c7 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -778,7 +778,7 @@ void Preview::load_print_as_sla() size_t cnt = obj->get_slice_count(); for (size_t i = 0; i < cnt; i++) { - zs.insert(shift_z + double(obj->get_slice_level(i))); + zs.insert(shift_z + obj->get_slice_record(i).key() * SCALING_FACTOR); } } } From d165dbb49842a6fd44193318443259dabc0b0ef6 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 22 Mar 2019 15:31:38 +0100 Subject: [PATCH 6/7] Refactoring changes to the slice index. --- src/libslic3r/MTUtils.hpp | 107 +++++++++++++++++ src/libslic3r/SLAPrint.cpp | 206 +++++++++------------------------ src/libslic3r/SLAPrint.hpp | 119 +++++++++++-------- src/slic3r/GUI/GLCanvas3D.cpp | 26 +++-- src/slic3r/GUI/GUI_Preview.cpp | 6 +- 5 files changed, 249 insertions(+), 215 deletions(-) diff --git a/src/libslic3r/MTUtils.hpp b/src/libslic3r/MTUtils.hpp index 1e0fb426a..1f6ca1a23 100644 --- a/src/libslic3r/MTUtils.hpp +++ b/src/libslic3r/MTUtils.hpp @@ -56,6 +56,113 @@ public: } }; +template +class IndexBasedIterator { + static const size_t NONE = size_t(-1); + + std::reference_wrapper 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 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(b)), to(std::forward(e)) {} + + inline size_t size() const { return end() - begin(); } + inline bool empty() const { return size() == 0; } +}; + } #endif // MTUTILS_HPP diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 58386c0bd..4d34b8e7d 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -626,8 +626,8 @@ void SLAPrint::process() double lhd = m_objects.front()->m_config.layer_height.getFloat(); float lh = float(lhd); - LevelID ilhs = ilhd / SCALING_FACTOR; - LevelID lhs = lhd / SCALING_FACTOR; + auto ilhs = LevelID(ilhd / SCALING_FACTOR); + auto lhs = LevelID(lhd / SCALING_FACTOR); const size_t objcount = m_objects.size(); const unsigned min_objstatus = 0; // where the per object operations start @@ -657,17 +657,15 @@ void SLAPrint::process() double minZ = bb3d.min(Z) - po.get_elevation(); double maxZ = bb3d.max(Z); - LevelID minZs = minZ / SCALING_FACTOR; - LevelID maxZs = maxZ / SCALING_FACTOR; - - auto slh = [](float h) { return LevelID( double(h) / SCALING_FACTOR); }; + 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, minZ + ilh / 2.f, ilh); + 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, h*SCALING_FACTOR - lh / 2.f, lh); + 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))); @@ -867,8 +865,10 @@ void SLAPrint::process() // be part of the slices) auto slice_supports = [](SLAPrintObject& po) { auto& sd = po.m_supportdata; + + if(sd) sd->support_slices.clear(); + if(sd && sd->support_tree_ptr) { - sd->support_slices.clear(); std::vector heights; heights.reserve(po.m_slice_index.size()); @@ -891,75 +891,6 @@ void SLAPrint::process() // 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) 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& 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& 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. report_status(*this, -2, "", SlicingStatus::RELOAD_SLA_PREVIEW); }; @@ -975,41 +906,16 @@ void SLAPrint::process() LevelID gndlvl = o->get_slice_index().front().key(); for(auto& slicerecord : o->get_slice_index()) { auto& lyrs = m_printer_input[slicerecord.key() - gndlvl]; - auto objslit = slicerecord.get_slices(*o, soModel); - auto supslit = slicerecord.get_slices(*o, soSupport); - if(objslit != o->get_model_slices().end()) - lyrs.emplace_back(*objslit, o->instances()); + const ExPolygons& objslices = o->get_slices_from_record(slicerecord, soModel); + const ExPolygons& supslices = o->get_slices_from_record(slicerecord, soSupport); - if(supslit != o->get_support_slices().end()) - lyrs.emplace_back(*supslit, o->instances()); + if(!objslices.empty()) + lyrs.emplace_back(objslices, o->instances()); + + if(!supslices.empty()) + lyrs.emplace_back(supslices, o->instances()); } - -// auto& po = *o; -// std::vector& oslices = po.m_model_slices; - -// // We need to adjust the min Z level of the slices to be zero -// LevelID smfirst = -// 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 -// // of the print object slices - -// for(size_t i = 0; i < oslices.size(); ++i) { -// auto& lyrs = m_printer_input[gndlvl + po.m_level_ids[i]]; -// lyrs.emplace_back(oslices[i], po.m_instances); -// } - -// if(!po.m_supportdata) continue; -// std::vector& 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); -// } } // collect all the keys @@ -1355,13 +1261,13 @@ void SLAPrint::fill_statistics() record = &(*it); } - auto modelslice_it = record->get_slices(*po, soModel); - if (modelslice_it != po->get_model_slices().end()) - append(model_polygons, get_all_polygons(*modelslice_it, po->instances())); - - auto supportslice_it = record->get_slices(*po, soSupport); - if (supportslice_it != po->get_support_slices().end()) - append(supports_polygons, get_all_polygons(*supportslice_it, po->instances())); + const ExPolygons &modelslices = po->get_slices_from_record(*record, soModel); + if (!modelslices.empty()) + append(model_polygons, get_all_polygons(modelslices, po->instances())); + + const ExPolygons &supportslices = po->get_slices_from_record(*record, soSupport); + if (!supportslices.empty()) + append(supports_polygons, get_all_polygons(supportslices, po->instances())); } model_polygons = union_(model_polygons); @@ -1561,6 +1467,7 @@ double SLAPrintObject::get_current_elevation() const namespace { // dummy empty static containers for return values in some methods const std::vector EMPTY_SLICES; const TriangleMesh EMPTY_MESH; +const ExPolygons EMPTY_SLICE; } const std::vector& SLAPrintObject::get_support_points() const @@ -1597,7 +1504,8 @@ SLAPrintObject::search_slice_index(float slice_level) const } SLAPrintObject::SliceIndex::iterator -SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) +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(), @@ -1608,13 +1516,15 @@ SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) }); // Return valid iterator only if the keys really match - if(it != m_slice_index.end() && it->key() != key) it = m_slice_index.end(); + 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) const +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(), @@ -1625,28 +1535,12 @@ SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) const }); // Return valid iterator only if the keys really match - if(it != m_slice_index.end() && it->key() != key) it = m_slice_index.end(); + if(exact && it != m_slice_index.end() && it->key() != key) + it = m_slice_index.end(); return it; } -SliceRange SLAPrintObject::get_slices(SliceOrigin so, - float from_level, - float to_level) const -{ - auto it_from = search_slice_index(from_level); - auto it_to = search_slice_index(to_level); - - SliceRange ret; - - auto endit = so == soModel? get_model_slices().end() : get_support_slices().end(); - - ret.from = it_from == m_slice_index.end() ? endit : it_from->get_slices(*this, so); - ret.to = it_to == m_slice_index.end() ? endit : it_to->get_slices(*this, so); - - return ret; -} - const std::vector &SLAPrintObject::get_support_slices() const { // assert(is_step_done(slaposSliceSupports)); @@ -1654,6 +1548,28 @@ const std::vector &SLAPrintObject::get_support_slices() const return m_supportdata->support_slices; } +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& 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::get_slice_index() const { @@ -1778,18 +1694,4 @@ std::string SLAPrintStatistics::finalize_output_path(const std::string &path_in) return final_path; } -SliceIterator SLAPrintObject::_SliceRecord::get_slices(const SLAPrintObject &po, - SliceOrigin so) const -{ - - const std::vector& v = so == soModel? po.get_model_slices() : - po.get_support_slices(); - - size_t idx = so == soModel ? m_model_slices_idx : m_support_slices_idx; - - using DiffT = std::vector::const_iterator::difference_type; - - return idx == NONE? v.end() : v.begin() + DiffT(idx); -} - } // namespace Slic3r diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index b33bfdeb0..ff715fb5e 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -6,6 +6,7 @@ #include "PrintExport.hpp" #include "Point.hpp" #include "MTUtils.hpp" +#include namespace Slic3r { @@ -35,23 +36,8 @@ using _SLAPrintObjectBase = // the printer (rasterizer) in the SLAPrint class. using LevelID = long long; -template struct Range { - It from, to; - It begin() const { return from; } - It end() const { return to; } - using Type = It; - - Range() = default; - explicit Range(It &&b, It &&e): - from(std::forward(b)), to(std::forward(e)) {} -}; - enum SliceOrigin { soSupport, soModel }; -using SliceStore = std::vector; -using SliceIterator = SliceStore::const_iterator; -using SliceRange = Range; - class SLAPrintObject : public _SLAPrintObjectBase { private: // Prevents erroneous use by other classes. @@ -107,12 +93,14 @@ public: // This method returns the support points of this SLAPrintObject. const std::vector& 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: - LevelID m_print_z = 0; // Top of the layer + 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 @@ -139,8 +127,9 @@ private: // levels of the model in scaled-clipper coordinates. The levels correspond // to the z coordinate of the object coordinate system. class _SliceRecord: public SliceRecord { - private: + 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; @@ -148,14 +137,12 @@ private: _SliceRecord(Key key, float slicez, float height): SliceRecord(key, slicez, height) {} - // Returns the slices for either the model or the supports. The return - // value is an iterator to po.get_model_slices() or po.get_support_slices - // depending on the SliceOrigin parameter. - SliceIterator get_slices(const SLAPrintObject& po, SliceOrigin so) const; - - // Methods for setting the indixes into the slice vectors. + // Methods for setting the indices into the slice vectors. 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; } }; // Slice index will be a plain vector sorted by the integer height levels @@ -171,37 +158,78 @@ private: // Search the slice index for a particular level in integer coordinates. // If no such layer is present, it will return m_slice_index.end() - SliceIndex::iterator search_slice_index(_SliceRecord::Key key); - SliceIndex::const_iterator search_slice_index(_SliceRecord::Key key) const; + // 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& get_model_slices() const; + const std::vector& get_support_slices() const; public: - // ///////////////////////////////////////////////////////////////////////// - // The following methods can be used after the model and the support slicing - // steps have been succesfully finished. - // ///////////////////////////////////////////////////////////////////////// - - // Getting slices (model or supports) for a Z coordinate range. The returned - // iterators should include the slices for the given boundaries as well. - SliceRange get_slices( - SliceOrigin so, - float from_level, - float to_level = std::numeric_limits::infinity()) const; + // Should work as a polymorphic bidirectional iterator to the slice records + using SliceRecordConstIterator = + IndexBasedIterator; + // ///////////////////////////////////////////////////////////////////////// + // // 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& get_model_slices() const; - const std::vector& get_support_slices() const; + // + // ///////////////////////////////////////////////////////////////////////// - // Returns the total number of slices in the slice grid (model and supports) - inline size_t get_slice_count() const { return m_slice_index.size(); } + // 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 Range + get_slice_records(Key from, Key to = std::numeric_limits::max()) const + { + SliceIndex::const_iterator it_from, it_to; + if(std::is_integral::value) { + it_from = search_slice_index(SliceRecord::Key(from)); + it_to = search_slice_index(SliceRecord::Key(to)); + } else if(std::is_floating_point::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 ), + }; - inline const SliceRecord& get_slice_record(size_t idx) const { - return m_slice_index[idx]; + 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 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: // to be called from SLAPrint only. friend class SLAPrint; @@ -242,7 +270,7 @@ private: // Exact (float) height levels mapped to the slices. Each record contains // the index to the model and the support slice vectors. - std::vector<_SliceRecord> m_slice_index; + std::vector<_SliceRecord> m_slice_index; std::vector m_model_height_levels; @@ -335,11 +363,6 @@ private: // Invalidate steps based on a set of parameters changed. bool invalidate_state_by_config_options(const std::vector &opt_keys); - std::vector calculate_heights(const BoundingBoxf3& bb, - float elevation, - float initial_layer_height, - float layer_height) const; - void fill_statistics(); SLAPrintConfig m_print_config; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 0f1e15b76..8acb5ad53 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -5014,26 +5014,28 @@ 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)) { // FIXME: is this all right (by Tamas)? - SliceRange obj_range = obj->get_slices(soModel, float(min_z), float(max_z)); - SliceRange sup_range = obj->get_slices(soSupport, float(min_z), float(max_z)); - auto obj_end = obj->get_model_slices().end(); - auto sup_end = obj->get_support_slices().end(); + 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); // calculate model bottom cap - if(bottom_obj_triangles.empty() && obj_range.from != obj_end) - bottom_obj_triangles = triangulate_expolygons_3d(*obj_range.from, min_z, true); + if(bottom_obj_triangles.empty() && !obj_bottom.empty()) + bottom_obj_triangles = triangulate_expolygons_3d(obj_bottom, min_z, true); // calculate support bottom cap - if(bottom_sup_triangles.empty() && sup_range.from != sup_end) - bottom_sup_triangles = triangulate_expolygons_3d(*sup_range.from, min_z, true); + if(bottom_sup_triangles.empty() && !sup_bottom.empty()) + bottom_sup_triangles = triangulate_expolygons_3d(sup_bottom, min_z, true); // calculate model top cap - if(top_obj_triangles.empty() && obj_range.to != obj_end) - top_obj_triangles = triangulate_expolygons_3d(*obj_range.to, max_z, false); + if(top_obj_triangles.empty() && !obj_top.empty()) + top_obj_triangles = triangulate_expolygons_3d(obj_top, max_z, false); // calculate support top cap - if(top_sup_triangles.empty() && sup_range.to != sup_end) - top_sup_triangles = triangulate_expolygons_3d(*sup_range.to, max_z, false); + if(top_sup_triangles.empty() && !sup_top.empty()) + top_sup_triangles = triangulate_expolygons_3d(sup_top, max_z, false); // const std::vector& model_slices = obj->get_model_slices(); // const std::vector& support_slices = obj->get_support_slices(); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 10a4a12c7..5edca6c96 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -775,10 +775,10 @@ void Preview::load_print_as_sla() double shift_z = obj->get_current_elevation(); if (obj->is_step_done(slaposIndexSlices)) { - size_t cnt = obj->get_slice_count(); - for (size_t i = 0; i < cnt; i++) + auto slicerecords = obj->get_slice_records(); + for (auto& rec : slicerecords) { - zs.insert(shift_z + obj->get_slice_record(i).key() * SCALING_FACTOR); + zs.insert(shift_z + /*rec.slice_level()*/ rec.key() * SCALING_FACTOR); } } } From 8e18605bd720f895cc6f0088b1dd27c49dd4fb69 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 22 Mar 2019 15:48:20 +0100 Subject: [PATCH 7/7] Fix for incorrect model slices after elevation has changed. --- src/libslic3r/SLAPrint.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 4d34b8e7d..79834908f 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -1363,11 +1363,15 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector