From 19a96336ffad44ad3c38383e0d7c93047c4258ad Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 20 Mar 2019 18:03:11 +0100 Subject: [PATCH 01/14] 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 83fa61fdd0..62ddba84b7 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 c06e2fc777..4d5f1d0daa 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 02/14] 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 62ddba84b7..938f148a30 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 4d5f1d0daa..6204628757 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 1c09096a8d..7bd63aa3c9 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 be3fad9ece..f691850b42 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 03/14] 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 938f148a30..e12dc7f233 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 6204628757..e86080963a 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 7bd63aa3c9..90656c93b7 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 f691850b42..4776733420 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 04/14] 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 df9990822d..34dd80cee0 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 74d7da9cad..66677e4d7a 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 e12dc7f233..bbf53ef7e8 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 e86080963a..3e0a0c5e3a 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 05/14] 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 bbf53ef7e8..58386c0bdb 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 3e0a0c5e3a..b33bfdeb08 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 148b830811..10a4a12c7e 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 06/14] 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 1e0fb426aa..1f6ca1a237 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 58386c0bdb..4d34b8e7d4 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 b33bfdeb08..ff715fb5ed 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 0f1e15b76c..8acb5ad537 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 10a4a12c7e..5edca6c969 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 ae9356904402ada309f9a2f82e2a53084f379528 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 22 Mar 2019 15:45:51 +0100 Subject: [PATCH 07/14] Call Config Wizard from the Printer combo box at both the plater and the parameter tab. --- src/slic3r/GUI/Plater.cpp | 9 ++++--- src/slic3r/GUI/Plater.hpp | 8 ++++-- src/slic3r/GUI/Preset.cpp | 47 +++++++++++++++++++++++++++++++-- src/slic3r/GUI/Preset.hpp | 5 ++++ src/slic3r/GUI/PresetBundle.cpp | 1 + src/slic3r/GUI/Tab.cpp | 3 +++ 6 files changed, 66 insertions(+), 7 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 906a5009ae..a2ab8c3f1c 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -57,6 +57,7 @@ #include "BackgroundSlicingProcess.hpp" #include "ProgressStatusBar.hpp" #include "PrintHostDialogs.hpp" +#include "ConfigWizard.hpp" #include "../Utils/ASCIIFolding.hpp" #include "../Utils/PrintHost.hpp" #include "../Utils/FixModelByWin10.hpp" @@ -233,9 +234,11 @@ wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 * auto selected_item = this->GetSelection(); auto marker = reinterpret_cast(this->GetClientData(selected_item)); - if (marker == LABEL_ITEM_MARKER) { + if (marker == LABEL_ITEM_MARKER || marker == LABEL_ITEM_CONFIG_WIZARD) { this->SetSelection(this->last_selected); evt.StopPropagation(); + if (marker == LABEL_ITEM_CONFIG_WIZARD) + wxTheApp->CallAfter([]() { Slic3r::GUI::config_wizard(Slic3r::GUI::ConfigWizard::RR_USER); }); } else if ( this->last_selected != selected_item || wxGetApp().get_tab(this->preset_type)->get_presets()->current_is_dirty() ) { this->last_selected = selected_item; @@ -317,9 +320,9 @@ PresetComboBox::~PresetComboBox() } -void PresetComboBox::set_label_marker(int item) +void PresetComboBox::set_label_marker(int item, LabelItemType label_item_type) { - this->SetClientData(item, (void*)LABEL_ITEM_MARKER); + this->SetClientData(item, (void*)label_item_type); } void PresetComboBox::check_selection() diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index f3e195ad09..f830edce3f 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -48,14 +48,18 @@ public: wxButton* edit_btn { nullptr }; - void set_label_marker(int item); + enum LabelItemType { + LABEL_ITEM_MARKER = 0x4d, + LABEL_ITEM_CONFIG_WIZARD = 0x4e + }; + + void set_label_marker(int item, LabelItemType label_item_type = LABEL_ITEM_MARKER); void set_extruder_idx(const int extr_idx) { extruder_idx = extr_idx; } int get_extruder_idx() const { return extruder_idx; } void check_selection(); private: typedef std::size_t Marker; - enum { LABEL_ITEM_MARKER = 0x4d }; Preset::Type preset_type; int last_selected; diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index e63ae32f7f..6ed711c95b 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -519,6 +519,7 @@ PresetCollection::PresetCollection(Preset::Type type, const std::vectorLoadFile(wxString::FromUTF8(Slic3r::var(file_name).c_str()), wxBITMAP_TYPE_PNG); } +bool PresetCollection::load_bitmap_add(const std::string &file_name) +{ + return m_bitmap_add->LoadFile(wxString::FromUTF8(Slic3r::var(file_name).c_str()), wxBITMAP_TYPE_PNG); +} + const Preset* PresetCollection::get_selected_preset_parent() const { const std::string &inherits = this->get_edited_preset().inherits(); @@ -903,7 +911,7 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) wxString selected = ""; if (!this->m_presets.front().is_visible) ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap)); - for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++i) { + for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++ i) { const Preset &preset = this->m_presets[i]; if (! preset.is_visible || (! preset.is_compatible && i != m_idx_selected)) continue; @@ -953,6 +961,30 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) selected_preset_item = ui->GetCount() - 1; } } + if (m_type == Preset::TYPE_PRINTER) { + std::string bitmap_key = ""; + // If the filament preset is not compatible and there is a "red flag" icon loaded, show it left + // to the filament color image. + if (wide_icons) + bitmap_key += "wide,"; + bitmap_key += "add_printer"; + wxBitmap *bmp = m_bitmap_cache->find(bitmap_key); + if (bmp == nullptr) { + // Create the bitmap with color bars. + std::vector bmps; + if (wide_icons) + // Paint a red flag for incompatible presets. + bmps.emplace_back(m_bitmap_cache->mkclear(16, 16)); + // Paint the color bars. + bmps.emplace_back(m_bitmap_cache->mkclear(4, 16)); + bmps.emplace_back(*m_bitmap_main_frame); + // Paint a lock at the system presets. + bmps.emplace_back(m_bitmap_cache->mkclear(6, 16)); + bmps.emplace_back(m_bitmap_add ? *m_bitmap_add : wxNullBitmap); + bmp = m_bitmap_cache->insert(bitmap_key, bmps); + } + ui->set_label_marker(ui->Append("------- " + _(L("Add a new printer")) + " -------", *bmp), GUI::PresetComboBox::LABEL_ITEM_CONFIG_WIZARD); + } ui->SetSelection(selected_preset_item); ui->SetToolTip(ui->GetString(selected_preset_item)); @@ -1001,7 +1033,7 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati if (i == m_idx_selected) selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); } - if (i + 1 == m_num_default_presets) + if (i + 1 == m_num_default_presets) ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap); } if (!nonsys_presets.empty()) @@ -1013,6 +1045,17 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati selected_preset_item = ui->GetCount() - 1; } } + if (m_type == Preset::TYPE_PRINTER) { + wxBitmap *bmp = m_bitmap_cache->find("add_printer_tab"); + if (bmp == nullptr) { + // Create the bitmap with color bars. + std::vector bmps; + bmps.emplace_back(*m_bitmap_main_frame); + bmps.emplace_back(m_bitmap_add ? *m_bitmap_add : wxNullBitmap); + bmp = m_bitmap_cache->insert("add_printer_tab", bmps); + } + ui->Append("------- " + _(L("Add a new printer")) + " -------", *bmp); + } ui->SetSelection(selected_preset_item); ui->SetToolTip(ui->GetString(selected_preset_item)); ui->Thaw(); diff --git a/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp index c84c37029e..cc0a515889 100644 --- a/src/slic3r/GUI/Preset.hpp +++ b/src/slic3r/GUI/Preset.hpp @@ -277,6 +277,9 @@ public: // Load default bitmap to be placed at the wxBitmapComboBox of a MainFrame. bool load_bitmap_default(const std::string &file_name); + // Load "add new printer" bitmap to be placed at the wxBitmapComboBox of a MainFrame. + bool load_bitmap_add(const std::string &file_name); + // Compatible & incompatible marks, to be placed at the wxBitmapComboBox items. void set_bitmap_compatible (const wxBitmap *bmp) { m_bitmap_compatible = bmp; } void set_bitmap_incompatible(const wxBitmap *bmp) { m_bitmap_incompatible = bmp; } @@ -467,6 +470,8 @@ private: // Marks placed at the wxBitmapComboBox of a MainFrame. // These bitmaps are owned by PresetCollection. wxBitmap *m_bitmap_main_frame; + // "Add printer profile" icon, owned by PresetCollection. + wxBitmap *m_bitmap_add; // Path to the directory to store the config files into. std::string m_dir_path; diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index b8c9fedacc..b7e26a66ce 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -107,6 +107,7 @@ PresetBundle::PresetBundle() : this->filaments .load_bitmap_default("spool.png"); this->sla_materials.load_bitmap_default("package_green.png"); this->printers .load_bitmap_default("printer_empty.png"); + this->printers .load_bitmap_add("add.png"); this->load_compatible_bitmaps(); // Re-activate the default presets, so their "edited" preset copies will be updated with the additional configuration values above. diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index d38e96ca28..e5044935ec 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -29,6 +29,7 @@ #include "GUI_App.hpp" #include "GUI_ObjectList.hpp" +#include "ConfigWizard.hpp" namespace Slic3r { namespace GUI { @@ -252,6 +253,8 @@ void Tab::create_preset_tab() /*selected_string == "------- System presets -------" || selected_string == "------- User presets -------"*/) { m_presets_choice->SetSelection(m_selected_preset_item); + if (selected_string == "------- " + _(L("Add a new printer")) + " -------") + wxTheApp->CallAfter([]() { Slic3r::GUI::config_wizard(Slic3r::GUI::ConfigWizard::RR_USER); }); return; } m_selected_preset_item = selected_item; From 8e18605bd720f895cc6f0088b1dd27c49dd4fb69 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 22 Mar 2019 15:48:20 +0100 Subject: [PATCH 08/14] 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 4d34b8e7d4..79834908f2 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 Date: Fri, 22 Mar 2019 17:07:12 +0100 Subject: [PATCH 09/14] Refactored the -------- xxxx ---------- menu items to use a generic code to generate these separators. Now using the connected dashes (unicode emdash characters) on OSX and Windows. --- src/slic3r/GUI/Preset.cpp | 21 +++++++++++++-------- src/slic3r/GUI/Preset.hpp | 9 +++++++++ src/slic3r/GUI/PresetBundle.cpp | 8 ++++---- src/slic3r/GUI/Tab.cpp | 4 ++-- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 6ed711c95b..3da4c18716 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -910,7 +910,7 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) std::map nonsys_presets; wxString selected = ""; if (!this->m_presets.front().is_visible) - ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap)); + ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap)); for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++ i) { const Preset &preset = this->m_presets[i]; if (! preset.is_visible || (! preset.is_compatible && i != m_idx_selected)) @@ -950,11 +950,11 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); } if (i + 1 == m_num_default_presets) - ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap)); + ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap)); } if (!nonsys_presets.empty()) { - ui->set_label_marker(ui->Append("------- " + _(L("User presets")) + " -------", wxNullBitmap)); + ui->set_label_marker(ui->Append(PresetCollection::separator(L("User presets")), wxNullBitmap)); for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { ui->Append(it->first, *it->second); if (it->first == selected) @@ -983,7 +983,7 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) bmps.emplace_back(m_bitmap_add ? *m_bitmap_add : wxNullBitmap); bmp = m_bitmap_cache->insert(bitmap_key, bmps); } - ui->set_label_marker(ui->Append("------- " + _(L("Add a new printer")) + " -------", *bmp), GUI::PresetComboBox::LABEL_ITEM_CONFIG_WIZARD); + ui->set_label_marker(ui->Append(PresetCollection::separator(L("Add a new printer")), *bmp), GUI::PresetComboBox::LABEL_ITEM_CONFIG_WIZARD); } ui->SetSelection(selected_preset_item); @@ -1002,7 +1002,7 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati std::map nonsys_presets; wxString selected = ""; if (!this->m_presets.front().is_visible) - ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap); + ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap); for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++i) { const Preset &preset = this->m_presets[i]; if (! preset.is_visible || (! show_incompatible && ! preset.is_compatible && i != m_idx_selected)) @@ -1034,11 +1034,11 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); } if (i + 1 == m_num_default_presets) - ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap); + ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap); } if (!nonsys_presets.empty()) { - ui->Append("------- " + _(L("User presets")) + " -------", wxNullBitmap); + ui->Append(PresetCollection::separator(L("User presets")), wxNullBitmap); for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { ui->Append(it->first, *it->second); if (it->first == selected) @@ -1054,7 +1054,7 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati bmps.emplace_back(m_bitmap_add ? *m_bitmap_add : wxNullBitmap); bmp = m_bitmap_cache->insert("add_printer_tab", bmps); } - ui->Append("------- " + _(L("Add a new printer")) + " -------", *bmp); + ui->Append(PresetCollection::separator("Add a new printer"), *bmp); } ui->SetSelection(selected_preset_item); ui->SetToolTip(ui->GetString(selected_preset_item)); @@ -1284,6 +1284,11 @@ std::string PresetCollection::path_from_name(const std::string &new_name) const return (boost::filesystem::path(m_dir_path) / file_name).make_preferred().string(); } +wxString PresetCollection::separator(const std::string &label) +{ + return wxString::FromUTF8(PresetCollection::separator_head()) + _(label) + wxString::FromUTF8(PresetCollection::separator_tail()); +} + const Preset& PrinterPresetCollection::default_preset_for(const DynamicPrintConfig &config) const { const ConfigOptionEnumGeneric *opt_printer_technology = config.opt("printer_technology"); diff --git a/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp index cc0a515889..ee795f2b9b 100644 --- a/src/slic3r/GUI/Preset.hpp +++ b/src/slic3r/GUI/Preset.hpp @@ -410,6 +410,15 @@ public: // Generate a file path from a profile name. Add the ".ini" suffix if it is missing. std::string path_from_name(const std::string &new_name) const; +#ifdef __linux__ + static const char* separator_head() { return "------- "; } + static const char* separator_tail() { return " -------"; } +#else /* __linux__ */ + static const char* separator_head() { return "————— "; } + static const char* separator_tail() { return " —————"; } +#endif /* __linux__ */ + static wxString separator(const std::string &label); + protected: // Select a preset, if it exists. If it does not exist, select an invalid (-1) index. // This is a temporary state, which shall be fixed immediately by the following step. diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index b7e26a66ce..9f42613726 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -1406,7 +1406,7 @@ void PresetBundle::export_configbundle(const std::string &path, bool export_syst // an optional "(modified)" suffix will be removed from the filament name. void PresetBundle::set_filament_preset(size_t idx, const std::string &name) { - if (name.find_first_of("-------") == 0) + if (name.find_first_of(PresetCollection::separator_head()) == 0) return; if (idx >= filament_presets.size()) @@ -1462,7 +1462,7 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::Pr std::map nonsys_presets; wxString selected_str = ""; if (!this->filaments().front().is_visible) - ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap)); + ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap)); for (int i = this->filaments().front().is_visible ? 0 : 1; i < int(this->filaments().size()); ++i) { const Preset &preset = this->filaments.preset(i); bool selected = this->filament_presets[idx_extruder] == preset.name; @@ -1515,12 +1515,12 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::Pr selected_str = wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()); } if (preset.is_default) - ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap)); + ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap)); } if (!nonsys_presets.empty()) { - ui->set_label_marker(ui->Append("------- " + _(L("User presets")) + " -------", wxNullBitmap)); + ui->set_label_marker(ui->Append(PresetCollection::separator(L("User presets")), wxNullBitmap)); for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { ui->Append(it->first, *it->second); if (it->first == selected_str) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index e5044935ec..48d9ece478 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -249,11 +249,11 @@ void Tab::create_preset_tab() return; if (selected_item >= 0) { std::string selected_string = m_presets_choice->GetString(selected_item).ToUTF8().data(); - if (selected_string.find("-------") == 0 + if (selected_string.find(PresetCollection::separator_head()) == 0 /*selected_string == "------- System presets -------" || selected_string == "------- User presets -------"*/) { m_presets_choice->SetSelection(m_selected_preset_item); - if (selected_string == "------- " + _(L("Add a new printer")) + " -------") + if (wxString::FromUTF8(selected_string.c_str()) == PresetCollection::separator(L("Add a new printer"))) wxTheApp->CallAfter([]() { Slic3r::GUI::config_wizard(Slic3r::GUI::ConfigWizard::RR_USER); }); return; } From 2fe27a29e0eb9420f14a2cad0e6cb42276be27d4 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 22 Mar 2019 21:26:58 +0100 Subject: [PATCH 10/14] Fixed the SLA layer preview. --- src/libslic3r/SLAPrint.hpp | 5 ++ src/slic3r/GUI/GLCanvas3D.cpp | 91 ++++++++++++---------------------- src/slic3r/GUI/GUI_Preview.cpp | 18 +++---- 3 files changed, 44 insertions(+), 70 deletions(-) diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index ff715fb5ed..fbe2821b21 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -350,6 +350,11 @@ public: } const PrintObjects& objects() const { return m_objects; } + const SLAPrintConfig& print_config() const { return m_print_config; } + const SLAPrinterConfig& printer_config() const { return m_printer_config; } + const SLAMaterialConfig& material_config() const { return m_material_config; } + + std::string output_filename() const override; const SLAPrintStatistics& print_statistics() const { return m_print_statistics; } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 0018ae1cc4..8be187dece 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4971,24 +4971,20 @@ void GLCanvas3D::_render_sla_slices() const { const SLAPrintObject* obj = print_objects[i]; - double shift_z = obj->get_current_elevation(); - double min_z = clip_min_z - shift_z; - double max_z = clip_max_z - shift_z; - SlaCap::ObjectIdToTrianglesMap::iterator it_caps_bottom = m_sla_caps[0].triangles.find(i); SlaCap::ObjectIdToTrianglesMap::iterator it_caps_top = m_sla_caps[1].triangles.find(i); { if (it_caps_bottom == m_sla_caps[0].triangles.end()) it_caps_bottom = m_sla_caps[0].triangles.emplace(i, SlaCap::Triangles()).first; - if (! m_sla_caps[0].matches(min_z)) { - m_sla_caps[0].z = min_z; + if (! m_sla_caps[0].matches(clip_min_z)) { + m_sla_caps[0].z = clip_min_z; it_caps_bottom->second.object.clear(); it_caps_bottom->second.supports.clear(); } if (it_caps_top == m_sla_caps[1].triangles.end()) it_caps_top = m_sla_caps[1].triangles.emplace(i, SlaCap::Triangles()).first; - if (! m_sla_caps[1].matches(max_z)) { - m_sla_caps[1].z = max_z; + if (! m_sla_caps[1].matches(clip_max_z)) { + m_sla_caps[1].z = clip_max_z; it_caps_top->second.object.clear(); it_caps_top->second.supports.clear(); } @@ -5008,61 +5004,40 @@ void GLCanvas3D::_render_sla_slices() const std::vector instance_transforms; for (const SLAPrintObject::Instance& inst : instances) { - instance_transforms.push_back({ to_3d(unscale(inst.shift), shift_z), Geometry::rad2deg(inst.rotation) }); + instance_transforms.push_back({ to_3d(unscale(inst.shift), 0.), Geometry::rad2deg(inst.rotation) }); } 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)? - 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); + double initial_layer_height = print->material_config().initial_layer_height.value; + LevelID key_zero = obj->get_slice_records().begin()->key(); + LevelID key_low = LevelID((clip_min_z - initial_layer_height) / SCALING_FACTOR) + key_zero; + LevelID key_high = LevelID((clip_max_z - initial_layer_height) / SCALING_FACTOR) + key_zero; + auto slice_range = obj->get_slice_records(key_low - LevelID(SCALED_EPSILON), key_high - LevelID(SCALED_EPSILON)); + auto it_low = slice_range.begin(); + auto it_high = std::prev(slice_range.end()); + + if (! it_low.is_end() && it_low->key() < key_low + LevelID(SCALED_EPSILON)) { + const ExPolygons& obj_bottom = obj->get_slices_from_record(it_low, soModel); + const ExPolygons& sup_bottom = obj->get_slices_from_record(it_low, soSupport); + // calculate model bottom cap + if (bottom_obj_triangles.empty() && !obj_bottom.empty()) + bottom_obj_triangles = triangulate_expolygons_3d(obj_bottom, clip_min_z, true); + // calculate support bottom cap + if (bottom_sup_triangles.empty() && !sup_bottom.empty()) + bottom_sup_triangles = triangulate_expolygons_3d(sup_bottom, clip_min_z, true); + } - // calculate model bottom cap - 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_bottom.empty()) - bottom_sup_triangles = triangulate_expolygons_3d(sup_bottom, min_z, true); - - // calculate model top cap - 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_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(); - -// 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 (! it_high.is_end() && it_high->key() < key_high + LevelID(SCALED_EPSILON)) { + const ExPolygons& obj_top = obj->get_slices_from_record(it_high, soModel); + const ExPolygons& sup_top = obj->get_slices_from_record(it_high, soSupport); + // calculate model top cap + if (top_obj_triangles.empty() && !obj_top.empty()) + top_obj_triangles = triangulate_expolygons_3d(obj_top, clip_max_z, false); + // calculate support top cap + if (top_sup_triangles.empty() && !sup_top.empty()) + top_sup_triangles = triangulate_expolygons_3d(sup_top, clip_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 5edca6c969..2361ff6d39 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -769,19 +769,17 @@ void Preview::load_print_as_sla() unsigned int n_layers = 0; const SLAPrint* print = m_process->sla_print(); - std::set zs; + std::vector zs; + double initial_layer_height = print->material_config().initial_layer_height.value; for (const SLAPrintObject* obj : print->objects()) - { - double shift_z = obj->get_current_elevation(); if (obj->is_step_done(slaposIndexSlices)) { auto slicerecords = obj->get_slice_records(); + auto low_coord = slicerecords.begin()->key(); for (auto& rec : slicerecords) - { - zs.insert(shift_z + /*rec.slice_level()*/ rec.key() * SCALING_FACTOR); - } + zs.emplace_back(initial_layer_height + (rec.key() - low_coord) * SCALING_FACTOR); } - } + sort_remove_duplicates(zs); n_layers = (unsigned int)zs.size(); if (n_layers == 0) @@ -796,11 +794,7 @@ void Preview::load_print_as_sla() show_hide_ui_elements("none"); if (n_layers > 0) - { - std::vector layer_zs; - std::copy(zs.begin(), zs.end(), std::back_inserter(layer_zs)); - update_sliders(layer_zs); - } + update_sliders(zs); m_loaded = true; } From b2ef3ba291e3df265a52e8e69e3b99b10178aa75 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 22 Mar 2019 23:00:23 +0100 Subject: [PATCH 11/14] Fixed the options override box at the side bar. --- src/slic3r/GUI/GUI_ObjectSettings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectSettings.cpp b/src/slic3r/GUI/GUI_ObjectSettings.cpp index 3781cbf450..db9af7cce3 100644 --- a/src/slic3r/GUI/GUI_ObjectSettings.cpp +++ b/src/slic3r/GUI/GUI_ObjectSettings.cpp @@ -40,7 +40,7 @@ void OG_Settings::Hide() void OG_Settings::UpdateAndShow(const bool show) { Show(show); -// m_parent->Layout(); +// m_parent->Layout(); } wxSizer* OG_Settings::get_sizer() @@ -119,7 +119,7 @@ void ObjectSettings::update_settings_list() if (cat.second.size() == 1 && cat.second[0] == "extruder") continue; - auto optgroup = std::make_shared(m_parent, cat.first, config, false, extra_column); + auto optgroup = std::make_shared(m_og->ctrl_parent(), cat.first, config, false, extra_column); optgroup->label_width = 15 * wxGetApp().em_unit();//150; optgroup->sidetext_width = 7 * wxGetApp().em_unit();//70; From c623cbc4d72bbd5e05c27946292139fd2576b7fc Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 22 Mar 2019 23:10:11 +0100 Subject: [PATCH 12/14] Fix of Perl bindings --- src/slic3r/GUI/Preset.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp index ee795f2b9b..ac1171e183 100644 --- a/src/slic3r/GUI/Preset.hpp +++ b/src/slic3r/GUI/Preset.hpp @@ -11,9 +11,10 @@ #include "slic3r/Utils/Semver.hpp" class wxBitmap; -class wxChoice; class wxBitmapComboBox; +class wxChoice; class wxItemContainer; +class wxString; namespace Slic3r { From 4f585f11575d49dd086bc65badd4b3ebe2f10955 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sat, 23 Mar 2019 08:23:22 +0100 Subject: [PATCH 13/14] Improved rendering when deleting an option from object's overrides. Replaced the single column icon with an empty icon. Will it break something? The single column added an ugly spacer in front of non-editable combo boxes. --- src/slic3r/GUI/Field.cpp | 5 ++++- src/slic3r/GUI/GUI_ObjectSettings.cpp | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 026b62ab59..9cd933160e 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -540,7 +540,10 @@ void Choice::BUILD() { else{ for (auto el : m_opt.enum_labels.empty() ? m_opt.enum_values : m_opt.enum_labels) { const wxString& str = _(el);//m_opt_id == "support" ? _(el) : el; - temp->Append(str, create_scaled_bitmap("empty_icon.png")); + //FIXME Vojtech: Why is the single column empty icon necessary? It is a workaround of some kind, but what for? + // Please document such workarounds by comments! + // temp->Append(str, create_scaled_bitmap("empty_icon.png")); + temp->Append(str, wxNullBitmap); } set_selection(); } diff --git a/src/slic3r/GUI/GUI_ObjectSettings.cpp b/src/slic3r/GUI/GUI_ObjectSettings.cpp index db9af7cce3..dbfdb8e6c5 100644 --- a/src/slic3r/GUI/GUI_ObjectSettings.cpp +++ b/src/slic3r/GUI/GUI_ObjectSettings.cpp @@ -10,6 +10,8 @@ #include "I18N.hpp" +#include + namespace Slic3r { namespace GUI @@ -84,6 +86,7 @@ void ObjectSettings::update_settings_list() btn->Bind(wxEVT_BUTTON, [opt_key, config, this](wxEvent &event) { config->erase(opt_key); wxTheApp->CallAfter([this]() { + wxWindowUpdateLocker noUpdates(m_parent); update_settings_list(); m_parent->Layout(); }); From 9652e8193a48d53441c2210a6f2d988b3ba811e1 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sat, 23 Mar 2019 10:04:44 +0100 Subject: [PATCH 14/14] Fixed caching of profile selections at the plater. --- src/slic3r/GUI/Plater.cpp | 6 +----- src/slic3r/GUI/Preset.cpp | 1 + src/slic3r/GUI/PresetBundle.cpp | 1 + 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index a2ab8c3f1c..f9c598ce39 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -327,8 +327,7 @@ void PresetComboBox::set_label_marker(int item, LabelItemType label_item_type) void PresetComboBox::check_selection() { - if (this->last_selected != GetSelection()) - this->last_selected = GetSelection(); + this->last_selected = GetSelection(); } // Frequently changed parameters @@ -829,10 +828,7 @@ void Sidebar::update_presets(Preset::Type preset_type) preset_bundle.sla_materials.update_platter_ui(p->combo_sla_material); } // Update the printer choosers, update the dirty flags. - auto prev_selection = p->combo_printer->GetSelection(); preset_bundle.printers.update_platter_ui(p->combo_printer); - if (prev_selection != p->combo_printer->GetSelection()) - p->combo_printer->check_selection(); // Update the filament choosers to only contain the compatible presets, update the color preview, // update the dirty flags. if (print_tech == ptFFF) { diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 3da4c18716..82223b15c0 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -988,6 +988,7 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) ui->SetSelection(selected_preset_item); ui->SetToolTip(ui->GetString(selected_preset_item)); + ui->check_selection(); ui->Thaw(); } diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index 9f42613726..f78a04126f 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -1529,6 +1529,7 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::Pr } ui->SetSelection(selected_preset_item); ui->SetToolTip(ui->GetString(selected_preset_item)); + ui->check_selection(); ui->Thaw(); }