From 19a96336ffad44ad3c38383e0d7c93047c4258ad Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 20 Mar 2019 18:03:11 +0100 Subject: [PATCH 01/20] WIP on slice indexing --- src/libslic3r/SLAPrint.cpp | 300 +++++++++++++++++++++++++------------ src/libslic3r/SLAPrint.hpp | 112 ++++++++++---- 2 files changed, 289 insertions(+), 123 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 83fa61fdd..62ddba84b 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -567,6 +567,18 @@ sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c) { return scfg; } +sla::PoolConfig make_pool_config(const SLAPrintObjectConfig& c) { + sla::PoolConfig pcfg; + + pcfg.min_wall_thickness_mm = c.pad_wall_thickness.getFloat(); + pcfg.wall_slope = c.pad_wall_slope.getFloat(); + pcfg.edge_radius_mm = c.pad_edge_radius.getFloat(); + pcfg.max_merge_distance_mm = c.pad_max_merge_distance.getFloat(); + pcfg.min_wall_height_mm = c.pad_wall_height.getFloat(); + + return pcfg; +} + void swapXY(ExPolygon& expoly) { for(auto& p : expoly.contour.points) std::swap(p(X), p(Y)); for(auto& h : expoly.holes) for(auto& p : h.points) std::swap(p(X), p(Y)); @@ -647,18 +659,58 @@ void SLAPrint::process() // Slicing the model object. This method is oversimplified and needs to // be compared with the fff slicing algorithm for verification auto slice_model = [this, ilh](SLAPrintObject& po) { - double lh = po.m_config.layer_height.getFloat(); - TriangleMesh mesh = po.transformed_mesh(); + + // We need to prepare the slice index... + + auto&& bb3d = mesh.bounding_box(); + float minZ = float(bb3d.min(Z)) - float(po.get_elevation()); + float maxZ = float(bb3d.max(Z)); + auto flh = float(po.m_config.layer_height.getFloat()); + + auto slh = [](float h) { return LevelID( double(h) / SCALING_FACTOR); }; + + po.m_slice_index.clear(); + po.m_slice_index.reserve(size_t(maxZ - (minZ + ilh) / flh) + 1); + po.m_slice_index.emplace_back(slh(minZ + ilh), minZ + ilh / 2.f, ilh); + + for(float h = minZ + ilh + flh; h <= maxZ; h += flh) { + po.m_slice_index.emplace_back(slh(h), h - flh / 2.f, flh); + } + + + using SlRec = SLAPrintObject::SliceRecord; + auto slindex_it = std::lower_bound(po.m_slice_index.begin(), + po.m_slice_index.end(), + float(bb3d.min(Z)), // model start z + [](const SlRec& sr1, const SlRec& sr2){ + return sr1.slice_level() < sr2.slice_level(); + }); + + if(slindex_it == po.m_slice_index.end()) + throw std::runtime_error(L("Slicing had to be stopped " + "due to an internal error.")); + + po.m_height_levels.clear(); + po.m_height_levels.reserve(po.m_slice_index.size()); + for(auto it = slindex_it; it != po.m_slice_index.end(); ++it) + po.m_height_levels.emplace_back(it->slice_level()); + TriangleMeshSlicer slicer(&mesh); - // The 1D grid heights - std::vector heights = calculate_heights(mesh.bounding_box(), - float(po.get_elevation()), - ilh, float(lh)); + po.m_model_slices.clear(); + slicer.slice(po.m_height_levels, + float(po.config().slice_closing_radius.value), + &po.m_model_slices, + [this](){ throw_if_canceled(); }); - auto& layers = po.m_model_slices; layers.clear(); - slicer.slice(heights, float(po.config().slice_closing_radius.value), &layers, [this](){ throw_if_canceled(); }); + auto mit = slindex_it; + for(size_t id = 0; + id < po.m_model_slices.size() && mit != po.m_slice_index.end(); + id++) + { + mit->set_model_slice_idx(id); ++mit; + } }; // In this step we check the slices, identify island and cover them with @@ -680,12 +732,8 @@ void SLAPrint::process() if (mo.sla_points_status != sla::PointsStatus::UserModified) { // calculate heights of slices (slices are calculated already) - double lh = po.m_config.layer_height.getFloat(); - - std::vector heights = - calculate_heights(po.transformed_mesh().bounding_box(), - float(po.get_elevation()), - ilh, float(lh)); + auto&& bb = po.transformed_mesh().bounding_box(); + std::vector heights = po.get_slice_levels(float(bb.min(Z))); this->throw_if_canceled(); SLAAutoSupports::Config config; @@ -837,79 +885,86 @@ void SLAPrint::process() auto lh = float(po.m_config.layer_height.getFloat()); sd->support_slices = sd->support_tree_ptr->slice(lh, ilh); } + + for(size_t i = 0; + i < sd->support_slices.size() && i < po.m_slice_index.size(); + ++i) + { + po.m_slice_index[i].set_support_slice_idx(i); + } }; // We have the layer polygon collection but we need to unite them into // an index where the key is the height level in discrete levels (clipper) auto index_slices = [this, ilhd](SLAPrintObject& po) { - po.m_slice_index.clear(); - auto sih = LevelID(scale_(ilhd)); +// po.m_slice_index.clear(); +// auto sih = LevelID(scale_(ilhd)); - // Establish the slice grid boundaries - auto bb = po.transformed_mesh().bounding_box(); - double modelgnd = bb.min(Z); - double elevation = po.get_elevation(); - double lh = po.m_config.layer_height.getFloat(); - double minZ = modelgnd - elevation; +// // Establish the slice grid boundaries +// auto bb = po.transformed_mesh().bounding_box(); +// double modelgnd = bb.min(Z); +// double elevation = po.get_elevation(); +// double lh = po.m_config.layer_height.getFloat(); +// double minZ = modelgnd - elevation; - // scaled values: - auto sminZ = LevelID(scale_(minZ)); - auto smaxZ = LevelID(scale_(bb.max(Z))); - auto smodelgnd = LevelID(scale_(modelgnd)); - auto slh = LevelID(scale_(lh)); +// // scaled values: +// auto sminZ = LevelID(scale_(minZ)); +// auto smaxZ = LevelID(scale_(bb.max(Z))); +// auto smodelgnd = LevelID(scale_(modelgnd)); +// auto slh = LevelID(scale_(lh)); - // It is important that the next levels match the levels in - // model_slice method. Only difference is that here it works with - // scaled coordinates - po.m_level_ids.clear(); - for(LevelID h = sminZ + sih; h < smaxZ; h += slh) - if(h >= smodelgnd) po.m_level_ids.emplace_back(h); +// // It is important that the next levels match the levels in +// // model_slice method. Only difference is that here it works with +// // scaled coordinates +// po.m_level_ids.clear(); +// for(LevelID h = sminZ + sih; h < smaxZ; h += slh) +// if(h >= smodelgnd) po.m_level_ids.emplace_back(h); - std::vector& oslices = po.m_model_slices; +// std::vector& oslices = po.m_model_slices; - // If everything went well this code should not run at all, but - // let's be robust... - // assert(levelids.size() == oslices.size()); - if(po.m_level_ids.size() < oslices.size()) { // extend the levels until... +// // If everything went well this code should not run at all, but +// // let's be robust... +// // assert(levelids.size() == oslices.size()); +// if(po.m_level_ids.size() < oslices.size()) { // extend the levels until... - BOOST_LOG_TRIVIAL(warning) - << "Height level mismatch at rasterization!\n"; +// BOOST_LOG_TRIVIAL(warning) +// << "Height level mismatch at rasterization!\n"; - LevelID lastlvl = po.m_level_ids.back(); - while(po.m_level_ids.size() < oslices.size()) { - lastlvl += slh; - po.m_level_ids.emplace_back(lastlvl); - } - } +// LevelID lastlvl = po.m_level_ids.back(); +// while(po.m_level_ids.size() < oslices.size()) { +// lastlvl += slh; +// po.m_level_ids.emplace_back(lastlvl); +// } +// } - for(size_t i = 0; i < oslices.size(); ++i) { - LevelID h = po.m_level_ids[i]; +// for(size_t i = 0; i < oslices.size(); ++i) { +// LevelID h = po.m_level_ids[i]; - float fh = float(double(h) * SCALING_FACTOR); +// float fh = float(double(h) * SCALING_FACTOR); - // now for the public slice index: - SLAPrintObject::SliceRecord& sr = po.m_slice_index[fh]; - // There should be only one slice layer for each print object - assert(sr.model_slices_idx == SLAPrintObject::SliceRecord::NONE); - sr.model_slices_idx = i; - } +// // now for the public slice index: +// SLAPrintObject::SliceRecord& sr = po.m_slice_index[fh]; +// // There should be only one slice layer for each print object +// assert(sr.model_slices_idx == SLAPrintObject::SliceRecord::NONE); +// sr.model_slices_idx = i; +// } - if(po.m_supportdata) { // deal with the support slices if present - std::vector& sslices = po.m_supportdata->support_slices; - po.m_supportdata->level_ids.clear(); - po.m_supportdata->level_ids.reserve(sslices.size()); +// if(po.m_supportdata) { // deal with the support slices if present +// std::vector& sslices = po.m_supportdata->support_slices; +// po.m_supportdata->level_ids.clear(); +// po.m_supportdata->level_ids.reserve(sslices.size()); - for(int i = 0; i < int(sslices.size()); ++i) { - LevelID h = sminZ + sih + i * slh; - po.m_supportdata->level_ids.emplace_back(h); +// for(int i = 0; i < int(sslices.size()); ++i) { +// LevelID h = sminZ + sih + i * slh; +// po.m_supportdata->level_ids.emplace_back(h); - float fh = float(double(h) * SCALING_FACTOR); +// float fh = float(double(h) * SCALING_FACTOR); - SLAPrintObject::SliceRecord& sr = po.m_slice_index[fh]; - assert(sr.support_slices_idx == SLAPrintObject::SliceRecord::NONE); - sr.support_slices_idx = SLAPrintObject::SliceRecord::Idx(i); - } - } +// SLAPrintObject::SliceRecord& sr = po.m_slice_index[fh]; +// assert(sr.support_slices_idx == SLAPrintObject::SliceRecord::NONE); +// sr.support_slices_idx = SLAPrintObject::SliceRecord::Idx(i); +// } +// } // Using RELOAD_SLA_PREVIEW to tell the Plater to pass the update status to the 3D preview to load the SLA slices. report_status(*this, -2, "", SlicingStatus::RELOAD_SLA_PREVIEW); @@ -923,31 +978,33 @@ void SLAPrint::process() m_printer_input.clear(); for(SLAPrintObject * o : m_objects) { - auto& po = *o; - std::vector& oslices = po.m_model_slices; +// auto& po = *o; +// std::vector& oslices = po.m_model_slices; - // We need to adjust the min Z level of the slices to be zero - LevelID smfirst = - po.m_supportdata && !po.m_supportdata->level_ids.empty() ? - po.m_supportdata->level_ids.front() : 0; - LevelID mfirst = po.m_level_ids.empty()? 0 : po.m_level_ids.front(); - LevelID gndlvl = -(std::min(smfirst, mfirst)); +// // We need to adjust the min Z level of the slices to be zero +// LevelID smfirst = +// po.m_supportdata && !po.m_supportdata->level_ids.empty() ? +// po.m_supportdata->level_ids.front() : 0; +// LevelID mfirst = po.m_level_ids.empty()? 0 : po.m_level_ids.front(); +// LevelID gndlvl = -(std::min(smfirst, mfirst)); - // now merge this object's support and object slices with the rest - // of the print object slices +// // now merge this object's support and object slices with the rest +// // of the print object slices - for(size_t i = 0; i < oslices.size(); ++i) { - auto& lyrs = m_printer_input[gndlvl + po.m_level_ids[i]]; - lyrs.emplace_back(oslices[i], po.m_instances); - } +// for(size_t i = 0; i < oslices.size(); ++i) { +// auto& lyrs = m_printer_input[gndlvl + po.m_level_ids[i]]; +// lyrs.emplace_back(oslices[i], po.m_instances); +// } - if(!po.m_supportdata) continue; - std::vector& sslices = po.m_supportdata->support_slices; - for(size_t i = 0; i < sslices.size(); ++i) { - LayerRefs& lyrs = - m_printer_input[gndlvl + po.m_supportdata->level_ids[i]]; - lyrs.emplace_back(sslices[i], po.m_instances); - } +// if(!po.m_supportdata) continue; +// std::vector& sslices = po.m_supportdata->support_slices; +// for(size_t i = 0; i < sslices.size(); ++i) { +// LayerRefs& lyrs = +// m_printer_input[gndlvl + po.m_supportdata->level_ids[i]]; +// lyrs.emplace_back(sslices[i], po.m_instances); +// } + +// for(size_t i = 0; i < o->m_sli) } // collect all the keys @@ -1474,11 +1531,7 @@ double SLAPrintObject::get_elevation() const { // its walls but currently it is half of its thickness. Whatever it // will be in the future, we provide the config to the get_pad_elevation // method and we will have the correct value - sla::PoolConfig pcfg; - pcfg.min_wall_height_mm = m_config.pad_wall_height.getFloat(); - pcfg.min_wall_thickness_mm = m_config.pad_wall_thickness.getFloat(); - pcfg.edge_radius_mm = m_config.pad_edge_radius.getFloat(); - pcfg.max_merge_distance_mm = m_config.pad_max_merge_distance.getFloat(); + sla::PoolConfig pcfg = make_pool_config(m_config); ret += sla::get_pad_elevation(pcfg); } @@ -1509,6 +1562,33 @@ const std::vector& SLAPrintObject::get_support_points() const return m_supportdata->support_points; } +SliceIterator SLAPrintObject::get_slices(SliceOrigin so, LevelID k) const +{ + SliceIterator ret = so == soModel ? get_model_slices().end() : + get_support_slices().end(); + + auto it = std::lower_bound(m_slice_index.begin(), + m_slice_index.end(), + k, + SliceRecord::cmpfn); + + if(it != m_slice_index.end()) { + ret = it->get_slices(*this, so); + } + + return ret; +} + +SliceRange SLAPrintObject::get_slices(SliceOrigin so, + float from_level, + float to_level) const +{ + auto from = LevelID(double(from_level) / SCALING_FACTOR); + auto to = LevelID(double(to_level) / SCALING_FACTOR); + + return SliceRange(get_slices(so, from), get_slices(so, to)); +} + const std::vector &SLAPrintObject::get_support_slices() const { // assert(is_step_done(slaposSliceSupports)); @@ -1516,12 +1596,28 @@ const std::vector &SLAPrintObject::get_support_slices() const return m_supportdata->support_slices; } -const SLAPrintObject::SliceIndex &SLAPrintObject::get_slice_index() const +const std::vector& +SLAPrintObject::get_slice_index() const { // assert(is_step_done(slaposIndexSlices)); return m_slice_index; } +std::vector SLAPrintObject::get_slice_levels(float from_eq) const +{ + using SlRec = SLAPrintObject::SliceRecord; + auto it = std::lower_bound(m_slice_index.begin(), + m_slice_index.end(), + from_eq, // model start z + [](const SlRec& sr1, const SlRec& sr2){ + return sr1.slice_level() < sr2.slice_level(); + }); + + std::vector heights; heights.reserve(m_slice_index.size()); + for(; it != m_slice_index.end(); ++it) + heights.emplace_back(it->slice_level()); +} + const std::vector &SLAPrintObject::get_model_slices() const { // assert(is_step_done(slaposObjectSlice)); @@ -1639,4 +1735,18 @@ std::string SLAPrintStatistics::finalize_output_path(const std::string &path_in) return final_path; } +SliceIterator SLAPrintObject::SliceRecord::get_slices(const SLAPrintObject &po, + SliceOrigin so) const +{ + + const std::vector& v = so == soModel? po.get_model_slices() : + po.get_support_slices(); + + Idx idx = so == soModel ? m_model_slices_idx : m_support_slices_idx; + + using DiffT = std::vector::const_iterator::difference_type; + + return idx == NONE? v.end() : v.begin() + DiffT(idx); +} + } // namespace Slic3r diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index c06e2fc77..4d5f1d0da 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -35,12 +35,34 @@ using _SLAPrintObjectBase = // the printer (rasterizer) in the SLAPrint class. using LevelID = long long; +template struct Range { + It from, to; + It begin() const { return from; } + It end() const { return to; } + using Type = It; + + Range() = default; + explicit Range(It &&b, It &&e): + from(std::forward(b)), to(std::forward(e)) {} +}; + +enum SliceOrigin { soSlice, soModel }; + +using SliceStore = std::vector; +using SliceIterator = SliceStore::const_iterator; +using SliceRange = Range; + class SLAPrintObject : public _SLAPrintObjectBase { private: // Prevents erroneous use by other classes. using Inherited = _SLAPrintObjectBase; public: + + // I refuse to grantee copying (Tamas) + SLAPrintObject(const SLAPrintObject&) = delete; + SLAPrintObject& operator=(const SLAPrintObject&) = delete; + const SLAPrintObjectConfig& config() const { return m_config; } const Transform3d& trafo() const { return m_trafo; } @@ -82,6 +104,66 @@ public: // pad is not, then without the pad, otherwise the full value is returned. double get_current_elevation() const; + // This method returns the support points of this SLAPrintObject. + const std::vector& get_support_points() const; + +private: + + // An index record referencing the slices + // (get_model_slices(), get_support_slices()) where the keys are the height + // levels of the model in scaled-clipper coordinates. The levels correspond + // to the z coordinate of the object coordinate system. + class SliceRecord { + public: + using Key = LevelID; + + private: + using Idx = size_t; + static const Idx NONE = Idx(-1); // this will be the max limit of size_t + + LevelID m_print_z = 0; // Top of the layer + float m_slice_z = 0.f; // Exact level of the slice + float m_height = 0.f; // Height of the sliced layer + Idx m_model_slices_idx = NONE; + Idx m_support_slices_idx = NONE; + + public: + + SliceRecord(Key key, float slicez, float height): + m_print_z(key), m_slice_z(slicez), m_height(height) {} + + inline static bool cmpfn(const SliceRecord& sr1, const SliceRecord& sr2) + { + return sr1.key() < sr2.key(); + } + + inline Key key() const { return m_print_z; } + inline float slice_level() const { return m_slice_z; } + inline float layer_height() const { return m_height; } + + SliceIterator get_slices(const SLAPrintObject& po, + SliceOrigin so) const; + + void set_model_slice_idx(Idx id) { m_model_slices_idx = id; } + void set_support_slice_idx(Idx id) { m_support_slices_idx = id; } + }; + + + // Retrieve the slice index which is readable only after slaposIndexSlices + // is done. + const std::vector& get_slice_index() const; + + std::vector get_slice_levels(float from_eq) const; + +public: + + SliceIterator get_slices(SliceOrigin so, LevelID k) const; + + SliceRange get_slices( + SliceOrigin so, + float from_level, + float to_level = std::numeric_limits::infinity()) const; + // These two methods should be callable on the client side (e.g. UI thread) // when the appropriate steps slaposObjectSlice and slaposSliceSupports // are ready. All the print objects are processed before slapsRasterize so @@ -89,33 +171,6 @@ public: const std::vector& get_model_slices() const; const std::vector& get_support_slices() const; - // This method returns the support points of this SLAPrintObject. - const std::vector& get_support_points() const; - - // An index record referencing the slices - // (get_model_slices(), get_support_slices()) where the keys are the height - // levels of the model in scaled-clipper coordinates. The levels correspond - // to the z coordinate of the object coordinate system. - struct SliceRecord { - using Key = float; - - using Idx = size_t; - static const Idx NONE = Idx(-1); // this will be the max limit of size_t - - Idx model_slices_idx = NONE; - Idx support_slices_idx = NONE; - }; - - using SliceIndex = std::map; - - // Retrieve the slice index which is readable only after slaposIndexSlices - // is done. - const SliceIndex& get_slice_index() const; - - // I refuse to grantee copying (Tamas) - SLAPrintObject(const SLAPrintObject&) = delete; - SLAPrintObject& operator=(const SLAPrintObject&) = delete; - protected: // to be called from SLAPrint only. friend class SLAPrint; @@ -154,11 +209,12 @@ private: // Exact (float) height levels mapped to the slices. Each record contains // the index to the model and the support slice vectors. - SliceIndex m_slice_index; + std::vector m_slice_index; // The height levels corrected and scaled up in integer values. This will // be used at rasterization. std::vector m_level_ids; + std::vector m_height_levels; // Caching the transformed (m_trafo) raw mesh of the object mutable CachedObject m_transformed_rmesh; From d4dde12d0d031970113706a5dd954907776216ed Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 21 Mar 2019 12:25:33 +0100 Subject: [PATCH 02/20] Slic3r compiles with the new slice index interface. --- src/libslic3r/SLAPrint.cpp | 151 +++++++++++++++++++++++---------- src/libslic3r/SLAPrint.hpp | 32 ++++--- src/slic3r/GUI/GLCanvas3D.cpp | 66 +++++++++----- src/slic3r/GUI/GUI_Preview.cpp | 6 +- 4 files changed, 172 insertions(+), 83 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 62ddba84b..938f148a3 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -678,14 +678,7 @@ void SLAPrint::process() po.m_slice_index.emplace_back(slh(h), h - flh / 2.f, flh); } - - using SlRec = SLAPrintObject::SliceRecord; - auto slindex_it = std::lower_bound(po.m_slice_index.begin(), - po.m_slice_index.end(), - float(bb3d.min(Z)), // model start z - [](const SlRec& sr1, const SlRec& sr2){ - return sr1.slice_level() < sr2.slice_level(); - }); + auto slindex_it = po.search_slice_index(float(bb3d.min(Z))); if(slindex_it == po.m_slice_index.end()) throw std::runtime_error(L("Slicing had to be stopped " @@ -715,7 +708,7 @@ void SLAPrint::process() // In this step we check the slices, identify island and cover them with // support points. Then we sprinkle the rest of the mesh. - auto support_points = [this, ilh](SLAPrintObject& po) { + auto support_points = [this](SLAPrintObject& po) { const ModelObject& mo = *po.m_model_object; po.m_supportdata.reset( new SLAPrintObject::SupportData(po.transformed_mesh()) ); @@ -732,8 +725,7 @@ void SLAPrint::process() if (mo.sla_points_status != sla::PointsStatus::UserModified) { // calculate heights of slices (slices are calculated already) - auto&& bb = po.transformed_mesh().bounding_box(); - std::vector heights = po.get_slice_levels(float(bb.min(Z))); + const std::vector& heights = po.m_height_levels; this->throw_if_canceled(); SLAAutoSupports::Config config; @@ -896,7 +888,7 @@ void SLAPrint::process() // We have the layer polygon collection but we need to unite them into // an index where the key is the height level in discrete levels (clipper) - auto index_slices = [this, ilhd](SLAPrintObject& po) { + auto index_slices = [this/*, ilhd*/](SLAPrintObject& /*po*/) { // po.m_slice_index.clear(); // auto sih = LevelID(scale_(ilhd)); @@ -978,6 +970,19 @@ void SLAPrint::process() m_printer_input.clear(); for(SLAPrintObject * o : m_objects) { + LevelID gndlvl = o->get_slice_index().front().key(); + for(auto& slicerecord : o->get_slice_index()) { + auto& lyrs = m_printer_input[slicerecord.key() - gndlvl]; + auto objslit = slicerecord.get_slices(*o, soModel); + auto supslit = slicerecord.get_slices(*o, soSupport); + + if(objslit != o->get_model_slices().end()) + lyrs.emplace_back(*objslit, o->instances()); + + if(supslit != o->get_support_slices().end()) + lyrs.emplace_back(*supslit, o->instances()); + } + // auto& po = *o; // std::vector& oslices = po.m_model_slices; @@ -1003,8 +1008,6 @@ void SLAPrint::process() // m_printer_input[gndlvl + po.m_supportdata->level_ids[i]]; // lyrs.emplace_back(sslices[i], po.m_instances); // } - -// for(size_t i = 0; i < o->m_sli) } // collect all the keys @@ -1306,13 +1309,13 @@ void SLAPrint::fill_statistics() // find highest object // Which is a better bet? To compare by max_z or by number of layers in the index? - double max_z = 0.; + float max_z = 0.; size_t max_layers_cnt = 0; size_t highest_obj_idx = 0; for (SLAPrintObject *&po : m_objects) { const SLAPrintObject::SliceIndex& slice_index = po->get_slice_index(); if (! slice_index.empty()) { - double z = (-- slice_index.end())->first; + float z = (-- slice_index.end())->slice_level(); size_t cnt = slice_index.size(); //if (z > max_z) { if (cnt > max_layers_cnt) { @@ -1332,7 +1335,7 @@ void SLAPrint::fill_statistics() int sliced_layer_cnt = 0; for (const auto& layer : highest_obj_slice_index) { - const double l_height = (layer.first == highest_obj_slice_index.begin()->first) ? init_layer_height : layer_height; + const double l_height = (layer.key() == highest_obj_slice_index.begin()->key()) ? init_layer_height : layer_height; // Calculation of the consumed material @@ -1344,18 +1347,19 @@ void SLAPrint::fill_statistics() const SLAPrintObject::SliceRecord *record = nullptr; { const SLAPrintObject::SliceIndex& index = po->get_slice_index(); - auto key = layer.first; - const SLAPrintObject::SliceIndex::const_iterator it_key = index.lower_bound(key - float(EPSILON)); - if (it_key == index.end() || it_key->first > key + EPSILON) + auto it = po->search_slice_index(layer.slice_level() - float(EPSILON)); + if (it == index.end() || it->slice_level() > layer.slice_level() + float(EPSILON)) continue; - record = &it_key->second; + record = &(*it); } - if (record->model_slices_idx != SLAPrintObject::SliceRecord::NONE) - append(model_polygons, get_all_polygons(po->get_model_slices()[record->model_slices_idx], po->instances())); + auto modelslice_it = record->get_slices(*po, soModel); + if (modelslice_it != po->get_model_slices().end()) + append(model_polygons, get_all_polygons(*modelslice_it, po->instances())); - if (record->support_slices_idx != SLAPrintObject::SliceRecord::NONE) - append(supports_polygons, get_all_polygons(po->get_support_slices()[record->support_slices_idx], po->instances())); + auto supportslice_it = record->get_slices(*po, soSupport); + if (supportslice_it != po->get_support_slices().end()) + append(supports_polygons, get_all_polygons(*supportslice_it, po->instances())); } model_polygons = union_(model_polygons); @@ -1562,15 +1566,74 @@ const std::vector& SLAPrintObject::get_support_points() const return m_supportdata->support_points; } +SLAPrintObject::SliceIndex::iterator +SLAPrintObject::search_slice_index(float slice_level) +{ + SliceRecord query(0, slice_level, 0); + auto it = std::lower_bound(m_slice_index.begin(), m_slice_index.end(), + query, + [](const SliceRecord& r1, const SliceRecord& r2) + { + return r1.slice_level() < r2.slice_level(); + }); + + return it; +} + +SLAPrintObject::SliceIndex::const_iterator +SLAPrintObject::search_slice_index(float slice_level) const +{ + SliceRecord query(0, slice_level, 0); + auto it = std::lower_bound(m_slice_index.cbegin(), m_slice_index.cend(), + query, + [](const SliceRecord& r1, const SliceRecord& r2) + { + return r1.slice_level() < r2.slice_level(); + }); + + return it; +} + +SLAPrintObject::SliceIndex::iterator +SLAPrintObject::search_slice_index(SLAPrintObject::SliceRecord::Key key) +{ + SliceRecord query(key, 0.f, 0.f); + auto it = std::lower_bound(m_slice_index.begin(), m_slice_index.end(), + query, + [](const SliceRecord& r1, const SliceRecord& r2) + { + return r1.key() < r2.key(); + }); + + // Return valid iterator only if the keys really match + if(it != m_slice_index.end() && it->key() != key) it = m_slice_index.end(); + + return it; +} + +SLAPrintObject::SliceIndex::const_iterator +SLAPrintObject::search_slice_index(SLAPrintObject::SliceRecord::Key key) const +{ + SliceRecord query(key, 0.f, 0.f); + auto it = std::lower_bound(m_slice_index.cbegin(), m_slice_index.cend(), + query, + [](const SliceRecord& r1, const SliceRecord& r2) + { + return r1.key() < r2.key(); + }); + + // Return valid iterator only if the keys really match + if(it != m_slice_index.end() && it->key() != key) it = m_slice_index.end(); + + return it; +} + SliceIterator SLAPrintObject::get_slices(SliceOrigin so, LevelID k) const { SliceIterator ret = so == soModel ? get_model_slices().end() : get_support_slices().end(); - auto it = std::lower_bound(m_slice_index.begin(), - m_slice_index.end(), - k, - SliceRecord::cmpfn); + auto it = search_slice_index(k); if(it != m_slice_index.end()) { ret = it->get_slices(*this, so); @@ -1603,20 +1666,22 @@ SLAPrintObject::get_slice_index() const return m_slice_index; } -std::vector SLAPrintObject::get_slice_levels(float from_eq) const -{ - using SlRec = SLAPrintObject::SliceRecord; - auto it = std::lower_bound(m_slice_index.begin(), - m_slice_index.end(), - from_eq, // model start z - [](const SlRec& sr1, const SlRec& sr2){ - return sr1.slice_level() < sr2.slice_level(); - }); +//std::vector SLAPrintObject::get_slice_levels(float from_eq) const +//{ +// using SlRec = SLAPrintObject::SliceRecord; +// auto it = std::lower_bound(m_slice_index.begin(), +// m_slice_index.end(), +// from_eq, // model start z +// [](const SlRec& sr1, const SlRec& sr2){ +// return sr1.slice_level() < sr2.slice_level(); +// }); - std::vector heights; heights.reserve(m_slice_index.size()); - for(; it != m_slice_index.end(); ++it) - heights.emplace_back(it->slice_level()); -} +// std::vector heights; heights.reserve(m_slice_index.size()); +// for(; it != m_slice_index.end(); ++it) +// heights.emplace_back(it->slice_level()); + + +//} const std::vector &SLAPrintObject::get_model_slices() const { @@ -1742,7 +1807,7 @@ SliceIterator SLAPrintObject::SliceRecord::get_slices(const SLAPrintObject &po, const std::vector& v = so == soModel? po.get_model_slices() : po.get_support_slices(); - Idx idx = so == soModel ? m_model_slices_idx : m_support_slices_idx; + size_t idx = so == soModel ? m_model_slices_idx : m_support_slices_idx; using DiffT = std::vector::const_iterator::difference_type; diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 4d5f1d0da..620462875 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -46,7 +46,7 @@ template struct Range { from(std::forward(b)), to(std::forward(e)) {} }; -enum SliceOrigin { soSlice, soModel }; +enum SliceOrigin { soSupport, soModel }; using SliceStore = std::vector; using SliceIterator = SliceStore::const_iterator; @@ -118,25 +118,19 @@ private: using Key = LevelID; private: - using Idx = size_t; - static const Idx NONE = Idx(-1); // this will be the max limit of size_t + static const size_t NONE = size_t(-1); // this will be the max limit of size_t + size_t m_model_slices_idx = NONE; + size_t m_support_slices_idx = NONE; LevelID m_print_z = 0; // Top of the layer float m_slice_z = 0.f; // Exact level of the slice float m_height = 0.f; // Height of the sliced layer - Idx m_model_slices_idx = NONE; - Idx m_support_slices_idx = NONE; public: SliceRecord(Key key, float slicez, float height): m_print_z(key), m_slice_z(slicez), m_height(height) {} - inline static bool cmpfn(const SliceRecord& sr1, const SliceRecord& sr2) - { - return sr1.key() < sr2.key(); - } - inline Key key() const { return m_print_z; } inline float slice_level() const { return m_slice_z; } inline float layer_height() const { return m_height; } @@ -144,16 +138,22 @@ private: SliceIterator get_slices(const SLAPrintObject& po, SliceOrigin so) const; - void set_model_slice_idx(Idx id) { m_model_slices_idx = id; } - void set_support_slice_idx(Idx id) { m_support_slices_idx = id; } + + void set_model_slice_idx(size_t id) { m_model_slices_idx = id; } + void set_support_slice_idx(size_t id) { m_support_slices_idx = id; } + }; + using SliceIndex = std::vector; // Retrieve the slice index which is readable only after slaposIndexSlices // is done. - const std::vector& get_slice_index() const; + const SliceIndex& get_slice_index() const; - std::vector get_slice_levels(float from_eq) const; + SliceIndex::iterator search_slice_index(float slice_level); + SliceIndex::const_iterator search_slice_index(float slice_level) const; + SliceIndex::iterator search_slice_index(SliceRecord::Key key); + SliceIndex::const_iterator search_slice_index(SliceRecord::Key key) const; public: @@ -171,6 +171,10 @@ public: const std::vector& get_model_slices() const; const std::vector& get_support_slices() const; + inline const std::vector& get_height_levels() const { + return m_height_levels; + } + protected: // to be called from SLAPrint only. friend class SLAPrint; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 1c09096a8..7bd63aa3c 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4937,32 +4937,52 @@ void GLCanvas3D::_render_sla_slices() const if ((bottom_obj_triangles.empty() || bottom_sup_triangles.empty() || top_obj_triangles.empty() || top_sup_triangles.empty()) && obj->is_step_done(slaposIndexSlices)) { - const std::vector& model_slices = obj->get_model_slices(); - const std::vector& support_slices = obj->get_support_slices(); + // FIXME: is this all right (by Tamas)? + SliceRange model_slices = obj->get_slices(soModel, float(min_z), float(max_z)); + SliceRange support_slices = obj->get_slices(soSupport, float(min_z), float(max_z)); - const SLAPrintObject::SliceIndex& index = obj->get_slice_index(); - SLAPrintObject::SliceIndex::const_iterator it_min_z = std::find_if(index.begin(), index.end(), [min_z](const SLAPrintObject::SliceIndex::value_type& id) -> bool { return std::abs(min_z - id.first) < EPSILON; }); - SLAPrintObject::SliceIndex::const_iterator it_max_z = std::find_if(index.begin(), index.end(), [max_z](const SLAPrintObject::SliceIndex::value_type& id) -> bool { return std::abs(max_z - id.first) < EPSILON; }); + // calculate model bottom cap + if(bottom_obj_triangles.empty() && model_slices.from != obj->get_model_slices().end()) + bottom_obj_triangles = triangulate_expolygons_3d(*model_slices.from, min_z, true); - if (it_min_z != index.end()) - { - // calculate model bottom cap - if (bottom_obj_triangles.empty() && (it_min_z->second.model_slices_idx < model_slices.size())) - bottom_obj_triangles = triangulate_expolygons_3d(model_slices[it_min_z->second.model_slices_idx], min_z, true); - // calculate support bottom cap - if (bottom_sup_triangles.empty() && (it_min_z->second.support_slices_idx < support_slices.size())) - bottom_sup_triangles = triangulate_expolygons_3d(support_slices[it_min_z->second.support_slices_idx], min_z, true); - } + // calculate support bottom cap + if(bottom_sup_triangles.empty() && support_slices.from != obj->get_support_slices().end()) + bottom_sup_triangles = triangulate_expolygons_3d(*support_slices.from, min_z, true); - if (it_max_z != index.end()) - { - // calculate model top cap - if (top_obj_triangles.empty() && (it_max_z->second.model_slices_idx < model_slices.size())) - top_obj_triangles = triangulate_expolygons_3d(model_slices[it_max_z->second.model_slices_idx], max_z, false); - // calculate support top cap - if (top_sup_triangles.empty() && (it_max_z->second.support_slices_idx < support_slices.size())) - top_sup_triangles = triangulate_expolygons_3d(support_slices[it_max_z->second.support_slices_idx], max_z, false); - } + // calculate model top cap + if(top_obj_triangles.empty() && model_slices.to != obj->get_model_slices().end()) + top_obj_triangles = triangulate_expolygons_3d(*model_slices.to, max_z, true); + + // calculate support top cap + if(top_sup_triangles.empty() && support_slices.to != obj->get_support_slices().end()) + top_sup_triangles = triangulate_expolygons_3d(*support_slices.to, max_z, true); + +// const std::vector& model_slices = obj->get_model_slices(); +// const std::vector& support_slices = obj->get_support_slices(); + +// const SLAPrintObject::SliceIndex& index = obj->get_slice_index(); +// SLAPrintObject::SliceIndex::const_iterator it_min_z = std::find_if(index.begin(), index.end(), [min_z](const SLAPrintObject::SliceIndex::value_type& id) -> bool { return std::abs(min_z - id.first) < EPSILON; }); +// SLAPrintObject::SliceIndex::const_iterator it_max_z = std::find_if(index.begin(), index.end(), [max_z](const SLAPrintObject::SliceIndex::value_type& id) -> bool { return std::abs(max_z - id.first) < EPSILON; }); + +// if (it_min_z != index.end()) +// { +// // calculate model bottom cap +// if (bottom_obj_triangles.empty() && (it_min_z->second.model_slices_idx < model_slices.size())) +// bottom_obj_triangles = triangulate_expolygons_3d(model_slices[it_min_z->second.model_slices_idx], min_z, true); +// // calculate support bottom cap +// if (bottom_sup_triangles.empty() && (it_min_z->second.support_slices_idx < support_slices.size())) +// bottom_sup_triangles = triangulate_expolygons_3d(support_slices[it_min_z->second.support_slices_idx], min_z, true); +// } + +// if (it_max_z != index.end()) +// { +// // calculate model top cap +// if (top_obj_triangles.empty() && (it_max_z->second.model_slices_idx < model_slices.size())) +// top_obj_triangles = triangulate_expolygons_3d(model_slices[it_max_z->second.model_slices_idx], max_z, false); +// // calculate support top cap +// if (top_sup_triangles.empty() && (it_max_z->second.support_slices_idx < support_slices.size())) +// top_sup_triangles = triangulate_expolygons_3d(support_slices[it_max_z->second.support_slices_idx], max_z, false); +// } } if (!bottom_obj_triangles.empty() || !top_obj_triangles.empty() || !bottom_sup_triangles.empty() || !top_sup_triangles.empty()) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index be3fad9ec..f691850b4 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -776,10 +776,10 @@ void Preview::load_print_as_sla() double shift_z = obj->get_current_elevation(); if (obj->is_step_done(slaposIndexSlices)) { - const SLAPrintObject::SliceIndex& index = obj->get_slice_index(); - for (const SLAPrintObject::SliceIndex::value_type& id : index) + const std::vector& hlvls = obj->get_height_levels(); + for (float h : hlvls) { - zs.insert(shift_z + id.first); + zs.insert(shift_z + double(h)); } } } From 24a5dd4235764cd767e0bdfd7f69ee45f85deba2 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 21 Mar 2019 15:16:33 +0100 Subject: [PATCH 03/20] FIx for broken slice preview --- src/libslic3r/SLAPrint.cpp | 46 ++++++++++++++-------------------- src/libslic3r/SLAPrint.hpp | 12 ++++----- src/slic3r/GUI/GLCanvas3D.cpp | 22 ++++++++-------- src/slic3r/GUI/GUI_Preview.cpp | 6 ++--- 4 files changed, 40 insertions(+), 46 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 938f148a3..e12dc7f23 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -30,7 +30,6 @@ public: std::vector support_points; // all the support points (manual/auto) SupportTreePtr support_tree_ptr; // the supports SlicedSupports support_slices; // sliced supports - std::vector level_ids; inline SupportData(const TriangleMesh& trmesh): emesh(trmesh) {} }; @@ -603,25 +602,9 @@ std::string SLAPrint::validate() const return ""; } -std::vector SLAPrint::calculate_heights(const BoundingBoxf3& bb3d, - float elevation, - float initial_layer_height, - float layer_height) const -{ - std::vector heights; - float minZ = float(bb3d.min(Z)) - float(elevation); - float maxZ = float(bb3d.max(Z)); - auto flh = float(layer_height); - auto gnd = float(bb3d.min(Z)); - - for(float h = minZ + initial_layer_height; h < maxZ; h += flh) - if(h >= gnd) heights.emplace_back(h); - - return heights; -} - template -void report_status(SLAPrint& p, int st, const std::string& msg, Args&&...args) { +void report_status(SLAPrint& p, int st, const std::string& msg, Args&&...args) +{ BOOST_LOG_TRIVIAL(info) << st << "% " << msg; p.set_status(st, msg, std::forward(args)...); } @@ -684,15 +667,17 @@ void SLAPrint::process() throw std::runtime_error(L("Slicing had to be stopped " "due to an internal error.")); - po.m_height_levels.clear(); - po.m_height_levels.reserve(po.m_slice_index.size()); + po.m_model_height_levels.clear(); + po.m_model_height_levels.reserve(po.m_slice_index.size()); for(auto it = slindex_it; it != po.m_slice_index.end(); ++it) - po.m_height_levels.emplace_back(it->slice_level()); + { + po.m_model_height_levels.emplace_back(it->slice_level()); + } TriangleMeshSlicer slicer(&mesh); po.m_model_slices.clear(); - slicer.slice(po.m_height_levels, + slicer.slice(po.m_model_height_levels, float(po.config().slice_closing_radius.value), &po.m_model_slices, [this](){ throw_if_canceled(); }); @@ -725,7 +710,7 @@ void SLAPrint::process() if (mo.sla_points_status != sla::PointsStatus::UserModified) { // calculate heights of slices (slices are calculated already) - const std::vector& heights = po.m_height_levels; + const std::vector& heights = po.m_model_height_levels; this->throw_if_canceled(); SLAAutoSupports::Config config; @@ -1646,10 +1631,17 @@ SliceRange SLAPrintObject::get_slices(SliceOrigin so, float from_level, float to_level) const { - auto from = LevelID(double(from_level) / SCALING_FACTOR); - auto to = LevelID(double(to_level) / SCALING_FACTOR); + auto it_from = search_slice_index(from_level); + auto it_to = search_slice_index(to_level); - return SliceRange(get_slices(so, from), get_slices(so, to)); + SliceRange ret; + + auto endit = so == soModel? get_model_slices().end() : get_support_slices().end(); + + ret.from = it_from == m_slice_index.end() ? endit : it_from->get_slices(*this, so); + ret.to = it_to == m_slice_index.end() ? endit : it_to->get_slices(*this, so); + + return ret; } const std::vector &SLAPrintObject::get_support_slices() const diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 620462875..e86080963 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -171,8 +171,9 @@ public: const std::vector& get_model_slices() const; const std::vector& get_support_slices() const; - inline const std::vector& get_height_levels() const { - return m_height_levels; + inline size_t get_slice_count() const { return m_slice_index.size(); } + inline float get_slice_level(size_t idx) const { + return m_slice_index[idx].slice_level(); } protected: @@ -204,8 +205,10 @@ protected: private: // Object specific configuration, pulled from the configuration layer. SLAPrintObjectConfig m_config; + // Translation in Z + Rotation by Y and Z + Scaling / Mirroring. Transform3d m_trafo = Transform3d::Identity(); + std::vector m_instances; // Individual 2d slice polygons from lower z to higher z levels @@ -215,10 +218,7 @@ private: // the index to the model and the support slice vectors. std::vector m_slice_index; - // The height levels corrected and scaled up in integer values. This will - // be used at rasterization. - std::vector m_level_ids; - std::vector m_height_levels; + std::vector m_model_height_levels; // Caching the transformed (m_trafo) raw mesh of the object mutable CachedObject m_transformed_rmesh; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 7bd63aa3c..90656c93b 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4938,24 +4938,26 @@ void GLCanvas3D::_render_sla_slices() const if ((bottom_obj_triangles.empty() || bottom_sup_triangles.empty() || top_obj_triangles.empty() || top_sup_triangles.empty()) && obj->is_step_done(slaposIndexSlices)) { // FIXME: is this all right (by Tamas)? - SliceRange model_slices = obj->get_slices(soModel, float(min_z), float(max_z)); - SliceRange support_slices = obj->get_slices(soSupport, float(min_z), float(max_z)); + SliceRange obj_range = obj->get_slices(soModel, float(min_z), float(max_z)); + SliceRange sup_range = obj->get_slices(soSupport, float(min_z), float(max_z)); + auto obj_end = obj->get_model_slices().end(); + auto sup_end = obj->get_support_slices().end(); // calculate model bottom cap - if(bottom_obj_triangles.empty() && model_slices.from != obj->get_model_slices().end()) - bottom_obj_triangles = triangulate_expolygons_3d(*model_slices.from, min_z, true); + if(bottom_obj_triangles.empty() && obj_range.from != obj_end) + bottom_obj_triangles = triangulate_expolygons_3d(*obj_range.from, min_z, true); // calculate support bottom cap - if(bottom_sup_triangles.empty() && support_slices.from != obj->get_support_slices().end()) - bottom_sup_triangles = triangulate_expolygons_3d(*support_slices.from, min_z, true); + if(bottom_sup_triangles.empty() && sup_range.from != sup_end) + bottom_sup_triangles = triangulate_expolygons_3d(*sup_range.from, min_z, true); // calculate model top cap - if(top_obj_triangles.empty() && model_slices.to != obj->get_model_slices().end()) - top_obj_triangles = triangulate_expolygons_3d(*model_slices.to, max_z, true); + if(top_obj_triangles.empty() && obj_range.to != obj_end) + top_obj_triangles = triangulate_expolygons_3d(*obj_range.to, max_z, false); // calculate support top cap - if(top_sup_triangles.empty() && support_slices.to != obj->get_support_slices().end()) - top_sup_triangles = triangulate_expolygons_3d(*support_slices.to, max_z, true); + if(top_sup_triangles.empty() && sup_range.to != sup_end) + top_sup_triangles = triangulate_expolygons_3d(*sup_range.to, max_z, false); // const std::vector& model_slices = obj->get_model_slices(); // const std::vector& support_slices = obj->get_support_slices(); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index f691850b4..477673342 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -776,10 +776,10 @@ void Preview::load_print_as_sla() double shift_z = obj->get_current_elevation(); if (obj->is_step_done(slaposIndexSlices)) { - const std::vector& hlvls = obj->get_height_levels(); - for (float h : hlvls) + size_t cnt = obj->get_slice_count(); + for (size_t i = 0; i < cnt; i++) { - zs.insert(shift_z + double(h)); + zs.insert(shift_z + double(obj->get_slice_level(i))); } } } From 63a899b239a6ee8717102871aaea0122aab1ed34 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 21 Mar 2019 16:14:26 +0100 Subject: [PATCH 04/20] Using same slicing grid for the supports and the model. --- src/libslic3r/SLA/SLASupportTree.cpp | 12 ++++++++ src/libslic3r/SLA/SLASupportTree.hpp | 2 ++ src/libslic3r/SLAPrint.cpp | 45 +++++++--------------------- src/libslic3r/SLAPrint.hpp | 35 ++++++++++++++++++---- 4 files changed, 54 insertions(+), 40 deletions(-) diff --git a/src/libslic3r/SLA/SLASupportTree.cpp b/src/libslic3r/SLA/SLASupportTree.cpp index df9990822..34dd80cee 100644 --- a/src/libslic3r/SLA/SLASupportTree.cpp +++ b/src/libslic3r/SLA/SLASupportTree.cpp @@ -2240,6 +2240,18 @@ SlicedSupports SLASupportTree::slice(float layerh, float init_layerh) const return ret; } +SlicedSupports SLASupportTree::slice(const std::vector &heights, + float cr) const +{ + TriangleMesh fullmesh = m_impl->merged_mesh(); + fullmesh.merge(get_pad()); + TriangleMeshSlicer slicer(&fullmesh); + SlicedSupports ret; + slicer.slice(heights, cr, &ret, get().ctl().cancelfn); + + return ret; +} + const TriangleMesh &SLASupportTree::add_pad(const SliceLayer& baseplate, const PoolConfig& pcfg) const { diff --git a/src/libslic3r/SLA/SLASupportTree.hpp b/src/libslic3r/SLA/SLASupportTree.hpp index 74d7da9ca..66677e4d7 100644 --- a/src/libslic3r/SLA/SLASupportTree.hpp +++ b/src/libslic3r/SLA/SLASupportTree.hpp @@ -181,6 +181,8 @@ public: /// Get the sliced 2d layers of the support geometry. SlicedSupports slice(float layerh, float init_layerh = -1.0) const; + SlicedSupports slice(const std::vector&, float closing_radius) const; + /// Adding the "pad" (base pool) under the supports const TriangleMesh& add_pad(const SliceLayer& baseplate, const PoolConfig& pcfg) const; diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index e12dc7f23..bbf53ef7e 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -856,11 +856,19 @@ void SLAPrint::process() // Slicing the support geometries similarly to the model slicing procedure. // If the pad had been added previously (see step "base_pool" than it will // be part of the slices) - auto slice_supports = [ilh](SLAPrintObject& po) { + auto slice_supports = [](SLAPrintObject& po) { auto& sd = po.m_supportdata; if(sd && sd->support_tree_ptr) { - auto lh = float(po.m_config.layer_height.getFloat()); - sd->support_slices = sd->support_tree_ptr->slice(lh, ilh); + sd->support_slices.clear(); + + std::vector heights; heights.reserve(po.m_slice_index.size()); + + for(auto& rec : po.m_slice_index) { + heights.emplace_back(rec.slice_level()); + } + + sd->support_slices = sd->support_tree_ptr->slice( + heights, float(po.config().slice_closing_radius.value)); } for(size_t i = 0; @@ -1613,20 +1621,6 @@ SLAPrintObject::search_slice_index(SLAPrintObject::SliceRecord::Key key) const return it; } -SliceIterator SLAPrintObject::get_slices(SliceOrigin so, LevelID k) const -{ - SliceIterator ret = so == soModel ? get_model_slices().end() : - get_support_slices().end(); - - auto it = search_slice_index(k); - - if(it != m_slice_index.end()) { - ret = it->get_slices(*this, so); - } - - return ret; -} - SliceRange SLAPrintObject::get_slices(SliceOrigin so, float from_level, float to_level) const @@ -1658,23 +1652,6 @@ SLAPrintObject::get_slice_index() const return m_slice_index; } -//std::vector SLAPrintObject::get_slice_levels(float from_eq) const -//{ -// using SlRec = SLAPrintObject::SliceRecord; -// auto it = std::lower_bound(m_slice_index.begin(), -// m_slice_index.end(), -// from_eq, // model start z -// [](const SlRec& sr1, const SlRec& sr2){ -// return sr1.slice_level() < sr2.slice_level(); -// }); - -// std::vector heights; heights.reserve(m_slice_index.size()); -// for(; it != m_slice_index.end(); ++it) -// heights.emplace_back(it->slice_level()); - - -//} - const std::vector &SLAPrintObject::get_model_slices() const { // assert(is_step_done(slaposObjectSlice)); diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index e86080963..3e0a0c5e3 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -122,7 +122,7 @@ private: size_t m_model_slices_idx = NONE; size_t m_support_slices_idx = NONE; - LevelID m_print_z = 0; // Top of the layer + LevelID m_print_z = 0; // Top of the layer float m_slice_z = 0.f; // Exact level of the slice float m_height = 0.f; // Height of the sliced layer @@ -131,34 +131,54 @@ private: SliceRecord(Key key, float slicez, float height): m_print_z(key), m_slice_z(slicez), m_height(height) {} + // The key will be the integer height level of the top of the layer. inline Key key() const { return m_print_z; } + + // Returns the exact floating point Z coordinate of the slice inline float slice_level() const { return m_slice_z; } + + // Returns the current layer height inline float layer_height() const { return m_height; } - SliceIterator get_slices(const SLAPrintObject& po, - SliceOrigin so) const; - + // Returns the slices for eighter the model or the supports. The return + // value is an iterator to po.get_model_slices() or po.get_support_slices + // depending on the SliceOrigin parameter. + SliceIterator get_slices(const SLAPrintObject& po, SliceOrigin so) const; + // Methods for setting the indixes into the slice vectors. void set_model_slice_idx(size_t id) { m_model_slices_idx = id; } void set_support_slice_idx(size_t id) { m_support_slices_idx = id; } - }; + // Slice index will be a plain vector sorted by the integer height levels using SliceIndex = std::vector; // Retrieve the slice index which is readable only after slaposIndexSlices // is done. const SliceIndex& get_slice_index() const; + // Search slice index for the closest slice to the given level SliceIndex::iterator search_slice_index(float slice_level); SliceIndex::const_iterator search_slice_index(float slice_level) const; + + // Search the slice index for a particular level in integer coordinates. + // If no such layer is present, it will return m_slice_index.end() SliceIndex::iterator search_slice_index(SliceRecord::Key key); SliceIndex::const_iterator search_slice_index(SliceRecord::Key key) const; public: - SliceIterator get_slices(SliceOrigin so, LevelID k) const; + // ///////////////////////////////////////////////////////////////////////// + // The following methods can be used after the model and the support slicing + // steps have been succesfully finished. + // ///////////////////////////////////////////////////////////////////////// + // Getting slices for either the model or the supports for a particular + // height ID. +// SliceIterator get_slices(SliceOrigin so, LevelID k) const; + + // Getting slices (model or supports) for a Z coordinate range. The returned + // iterators should include the slices for the given boundaries as well. SliceRange get_slices( SliceOrigin so, float from_level, @@ -171,7 +191,10 @@ public: const std::vector& get_model_slices() const; const std::vector& get_support_slices() const; + // Returns the total number of slices in the slice grid (model and supports) inline size_t get_slice_count() const { return m_slice_index.size(); } + + // One can query the Z coordinate of the slice for a given inline float get_slice_level(size_t idx) const { return m_slice_index[idx].slice_level(); } From 5e646562cd2194cb03c80f68b871a6b3f9636d52 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 21 Mar 2019 18:01:41 +0100 Subject: [PATCH 05/20] Fixes for the duplicated layer issues... --- src/libslic3r/SLAPrint.cpp | 51 ++++++++++++++++++++-------------- src/libslic3r/SLAPrint.hpp | 51 ++++++++++++++++++---------------- src/slic3r/GUI/GUI_Preview.cpp | 2 +- 3 files changed, 58 insertions(+), 46 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index bbf53ef7e..58386c0bd 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -615,12 +615,19 @@ void SLAPrint::process() using namespace sla; using ExPolygon = Slic3r::ExPolygon; + if(m_objects.empty()) return; + // Assumption: at this point the print objects should be populated only with // the model objects we have to process and the instances are also filtered // shortcut to initial layer height double ilhd = m_material_config.initial_layer_height.getFloat(); auto ilh = float(ilhd); + double lhd = m_objects.front()->m_config.layer_height.getFloat(); + float lh = float(lhd); + + LevelID ilhs = ilhd / SCALING_FACTOR; + LevelID lhs = lhd / SCALING_FACTOR; const size_t objcount = m_objects.size(); const unsigned min_objstatus = 0; // where the per object operations start @@ -641,24 +648,26 @@ void SLAPrint::process() // Slicing the model object. This method is oversimplified and needs to // be compared with the fff slicing algorithm for verification - auto slice_model = [this, ilh](SLAPrintObject& po) { + auto slice_model = [this, ilhs, lhs, ilh, lh](SLAPrintObject& po) { TriangleMesh mesh = po.transformed_mesh(); // We need to prepare the slice index... auto&& bb3d = mesh.bounding_box(); - float minZ = float(bb3d.min(Z)) - float(po.get_elevation()); - float maxZ = float(bb3d.max(Z)); - auto flh = float(po.m_config.layer_height.getFloat()); + double minZ = bb3d.min(Z) - po.get_elevation(); + double maxZ = bb3d.max(Z); + + LevelID minZs = minZ / SCALING_FACTOR; + LevelID maxZs = maxZ / SCALING_FACTOR; auto slh = [](float h) { return LevelID( double(h) / SCALING_FACTOR); }; po.m_slice_index.clear(); - po.m_slice_index.reserve(size_t(maxZ - (minZ + ilh) / flh) + 1); - po.m_slice_index.emplace_back(slh(minZ + ilh), minZ + ilh / 2.f, ilh); + po.m_slice_index.reserve(size_t(maxZs - (minZs + ilhs) / lhs) + 1); + po.m_slice_index.emplace_back(minZs + ilhs, minZ + ilh / 2.f, ilh); - for(float h = minZ + ilh + flh; h <= maxZ; h += flh) { - po.m_slice_index.emplace_back(slh(h), h - flh / 2.f, flh); + for(LevelID h = minZs + ilhs + lhs; h <= maxZs; h += lhs) { + po.m_slice_index.emplace_back(h, h*SCALING_FACTOR - lh / 2.f, lh); } auto slindex_it = po.search_slice_index(float(bb3d.min(Z))); @@ -1337,7 +1346,7 @@ void SLAPrint::fill_statistics() for (SLAPrintObject * po : m_objects) { - const SLAPrintObject::SliceRecord *record = nullptr; + const SLAPrintObject::_SliceRecord *record = nullptr; { const SLAPrintObject::SliceIndex& index = po->get_slice_index(); auto it = po->search_slice_index(layer.slice_level() - float(EPSILON)); @@ -1562,10 +1571,10 @@ const std::vector& SLAPrintObject::get_support_points() const SLAPrintObject::SliceIndex::iterator SLAPrintObject::search_slice_index(float slice_level) { - SliceRecord query(0, slice_level, 0); + _SliceRecord query(0, slice_level, 0); auto it = std::lower_bound(m_slice_index.begin(), m_slice_index.end(), query, - [](const SliceRecord& r1, const SliceRecord& r2) + [](const _SliceRecord& r1, const _SliceRecord& r2) { return r1.slice_level() < r2.slice_level(); }); @@ -1576,10 +1585,10 @@ SLAPrintObject::search_slice_index(float slice_level) SLAPrintObject::SliceIndex::const_iterator SLAPrintObject::search_slice_index(float slice_level) const { - SliceRecord query(0, slice_level, 0); + _SliceRecord query(0, slice_level, 0); auto it = std::lower_bound(m_slice_index.cbegin(), m_slice_index.cend(), query, - [](const SliceRecord& r1, const SliceRecord& r2) + [](const _SliceRecord& r1, const _SliceRecord& r2) { return r1.slice_level() < r2.slice_level(); }); @@ -1588,12 +1597,12 @@ SLAPrintObject::search_slice_index(float slice_level) const } SLAPrintObject::SliceIndex::iterator -SLAPrintObject::search_slice_index(SLAPrintObject::SliceRecord::Key key) +SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) { - SliceRecord query(key, 0.f, 0.f); + _SliceRecord query(key, 0.f, 0.f); auto it = std::lower_bound(m_slice_index.begin(), m_slice_index.end(), query, - [](const SliceRecord& r1, const SliceRecord& r2) + [](const _SliceRecord& r1, const _SliceRecord& r2) { return r1.key() < r2.key(); }); @@ -1605,12 +1614,12 @@ SLAPrintObject::search_slice_index(SLAPrintObject::SliceRecord::Key key) } SLAPrintObject::SliceIndex::const_iterator -SLAPrintObject::search_slice_index(SLAPrintObject::SliceRecord::Key key) const +SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) const { - SliceRecord query(key, 0.f, 0.f); + _SliceRecord query(key, 0.f, 0.f); auto it = std::lower_bound(m_slice_index.cbegin(), m_slice_index.cend(), query, - [](const SliceRecord& r1, const SliceRecord& r2) + [](const _SliceRecord& r1, const _SliceRecord& r2) { return r1.key() < r2.key(); }); @@ -1645,7 +1654,7 @@ const std::vector &SLAPrintObject::get_support_slices() const return m_supportdata->support_slices; } -const std::vector& +const std::vector& SLAPrintObject::get_slice_index() const { // assert(is_step_done(slaposIndexSlices)); @@ -1769,7 +1778,7 @@ std::string SLAPrintStatistics::finalize_output_path(const std::string &path_in) return final_path; } -SliceIterator SLAPrintObject::SliceRecord::get_slices(const SLAPrintObject &po, +SliceIterator SLAPrintObject::_SliceRecord::get_slices(const SLAPrintObject &po, SliceOrigin so) const { diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 3e0a0c5e3..b33bfdeb0 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -107,30 +107,21 @@ public: // This method returns the support points of this SLAPrintObject. const std::vector& get_support_points() const; -private: - - // An index record referencing the slices - // (get_model_slices(), get_support_slices()) where the keys are the height - // levels of the model in scaled-clipper coordinates. The levels correspond - // to the z coordinate of the object coordinate system. class SliceRecord { public: using Key = LevelID; private: - static const size_t NONE = size_t(-1); // this will be the max limit of size_t - size_t m_model_slices_idx = NONE; - size_t m_support_slices_idx = NONE; - LevelID m_print_z = 0; // Top of the layer float m_slice_z = 0.f; // Exact level of the slice float m_height = 0.f; // Height of the sliced layer - public: - + protected: SliceRecord(Key key, float slicez, float height): m_print_z(key), m_slice_z(slicez), m_height(height) {} + public: + // The key will be the integer height level of the top of the layer. inline Key key() const { return m_print_z; } @@ -139,8 +130,25 @@ private: // Returns the current layer height inline float layer_height() const { return m_height; } + }; - // Returns the slices for eighter the model or the supports. The return +private: + + // An index record referencing the slices + // (get_model_slices(), get_support_slices()) where the keys are the height + // levels of the model in scaled-clipper coordinates. The levels correspond + // to the z coordinate of the object coordinate system. + class _SliceRecord: public SliceRecord { + private: + static const size_t NONE = size_t(-1); // this will be the max limit of size_t + size_t m_model_slices_idx = NONE; + size_t m_support_slices_idx = NONE; + + public: + _SliceRecord(Key key, float slicez, float height): + SliceRecord(key, slicez, height) {} + + // Returns the slices for either the model or the supports. The return // value is an iterator to po.get_model_slices() or po.get_support_slices // depending on the SliceOrigin parameter. SliceIterator get_slices(const SLAPrintObject& po, SliceOrigin so) const; @@ -151,7 +159,7 @@ private: }; // Slice index will be a plain vector sorted by the integer height levels - using SliceIndex = std::vector; + using SliceIndex = std::vector<_SliceRecord>; // Retrieve the slice index which is readable only after slaposIndexSlices // is done. @@ -163,8 +171,8 @@ private: // Search the slice index for a particular level in integer coordinates. // If no such layer is present, it will return m_slice_index.end() - SliceIndex::iterator search_slice_index(SliceRecord::Key key); - SliceIndex::const_iterator search_slice_index(SliceRecord::Key key) const; + SliceIndex::iterator search_slice_index(_SliceRecord::Key key); + SliceIndex::const_iterator search_slice_index(_SliceRecord::Key key) const; public: @@ -173,10 +181,6 @@ public: // steps have been succesfully finished. // ///////////////////////////////////////////////////////////////////////// - // Getting slices for either the model or the supports for a particular - // height ID. -// SliceIterator get_slices(SliceOrigin so, LevelID k) const; - // Getting slices (model or supports) for a Z coordinate range. The returned // iterators should include the slices for the given boundaries as well. SliceRange get_slices( @@ -194,9 +198,8 @@ public: // Returns the total number of slices in the slice grid (model and supports) inline size_t get_slice_count() const { return m_slice_index.size(); } - // One can query the Z coordinate of the slice for a given - inline float get_slice_level(size_t idx) const { - return m_slice_index[idx].slice_level(); + inline const SliceRecord& get_slice_record(size_t idx) const { + return m_slice_index[idx]; } protected: @@ -239,7 +242,7 @@ private: // Exact (float) height levels mapped to the slices. Each record contains // the index to the model and the support slice vectors. - std::vector m_slice_index; + std::vector<_SliceRecord> m_slice_index; std::vector m_model_height_levels; diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 148b83081..10a4a12c7 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -778,7 +778,7 @@ void Preview::load_print_as_sla() size_t cnt = obj->get_slice_count(); for (size_t i = 0; i < cnt; i++) { - zs.insert(shift_z + double(obj->get_slice_level(i))); + zs.insert(shift_z + obj->get_slice_record(i).key() * SCALING_FACTOR); } } } From db21c67f1869eed13483c56ce0a42bfd9d982056 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 22 Mar 2019 13:03:34 +0100 Subject: [PATCH 06/20] Changed logic for releasing mouse capture into GLToolbar::on_mouse() --- src/slic3r/GUI/GLToolbar.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index ac79784ad..1b6570eab 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -411,24 +411,19 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) // mouse anywhere if (evt.Moving()) + { m_tooltip = update_hover_state(mouse_pos, parent); + if ((m_mouse_capture.parent != nullptr) && (m_mouse_capture.parent != &parent)) + m_mouse_capture.reset(); + } else if (evt.LeftUp()) m_mouse_capture.left = false; else if (evt.MiddleUp()) m_mouse_capture.middle = false; else if (evt.RightUp()) m_mouse_capture.right = false; - else if (m_mouse_capture.any()) - { - if (evt.Dragging()) - processed = true; - else if (evt.Entering() && (m_mouse_capture.parent == &parent)) - // Resets the mouse capture state to avoid setting the dragging event as processed when, for example, - // the item action opens a modal dialog - // Keeps the mouse capture state if the entering event happens on different parent from the one - // who received the button down event, to prevent, for example, dragging when switching between scene views - m_mouse_capture.reset(); - } + else if (evt.Dragging() && m_mouse_capture.any()) + processed = true; int item_id = contains_mouse(mouse_pos, parent); if (item_id == -1) From 6bf0cf946669cba253c9b19db449727d0c003670 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 22 Mar 2019 14:35:26 +0100 Subject: [PATCH 07/20] Another tweak to the logic for releasing mouse capture into GLToolbar::on_mouse() --- src/slic3r/GUI/GLToolbar.cpp | 30 +++++++++++++++++++++++++++--- src/slic3r/GUI/GLToolbar.hpp | 4 ++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index 1b6570eab..1a8539aef 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -157,7 +157,9 @@ GLToolbar::GLToolbar(GLToolbar::EType type) #if ENABLE_SVG_ICONS , m_icons_texture_dirty(true) #endif // ENABLE_SVG_ICONS - , m_mouse_capture({ false, false, false, nullptr }) +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +// , m_mouse_capture({ false, false, false, nullptr }) +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ , m_tooltip("") { } @@ -410,12 +412,27 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) bool processed = false; // mouse anywhere - if (evt.Moving()) +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + if (evt.Moving() || evt.LeftDown() || evt.MiddleDown() || evt.RightDown() || evt.LeftDClick() || evt.RightDClick()) { - m_tooltip = update_hover_state(mouse_pos, parent); if ((m_mouse_capture.parent != nullptr) && (m_mouse_capture.parent != &parent)) + { m_mouse_capture.reset(); + std::cout << "Dragging restored by toolbar" << std::endl; + } } +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + if (evt.Moving()) +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +// { +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + m_tooltip = update_hover_state(mouse_pos, parent); +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +// if ((m_mouse_capture.parent != nullptr) && (m_mouse_capture.parent != &parent)) +// m_mouse_capture.reset(); +// } +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ else if (evt.LeftUp()) m_mouse_capture.left = false; else if (evt.MiddleUp()) @@ -423,7 +440,14 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) else if (evt.RightUp()) m_mouse_capture.right = false; else if (evt.Dragging() && m_mouse_capture.any()) +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + { + std::cout << "Dragging prevented by toolbar" << std::endl; +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ processed = true; +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + } +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ int item_id = contains_mouse(mouse_pos, parent); if (item_id == -1) diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index 95953795f..3d72266c9 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -238,6 +238,10 @@ private: bool right; GLCanvas3D* parent; +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + MouseCapture() { reset(); } +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + bool any() const { return left || middle || right; } void reset() { left = middle = right = false; parent = nullptr; } }; From d165dbb49842a6fd44193318443259dabc0b0ef6 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 22 Mar 2019 15:31:38 +0100 Subject: [PATCH 08/20] Refactoring changes to the slice index. --- src/libslic3r/MTUtils.hpp | 107 +++++++++++++++++ src/libslic3r/SLAPrint.cpp | 206 +++++++++------------------------ src/libslic3r/SLAPrint.hpp | 119 +++++++++++-------- src/slic3r/GUI/GLCanvas3D.cpp | 26 +++-- src/slic3r/GUI/GUI_Preview.cpp | 6 +- 5 files changed, 249 insertions(+), 215 deletions(-) diff --git a/src/libslic3r/MTUtils.hpp b/src/libslic3r/MTUtils.hpp index 1e0fb426a..1f6ca1a23 100644 --- a/src/libslic3r/MTUtils.hpp +++ b/src/libslic3r/MTUtils.hpp @@ -56,6 +56,113 @@ public: } }; +template +class IndexBasedIterator { + static const size_t NONE = size_t(-1); + + std::reference_wrapper m_index_ref; + size_t m_idx = NONE; +public: + + using value_type = Value; + using pointer = Value *; + using reference = Value &; + using difference_type = long; + using iterator_category = std::random_access_iterator_tag; + + inline explicit + IndexBasedIterator(Vector& index, size_t idx): + m_index_ref(index), m_idx(idx) {} + + // Post increment + inline IndexBasedIterator operator++(int) { + IndexBasedIterator cpy(*this); ++m_idx; return cpy; + } + + inline IndexBasedIterator operator--(int) { + IndexBasedIterator cpy(*this); --m_idx; return cpy; + } + + inline IndexBasedIterator& operator++() { + ++m_idx; return *this; + } + + inline IndexBasedIterator& operator--() { + --m_idx; return *this; + } + + inline IndexBasedIterator& operator+=(difference_type l) { + m_idx += size_t(l); return *this; + } + + inline IndexBasedIterator operator+(difference_type l) { + auto cpy = *this; cpy += l; return cpy; + } + + inline IndexBasedIterator& operator-=(difference_type l) { + m_idx -= size_t(l); return *this; + } + + inline IndexBasedIterator operator-(difference_type l) { + auto cpy = *this; cpy -= l; return cpy; + } + + operator difference_type() { return difference_type(m_idx); } + + inline bool is_end() const { return m_idx >= m_index_ref.get().size();} + + inline Value & operator*() const { + assert(m_idx < m_index_ref.get().size()); + return m_index_ref.get().operator[](m_idx); + } + + inline Value * operator->() const { + assert(m_idx < m_index_ref.get().size()); + return &m_index_ref.get().operator[](m_idx); + } + + inline bool operator ==(const IndexBasedIterator& other) { + size_t e = m_index_ref.get().size(); + return m_idx == other.m_idx || (m_idx >= e && other.m_idx >= e); + } + + inline bool operator !=(const IndexBasedIterator& other) { + return !(*this == other); + } + + inline bool operator <=(const IndexBasedIterator& other) { + return (m_idx < other.m_idx) || (*this == other); + } + + inline bool operator <(const IndexBasedIterator& other) { + return m_idx < other.m_idx && (*this != other); + } + + inline bool operator >=(const IndexBasedIterator& other) { + return m_idx > other.m_idx || *this == other; + } + + inline bool operator >(const IndexBasedIterator& other) { + return m_idx > other.m_idx && *this != other; + } +}; + +template class Range { + It from, to; +public: + It begin() const { return from; } + It end() const { return to; } + using Type = It; + + Range() = default; + Range(It &&b, It &&e): + from(std::forward(b)), to(std::forward(e)) {} + + inline size_t size() const { return end() - begin(); } + inline bool empty() const { return size() == 0; } +}; + } #endif // MTUTILS_HPP diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 58386c0bd..4d34b8e7d 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -626,8 +626,8 @@ void SLAPrint::process() double lhd = m_objects.front()->m_config.layer_height.getFloat(); float lh = float(lhd); - LevelID ilhs = ilhd / SCALING_FACTOR; - LevelID lhs = lhd / SCALING_FACTOR; + auto ilhs = LevelID(ilhd / SCALING_FACTOR); + auto lhs = LevelID(lhd / SCALING_FACTOR); const size_t objcount = m_objects.size(); const unsigned min_objstatus = 0; // where the per object operations start @@ -657,17 +657,15 @@ void SLAPrint::process() double minZ = bb3d.min(Z) - po.get_elevation(); double maxZ = bb3d.max(Z); - LevelID minZs = minZ / SCALING_FACTOR; - LevelID maxZs = maxZ / SCALING_FACTOR; - - auto slh = [](float h) { return LevelID( double(h) / SCALING_FACTOR); }; + auto minZs = LevelID(minZ / SCALING_FACTOR); + auto maxZs = LevelID(maxZ / SCALING_FACTOR); po.m_slice_index.clear(); po.m_slice_index.reserve(size_t(maxZs - (minZs + ilhs) / lhs) + 1); - po.m_slice_index.emplace_back(minZs + ilhs, minZ + ilh / 2.f, ilh); + po.m_slice_index.emplace_back(minZs + ilhs, float(minZ) + ilh / 2.f, ilh); for(LevelID h = minZs + ilhs + lhs; h <= maxZs; h += lhs) { - po.m_slice_index.emplace_back(h, h*SCALING_FACTOR - lh / 2.f, lh); + po.m_slice_index.emplace_back(h, float(h*SCALING_FACTOR) - lh / 2.f, lh); } auto slindex_it = po.search_slice_index(float(bb3d.min(Z))); @@ -867,8 +865,10 @@ void SLAPrint::process() // be part of the slices) auto slice_supports = [](SLAPrintObject& po) { auto& sd = po.m_supportdata; + + if(sd) sd->support_slices.clear(); + if(sd && sd->support_tree_ptr) { - sd->support_slices.clear(); std::vector heights; heights.reserve(po.m_slice_index.size()); @@ -891,75 +891,6 @@ void SLAPrint::process() // We have the layer polygon collection but we need to unite them into // an index where the key is the height level in discrete levels (clipper) auto index_slices = [this/*, ilhd*/](SLAPrintObject& /*po*/) { -// po.m_slice_index.clear(); -// auto sih = LevelID(scale_(ilhd)); - -// // Establish the slice grid boundaries -// auto bb = po.transformed_mesh().bounding_box(); -// double modelgnd = bb.min(Z); -// double elevation = po.get_elevation(); -// double lh = po.m_config.layer_height.getFloat(); -// double minZ = modelgnd - elevation; - -// // scaled values: -// auto sminZ = LevelID(scale_(minZ)); -// auto smaxZ = LevelID(scale_(bb.max(Z))); -// auto smodelgnd = LevelID(scale_(modelgnd)); -// auto slh = LevelID(scale_(lh)); - -// // It is important that the next levels match the levels in -// // model_slice method. Only difference is that here it works with -// // scaled coordinates -// po.m_level_ids.clear(); -// for(LevelID h = sminZ + sih; h < smaxZ; h += slh) -// if(h >= smodelgnd) po.m_level_ids.emplace_back(h); - -// std::vector& oslices = po.m_model_slices; - -// // If everything went well this code should not run at all, but -// // let's be robust... -// // assert(levelids.size() == oslices.size()); -// if(po.m_level_ids.size() < oslices.size()) { // extend the levels until... - -// BOOST_LOG_TRIVIAL(warning) -// << "Height level mismatch at rasterization!\n"; - -// LevelID lastlvl = po.m_level_ids.back(); -// while(po.m_level_ids.size() < oslices.size()) { -// lastlvl += slh; -// po.m_level_ids.emplace_back(lastlvl); -// } -// } - -// for(size_t i = 0; i < oslices.size(); ++i) { -// LevelID h = po.m_level_ids[i]; - -// float fh = float(double(h) * SCALING_FACTOR); - -// // now for the public slice index: -// SLAPrintObject::SliceRecord& sr = po.m_slice_index[fh]; -// // There should be only one slice layer for each print object -// assert(sr.model_slices_idx == SLAPrintObject::SliceRecord::NONE); -// sr.model_slices_idx = i; -// } - -// if(po.m_supportdata) { // deal with the support slices if present -// std::vector& sslices = po.m_supportdata->support_slices; -// po.m_supportdata->level_ids.clear(); -// po.m_supportdata->level_ids.reserve(sslices.size()); - -// for(int i = 0; i < int(sslices.size()); ++i) { -// LevelID h = sminZ + sih + i * slh; -// po.m_supportdata->level_ids.emplace_back(h); - -// float fh = float(double(h) * SCALING_FACTOR); - -// SLAPrintObject::SliceRecord& sr = po.m_slice_index[fh]; -// assert(sr.support_slices_idx == SLAPrintObject::SliceRecord::NONE); -// sr.support_slices_idx = SLAPrintObject::SliceRecord::Idx(i); -// } -// } - // Using RELOAD_SLA_PREVIEW to tell the Plater to pass the update status to the 3D preview to load the SLA slices. report_status(*this, -2, "", SlicingStatus::RELOAD_SLA_PREVIEW); }; @@ -975,41 +906,16 @@ void SLAPrint::process() LevelID gndlvl = o->get_slice_index().front().key(); for(auto& slicerecord : o->get_slice_index()) { auto& lyrs = m_printer_input[slicerecord.key() - gndlvl]; - auto objslit = slicerecord.get_slices(*o, soModel); - auto supslit = slicerecord.get_slices(*o, soSupport); - if(objslit != o->get_model_slices().end()) - lyrs.emplace_back(*objslit, o->instances()); + const ExPolygons& objslices = o->get_slices_from_record(slicerecord, soModel); + const ExPolygons& supslices = o->get_slices_from_record(slicerecord, soSupport); - if(supslit != o->get_support_slices().end()) - lyrs.emplace_back(*supslit, o->instances()); + if(!objslices.empty()) + lyrs.emplace_back(objslices, o->instances()); + + if(!supslices.empty()) + lyrs.emplace_back(supslices, o->instances()); } - -// auto& po = *o; -// std::vector& oslices = po.m_model_slices; - -// // We need to adjust the min Z level of the slices to be zero -// LevelID smfirst = -// po.m_supportdata && !po.m_supportdata->level_ids.empty() ? -// po.m_supportdata->level_ids.front() : 0; -// LevelID mfirst = po.m_level_ids.empty()? 0 : po.m_level_ids.front(); -// LevelID gndlvl = -(std::min(smfirst, mfirst)); - -// // now merge this object's support and object slices with the rest -// // of the print object slices - -// for(size_t i = 0; i < oslices.size(); ++i) { -// auto& lyrs = m_printer_input[gndlvl + po.m_level_ids[i]]; -// lyrs.emplace_back(oslices[i], po.m_instances); -// } - -// if(!po.m_supportdata) continue; -// std::vector& sslices = po.m_supportdata->support_slices; -// for(size_t i = 0; i < sslices.size(); ++i) { -// LayerRefs& lyrs = -// m_printer_input[gndlvl + po.m_supportdata->level_ids[i]]; -// lyrs.emplace_back(sslices[i], po.m_instances); -// } } // collect all the keys @@ -1355,13 +1261,13 @@ void SLAPrint::fill_statistics() record = &(*it); } - auto modelslice_it = record->get_slices(*po, soModel); - if (modelslice_it != po->get_model_slices().end()) - append(model_polygons, get_all_polygons(*modelslice_it, po->instances())); - - auto supportslice_it = record->get_slices(*po, soSupport); - if (supportslice_it != po->get_support_slices().end()) - append(supports_polygons, get_all_polygons(*supportslice_it, po->instances())); + const ExPolygons &modelslices = po->get_slices_from_record(*record, soModel); + if (!modelslices.empty()) + append(model_polygons, get_all_polygons(modelslices, po->instances())); + + const ExPolygons &supportslices = po->get_slices_from_record(*record, soSupport); + if (!supportslices.empty()) + append(supports_polygons, get_all_polygons(supportslices, po->instances())); } model_polygons = union_(model_polygons); @@ -1561,6 +1467,7 @@ double SLAPrintObject::get_current_elevation() const namespace { // dummy empty static containers for return values in some methods const std::vector EMPTY_SLICES; const TriangleMesh EMPTY_MESH; +const ExPolygons EMPTY_SLICE; } const std::vector& SLAPrintObject::get_support_points() const @@ -1597,7 +1504,8 @@ SLAPrintObject::search_slice_index(float slice_level) const } SLAPrintObject::SliceIndex::iterator -SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) +SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key, + bool exact) { _SliceRecord query(key, 0.f, 0.f); auto it = std::lower_bound(m_slice_index.begin(), m_slice_index.end(), @@ -1608,13 +1516,15 @@ SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) }); // Return valid iterator only if the keys really match - if(it != m_slice_index.end() && it->key() != key) it = m_slice_index.end(); + if(exact && it != m_slice_index.end() && it->key() != key) + it = m_slice_index.end(); return it; } SLAPrintObject::SliceIndex::const_iterator -SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) const +SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key, + bool exact) const { _SliceRecord query(key, 0.f, 0.f); auto it = std::lower_bound(m_slice_index.cbegin(), m_slice_index.cend(), @@ -1625,28 +1535,12 @@ SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) const }); // Return valid iterator only if the keys really match - if(it != m_slice_index.end() && it->key() != key) it = m_slice_index.end(); + if(exact && it != m_slice_index.end() && it->key() != key) + it = m_slice_index.end(); return it; } -SliceRange SLAPrintObject::get_slices(SliceOrigin so, - float from_level, - float to_level) const -{ - auto it_from = search_slice_index(from_level); - auto it_to = search_slice_index(to_level); - - SliceRange ret; - - auto endit = so == soModel? get_model_slices().end() : get_support_slices().end(); - - ret.from = it_from == m_slice_index.end() ? endit : it_from->get_slices(*this, so); - ret.to = it_to == m_slice_index.end() ? endit : it_to->get_slices(*this, so); - - return ret; -} - const std::vector &SLAPrintObject::get_support_slices() const { // assert(is_step_done(slaposSliceSupports)); @@ -1654,6 +1548,28 @@ const std::vector &SLAPrintObject::get_support_slices() const return m_supportdata->support_slices; } +const ExPolygons &SLAPrintObject::get_slices_from_record( + const _SliceRecord &rec, + SliceOrigin o) const +{ + size_t idx = o == soModel ? rec.get_model_slice_idx() : + rec.get_support_slice_idx(); + + const std::vector& v = o == soModel? get_model_slices() : + get_support_slices(); + + if(idx >= v.size()) return EMPTY_SLICE; + + return idx >= v.size() ? EMPTY_SLICE : v[idx]; +} + +const ExPolygons &SLAPrintObject::get_slices_from_record( + SLAPrintObject::SliceRecordConstIterator it, SliceOrigin o) const +{ + if(it.is_end()) return EMPTY_SLICE; + return get_slices_from_record(*it, o); +} + const std::vector& SLAPrintObject::get_slice_index() const { @@ -1778,18 +1694,4 @@ std::string SLAPrintStatistics::finalize_output_path(const std::string &path_in) return final_path; } -SliceIterator SLAPrintObject::_SliceRecord::get_slices(const SLAPrintObject &po, - SliceOrigin so) const -{ - - const std::vector& v = so == soModel? po.get_model_slices() : - po.get_support_slices(); - - size_t idx = so == soModel ? m_model_slices_idx : m_support_slices_idx; - - using DiffT = std::vector::const_iterator::difference_type; - - return idx == NONE? v.end() : v.begin() + DiffT(idx); -} - } // namespace Slic3r diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index b33bfdeb0..ff715fb5e 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -6,6 +6,7 @@ #include "PrintExport.hpp" #include "Point.hpp" #include "MTUtils.hpp" +#include namespace Slic3r { @@ -35,23 +36,8 @@ using _SLAPrintObjectBase = // the printer (rasterizer) in the SLAPrint class. using LevelID = long long; -template struct Range { - It from, to; - It begin() const { return from; } - It end() const { return to; } - using Type = It; - - Range() = default; - explicit Range(It &&b, It &&e): - from(std::forward(b)), to(std::forward(e)) {} -}; - enum SliceOrigin { soSupport, soModel }; -using SliceStore = std::vector; -using SliceIterator = SliceStore::const_iterator; -using SliceRange = Range; - class SLAPrintObject : public _SLAPrintObjectBase { private: // Prevents erroneous use by other classes. @@ -107,12 +93,14 @@ public: // This method returns the support points of this SLAPrintObject. const std::vector& get_support_points() const; + // The public Slice record structure. It corresponds to one printable layer. + // To get the sliced polygons, use SLAPrintObject::get_slices_from_record class SliceRecord { public: using Key = LevelID; private: - LevelID m_print_z = 0; // Top of the layer + Key m_print_z = 0; // Top of the layer float m_slice_z = 0.f; // Exact level of the slice float m_height = 0.f; // Height of the sliced layer @@ -139,8 +127,9 @@ private: // levels of the model in scaled-clipper coordinates. The levels correspond // to the z coordinate of the object coordinate system. class _SliceRecord: public SliceRecord { - private: + public: static const size_t NONE = size_t(-1); // this will be the max limit of size_t + private: size_t m_model_slices_idx = NONE; size_t m_support_slices_idx = NONE; @@ -148,14 +137,12 @@ private: _SliceRecord(Key key, float slicez, float height): SliceRecord(key, slicez, height) {} - // Returns the slices for either the model or the supports. The return - // value is an iterator to po.get_model_slices() or po.get_support_slices - // depending on the SliceOrigin parameter. - SliceIterator get_slices(const SLAPrintObject& po, SliceOrigin so) const; - - // Methods for setting the indixes into the slice vectors. + // Methods for setting the indices into the slice vectors. void set_model_slice_idx(size_t id) { m_model_slices_idx = id; } void set_support_slice_idx(size_t id) { m_support_slices_idx = id; } + + inline size_t get_model_slice_idx() const { return m_model_slices_idx; } + inline size_t get_support_slice_idx() const { return m_support_slices_idx; } }; // Slice index will be a plain vector sorted by the integer height levels @@ -171,37 +158,78 @@ private: // Search the slice index for a particular level in integer coordinates. // If no such layer is present, it will return m_slice_index.end() - SliceIndex::iterator search_slice_index(_SliceRecord::Key key); - SliceIndex::const_iterator search_slice_index(_SliceRecord::Key key) const; + // This behavior can be suppressed by the second parameter. If it is true + // the method will return the closest (non-equal) record + SliceIndex::iterator search_slice_index(_SliceRecord::Key key, bool exact = false); + SliceIndex::const_iterator search_slice_index(_SliceRecord::Key key, bool = false) const; + + const std::vector& get_model_slices() const; + const std::vector& get_support_slices() const; public: - // ///////////////////////////////////////////////////////////////////////// - // The following methods can be used after the model and the support slicing - // steps have been succesfully finished. - // ///////////////////////////////////////////////////////////////////////// - - // Getting slices (model or supports) for a Z coordinate range. The returned - // iterators should include the slices for the given boundaries as well. - SliceRange get_slices( - SliceOrigin so, - float from_level, - float to_level = std::numeric_limits::infinity()) const; + // Should work as a polymorphic bidirectional iterator to the slice records + using SliceRecordConstIterator = + IndexBasedIterator; + // ///////////////////////////////////////////////////////////////////////// + // // These two methods should be callable on the client side (e.g. UI thread) // when the appropriate steps slaposObjectSlice and slaposSliceSupports // are ready. All the print objects are processed before slapsRasterize so // it is safe to call them during and/or after slapsRasterize. - const std::vector& get_model_slices() const; - const std::vector& get_support_slices() const; + // + // ///////////////////////////////////////////////////////////////////////// - // Returns the total number of slices in the slice grid (model and supports) - inline size_t get_slice_count() const { return m_slice_index.size(); } + // Get the slice records from a range of slice levels (inclusive). Floating + // point keys are the levels where the model was sliced with the mesh + // slicer. Integral keys are the keys of the slice records, which + // correspond to the top of each layer.. The end() method of the returned + // range points *after* the last valid element. This is for being + // consistent with std and makeing range based for loops work. use + // std::prev(range.end()) or --range.end() to get the last element. + template Range + get_slice_records(Key from, Key to = std::numeric_limits::max()) const + { + SliceIndex::const_iterator it_from, it_to; + if(std::is_integral::value) { + it_from = search_slice_index(SliceRecord::Key(from)); + it_to = search_slice_index(SliceRecord::Key(to)); + } else if(std::is_floating_point::value) { + it_from = search_slice_index(float(from)); + it_to = search_slice_index(float(to)); + } else return { + SliceRecordConstIterator(m_slice_index, _SliceRecord::NONE ), + SliceRecordConstIterator(m_slice_index, _SliceRecord::NONE ), + }; - inline const SliceRecord& get_slice_record(size_t idx) const { - return m_slice_index[idx]; + auto start = m_slice_index.begin(); + + size_t bidx = it_from == m_slice_index.end() ? _SliceRecord::NONE : + size_t(it_from - start); + + size_t eidx = it_to == m_slice_index.end() ? _SliceRecord::NONE : + size_t(it_to - start) + 1; + + return { + SliceRecordConstIterator(m_slice_index, bidx), + SliceRecordConstIterator(m_slice_index, eidx), + }; } + // Get all the slice records as a range. + inline Range get_slice_records() const { + return { + SliceRecordConstIterator(m_slice_index, 0), + SliceRecordConstIterator(m_slice_index, m_slice_index.size()) + }; + } + + const ExPolygons& get_slices_from_record(SliceRecordConstIterator it, + SliceOrigin o) const; + + const ExPolygons& get_slices_from_record(const _SliceRecord& rec, + SliceOrigin o) const; protected: // to be called from SLAPrint only. friend class SLAPrint; @@ -242,7 +270,7 @@ private: // Exact (float) height levels mapped to the slices. Each record contains // the index to the model and the support slice vectors. - std::vector<_SliceRecord> m_slice_index; + std::vector<_SliceRecord> m_slice_index; std::vector m_model_height_levels; @@ -335,11 +363,6 @@ private: // Invalidate steps based on a set of parameters changed. bool invalidate_state_by_config_options(const std::vector &opt_keys); - std::vector calculate_heights(const BoundingBoxf3& bb, - float elevation, - float initial_layer_height, - float layer_height) const; - void fill_statistics(); SLAPrintConfig m_print_config; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 0f1e15b76..8acb5ad53 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -5014,26 +5014,28 @@ void GLCanvas3D::_render_sla_slices() const if ((bottom_obj_triangles.empty() || bottom_sup_triangles.empty() || top_obj_triangles.empty() || top_sup_triangles.empty()) && obj->is_step_done(slaposIndexSlices)) { // FIXME: is this all right (by Tamas)? - SliceRange obj_range = obj->get_slices(soModel, float(min_z), float(max_z)); - SliceRange sup_range = obj->get_slices(soSupport, float(min_z), float(max_z)); - auto obj_end = obj->get_model_slices().end(); - auto sup_end = obj->get_support_slices().end(); + auto slice_range = obj->get_slice_records(coord_t(min_z / SCALING_FACTOR), + coord_t(max_z / SCALING_FACTOR)); + const ExPolygons& obj_bottom = obj->get_slices_from_record(slice_range.begin(), soModel); + const ExPolygons& obj_top = obj->get_slices_from_record(std::prev(slice_range.end()), soModel); + const ExPolygons& sup_bottom = obj->get_slices_from_record(slice_range.begin(), soSupport); + const ExPolygons& sup_top = obj->get_slices_from_record(std::prev(slice_range.end()), soSupport); // calculate model bottom cap - if(bottom_obj_triangles.empty() && obj_range.from != obj_end) - bottom_obj_triangles = triangulate_expolygons_3d(*obj_range.from, min_z, true); + if(bottom_obj_triangles.empty() && !obj_bottom.empty()) + bottom_obj_triangles = triangulate_expolygons_3d(obj_bottom, min_z, true); // calculate support bottom cap - if(bottom_sup_triangles.empty() && sup_range.from != sup_end) - bottom_sup_triangles = triangulate_expolygons_3d(*sup_range.from, min_z, true); + if(bottom_sup_triangles.empty() && !sup_bottom.empty()) + bottom_sup_triangles = triangulate_expolygons_3d(sup_bottom, min_z, true); // calculate model top cap - if(top_obj_triangles.empty() && obj_range.to != obj_end) - top_obj_triangles = triangulate_expolygons_3d(*obj_range.to, max_z, false); + if(top_obj_triangles.empty() && !obj_top.empty()) + top_obj_triangles = triangulate_expolygons_3d(obj_top, max_z, false); // calculate support top cap - if(top_sup_triangles.empty() && sup_range.to != sup_end) - top_sup_triangles = triangulate_expolygons_3d(*sup_range.to, max_z, false); + if(top_sup_triangles.empty() && !sup_top.empty()) + top_sup_triangles = triangulate_expolygons_3d(sup_top, max_z, false); // const std::vector& model_slices = obj->get_model_slices(); // const std::vector& support_slices = obj->get_support_slices(); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 10a4a12c7..5edca6c96 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -775,10 +775,10 @@ void Preview::load_print_as_sla() double shift_z = obj->get_current_elevation(); if (obj->is_step_done(slaposIndexSlices)) { - size_t cnt = obj->get_slice_count(); - for (size_t i = 0; i < cnt; i++) + auto slicerecords = obj->get_slice_records(); + for (auto& rec : slicerecords) { - zs.insert(shift_z + obj->get_slice_record(i).key() * SCALING_FACTOR); + zs.insert(shift_z + /*rec.slice_level()*/ rec.key() * SCALING_FACTOR); } } } From 8e18605bd720f895cc6f0088b1dd27c49dd4fb69 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 22 Mar 2019 15:48:20 +0100 Subject: [PATCH 09/20] Fix for incorrect model slices after elevation has changed. --- src/libslic3r/SLAPrint.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 4d34b8e7d..79834908f 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -1363,11 +1363,15 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector Date: Fri, 22 Mar 2019 21:26:58 +0100 Subject: [PATCH 10/20] 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 ff715fb5e..fbe2821b2 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 0018ae1cc..8be187dec 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 5edca6c96..2361ff6d3 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/20] 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 3781cbf45..db9af7cce 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/20] 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 ee795f2b9..ac1171e18 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/20] 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 026b62ab5..9cd933160 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 db9af7cce..dbfdb8e6c 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/20] 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 a2ab8c3f1..f9c598ce3 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 3da4c1871..82223b15c 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 9f4261372..f78a04126 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(); } From 3f7f8f978eb6b08e27454c2c090f28dcb4c00a96 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Sun, 24 Mar 2019 13:35:09 +0100 Subject: [PATCH 15/20] Fix of sla gizmo (it sometimes showed supports for hidden objects) --- src/slic3r/GUI/GLCanvas3D.cpp | 10 ++++++---- src/slic3r/GUI/GLCanvas3D.hpp | 5 ++++- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 8be187dec..3192e7861 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2293,11 +2293,13 @@ int GLCanvas3D::check_volumes_outside_state() const return (int)state; } -void GLCanvas3D::toggle_sla_auxiliaries_visibility(bool visible) +void GLCanvas3D::toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo, int instance_idx) { for (GLVolume* vol : m_volumes.volumes) { - if (vol->composite_id.volume_id < 0) - vol->is_active = visible; + if ((mo == nullptr || m_model->objects[vol->composite_id.object_id] == mo) + && (instance_idx == -1 || vol->composite_id.instance_id == instance_idx) + && vol->composite_id.volume_id < 0) + vol->is_active = visible; } m_render_sla_auxiliaries = visible; @@ -2313,7 +2315,7 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject } } if (visible && !mo) - toggle_sla_auxiliaries_visibility(true); + toggle_sla_auxiliaries_visibility(true, mo, instance_idx); if (!mo && !visible && !m_model->objects.empty() && (m_model->objects.size() > 1 || m_model->objects.front()->instances.size() > 1)) _set_warning_texture(WarningTexture::SomethingNotShown, true); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index d9e38c4e0..29e0fbb08 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -584,6 +584,9 @@ private: bool m_regenerate_volumes; bool m_moving; bool m_tab_down; + + // Following variable is obsolete and it should be safe to remove it. + // I just don't want to do it now before a release (Lukas Matena 24.3.2019) bool m_render_sla_auxiliaries; std::string m_color_by; @@ -610,7 +613,7 @@ public: void reset_volumes(); int check_volumes_outside_state() const; - void toggle_sla_auxiliaries_visibility(bool visible); + void toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1); void toggle_model_objects_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1); void set_config(const DynamicPrintConfig* config); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index c629f2172..31f6b0278 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -666,7 +666,7 @@ RENDER_AGAIN: m_imgui->end(); if (m_editing_mode != m_old_editing_state) { // user toggled between editing/non-editing mode - m_parent.toggle_sla_auxiliaries_visibility(!m_editing_mode); + m_parent.toggle_sla_auxiliaries_visibility(!m_editing_mode, m_model_object, m_active_instance); force_refresh = true; } m_old_editing_state = m_editing_mode; From dd3ac4017a3001da6ab01d2b9ce54f42d0891b99 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 25 Mar 2019 08:48:41 +0100 Subject: [PATCH 16/20] Yet another tweak to the logic for releasing mouse capture into GLToolbar::on_mouse() --- src/slic3r/GUI/GLToolbar.cpp | 59 ++++++++++++++++++++++++++++++++---- src/slic3r/GUI/GLToolbar.hpp | 2 +- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index 1a8539aef..00596a9cc 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -413,14 +413,60 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) // mouse anywhere //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ - if (evt.Moving() || evt.LeftDown() || evt.MiddleDown() || evt.RightDown() || evt.LeftDClick() || evt.RightDClick()) + if (!evt.Dragging() && !evt.Leaving() && !evt.Entering() && (m_mouse_capture.parent != nullptr)) { - if ((m_mouse_capture.parent != nullptr) && (m_mouse_capture.parent != &parent)) - { - m_mouse_capture.reset(); - std::cout << "Dragging restored by toolbar" << std::endl; - } + if (m_mouse_capture.any() && (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())) + // prevents loosing selection into the scene if mouse down was done inside the toolbar and mouse up was down outside it, + // as when switching between views + processed = true; + + m_mouse_capture.reset(); + + + std::cout << "Dragging restored by toolbar ["; + if (evt.Entering()) + std::cout << "Entering"; + else if (evt.Leaving()) + std::cout << "Leaving"; + else if (evt.Dragging()) + std::cout << "Dragging"; + else if (evt.Moving()) + std::cout << "Moving"; + else if (evt.Magnify()) + std::cout << "Magnify"; + else if (evt.LeftDown()) + std::cout << "LeftDown"; + else if (evt.LeftUp()) + std::cout << "LeftUp"; + else if (evt.LeftDClick()) + std::cout << "LeftDClick"; + else if (evt.MiddleDown()) + std::cout << "MiddleDown"; + else if (evt.MiddleUp()) + std::cout << "MiddleUp"; + else if (evt.MiddleDClick()) + std::cout << "MiddleDClick"; + else if (evt.RightDown()) + std::cout << "RightDown"; + else if (evt.RightUp()) + std::cout << "RightUp"; + else if (evt.RightDClick()) + std::cout << "RightDClick"; + else + std::cout << "UNKNOWN "; + std::cout << "]" << std::endl; } + + +// if (evt.Moving() || evt.LeftDown() || evt.MiddleDown() || evt.RightDown() || evt.LeftDClick() || evt.RightDClick()) +// { +// std::cout << m_name << " - " << (void*)m_mouse_capture.parent << std::endl; +// if ((m_mouse_capture.parent != nullptr) && (m_mouse_capture.parent != &parent)) +// { +// m_mouse_capture.reset(); +// std::cout << "Dragging restored by toolbar" << std::endl; +// } +// } //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ if (evt.Moving()) @@ -444,6 +490,7 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) { std::cout << "Dragging prevented by toolbar" << std::endl; //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + // if the button down was done on this toolbar, prevent from dragging into the scene processed = true; //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ } diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index 3d72266c9..a0c0d9ca7 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -239,7 +239,7 @@ private: GLCanvas3D* parent; //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ - MouseCapture() { reset(); } + MouseCapture() { reset(); } //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ bool any() const { return left || middle || right; } From 149551946ca2f6f932d7e9f1f0ba461b956615cb Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 25 Mar 2019 12:07:43 +0100 Subject: [PATCH 17/20] Fix of #1998 --- src/libslic3r/Format/AMF.cpp | 11 ++++++----- src/slic3r/GUI/Plater.cpp | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index f5219263d..ff1da37cc 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -175,6 +175,11 @@ struct AMFParserContext bool mirrory_set; float mirrorz; bool mirrorz_set; + + bool anything_set() const { return deltax_set || deltay_set || deltaz_set || + rx_set || ry_set || rz_set || + scalex_set || scaley_set || scalez_set || + mirrorx_set || mirrory_set || mirrorz_set; } }; struct Object { @@ -644,11 +649,7 @@ void AMFParserContext::endDocument() continue; } for (const Instance &instance : object.second.instances) -#if ENABLE_VOLUMES_CENTERING_FIXES - { -#else - if (instance.deltax_set && instance.deltay_set) { -#endif // ENABLE_VOLUMES_CENTERING_FIXES + if (instance.anything_set()) { ModelInstance *mi = m_model.objects[object.second.idx]->add_instance(); mi->set_offset(Vec3d(instance.deltax_set ? (double)instance.deltax : 0.0, instance.deltay_set ? (double)instance.deltay : 0.0, instance.deltaz_set ? (double)instance.deltaz : 0.0)); mi->set_rotation(Vec3d(instance.rx_set ? (double)instance.rx : 0.0, instance.ry_set ? (double)instance.ry : 0.0, instance.rz_set ? (double)instance.rz : 0.0)); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f9c598ce3..e15882125 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1713,8 +1713,8 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode object->center_around_origin(); new_instances.emplace_back(object->add_instance()); #else /* AUTOPLACEMENT_ON_LOAD */ - // if object has no defined position(s) we need to rearrange everything after loading object->center_around_origin(); - need_arrange = true; + // if object has no defined position(s) we need to rearrange everything after loading + need_arrange = true; // add a default instance and center object around origin object->center_around_origin(); // also aligns object to Z = 0 ModelInstance* instance = object->add_instance(); From 3e0ec8098bce46673c4b0325b85825008ead9d03 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 25 Mar 2019 14:13:20 +0100 Subject: [PATCH 18/20] Code cleanup --- src/slic3r/GUI/GLToolbar.cpp | 65 ------------------------------------ src/slic3r/GUI/GLToolbar.hpp | 2 -- 2 files changed, 67 deletions(-) diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index 00596a9cc..2f7f13f6f 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -157,9 +157,6 @@ GLToolbar::GLToolbar(GLToolbar::EType type) #if ENABLE_SVG_ICONS , m_icons_texture_dirty(true) #endif // ENABLE_SVG_ICONS -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -// , m_mouse_capture({ false, false, false, nullptr }) -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ , m_tooltip("") { } @@ -412,7 +409,6 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) bool processed = false; // mouse anywhere -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ if (!evt.Dragging() && !evt.Leaving() && !evt.Entering() && (m_mouse_capture.parent != nullptr)) { if (m_mouse_capture.any() && (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())) @@ -421,64 +417,10 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) processed = true; m_mouse_capture.reset(); - - - std::cout << "Dragging restored by toolbar ["; - if (evt.Entering()) - std::cout << "Entering"; - else if (evt.Leaving()) - std::cout << "Leaving"; - else if (evt.Dragging()) - std::cout << "Dragging"; - else if (evt.Moving()) - std::cout << "Moving"; - else if (evt.Magnify()) - std::cout << "Magnify"; - else if (evt.LeftDown()) - std::cout << "LeftDown"; - else if (evt.LeftUp()) - std::cout << "LeftUp"; - else if (evt.LeftDClick()) - std::cout << "LeftDClick"; - else if (evt.MiddleDown()) - std::cout << "MiddleDown"; - else if (evt.MiddleUp()) - std::cout << "MiddleUp"; - else if (evt.MiddleDClick()) - std::cout << "MiddleDClick"; - else if (evt.RightDown()) - std::cout << "RightDown"; - else if (evt.RightUp()) - std::cout << "RightUp"; - else if (evt.RightDClick()) - std::cout << "RightDClick"; - else - std::cout << "UNKNOWN "; - std::cout << "]" << std::endl; } - -// if (evt.Moving() || evt.LeftDown() || evt.MiddleDown() || evt.RightDown() || evt.LeftDClick() || evt.RightDClick()) -// { -// std::cout << m_name << " - " << (void*)m_mouse_capture.parent << std::endl; -// if ((m_mouse_capture.parent != nullptr) && (m_mouse_capture.parent != &parent)) -// { -// m_mouse_capture.reset(); -// std::cout << "Dragging restored by toolbar" << std::endl; -// } -// } -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ - if (evt.Moving()) -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -// { -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ m_tooltip = update_hover_state(mouse_pos, parent); -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -// if ((m_mouse_capture.parent != nullptr) && (m_mouse_capture.parent != &parent)) -// m_mouse_capture.reset(); -// } -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ else if (evt.LeftUp()) m_mouse_capture.left = false; else if (evt.MiddleUp()) @@ -486,15 +428,8 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) else if (evt.RightUp()) m_mouse_capture.right = false; else if (evt.Dragging() && m_mouse_capture.any()) -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ - { - std::cout << "Dragging prevented by toolbar" << std::endl; -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // if the button down was done on this toolbar, prevent from dragging into the scene processed = true; -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ - } -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ int item_id = contains_mouse(mouse_pos, parent); if (item_id == -1) diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index a0c0d9ca7..5fac1f5b2 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -238,9 +238,7 @@ private: bool right; GLCanvas3D* parent; -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ MouseCapture() { reset(); } -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ bool any() const { return left || middle || right; } void reset() { left = middle = right = false; parent = nullptr; } From aca2ffcdfbefecf00437d89a965d1ccdade567e6 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Mon, 25 Mar 2019 15:06:29 +0100 Subject: [PATCH 19/20] doc: Warn about build dir being too nested on Windows --- doc/How to build - Windows.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/How to build - Windows.md b/doc/How to build - Windows.md index 627f1c99b..020b28958 100644 --- a/doc/How to build - Windows.md +++ b/doc/How to build - Windows.md @@ -91,6 +91,10 @@ You can also use the Visual Studio GUI or other generators as mentioned above. The `DESTDIR` option is the location where the bundle will be installed. This may be customized. If you leave it empty, the `DESTDIR` will be places inside the same `build` directory. +Warning: If the `build` directory is nested too deep inside other folders, various file paths during the build +become too long and the build might fail due to file writing errors. For this reason, it is recommended to +place the `build` directory relatively close to the drive root. + Note that the build variant that you may choose using Visual Studio (i.e. _Release_ or _Debug_ etc.) when building the dependency package is **not relevant**. The dependency build will by default build _both_ the _Release_ and _Debug_ variants regardless of what you choose in Visual Studio. You can disable building of the debug variant by passing the `-DDEP_DEBUG=OFF` option to CMake, this will only produce a _Release_ build. From ba66f34c4572beae3600a8557f89435ceaac2f5f Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Mon, 25 Mar 2019 15:50:07 +0100 Subject: [PATCH 20/20] Build: Add an option to choose GTK version on Linux, fix #1937 --- CMakeLists.txt | 2 ++ src/CMakeLists.txt | 1 + 2 files changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 90ebd1e5b..1e6cf45bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,8 @@ option(SLIC3R_PERL_XS "Compile XS Perl module and enable Perl unit and option(SLIC3R_ASAN "Enable ASan on Clang and GCC" 0) option(SLIC3R_SYNTAXONLY "Only perform source code correctness checking, no binary output (UNIX only)" 0) +set(SLIC3R_GTK "2" CACHE STRING "GTK version to use with wxWidgets on Linux") + # Proposal for C++ unit tests and sandboxes option(SLIC3R_BUILD_SANDBOXES "Build development sandboxes" OFF) option(SLIC3R_BUILD_TESTS "Build unit tests" OFF) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aae3436ae..a6ae94391 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -60,6 +60,7 @@ if (SLIC3R_GUI) endif() if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + set (wxWidgets_CONFIG_OPTIONS "--toolkit=gtk${SLIC3R_GTK}") if (SLIC3R_WX_STABLE) find_package(wxWidgets 3.0 REQUIRED COMPONENTS base core adv html gl) else ()