From 4628ba5767a1fbb14547ab03f50827dd0657d298 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Tue, 22 Jan 2019 17:50:33 +0100 Subject: [PATCH 01/23] Initial version of smart auto placement intended to replace autocenter. --- src/libnest2d/CMakeLists.txt | 7 +- .../libnest2d/backends/clipper/CMakeLists.txt | 6 +- .../include/libnest2d/geometry_traits_nfp.hpp | 454 ++++++++++++++++++ src/libnest2d/include/libnest2d/libnest2d.hpp | 147 +++--- .../libnest2d/optimizers/nlopt/CMakeLists.txt | 12 +- .../include/libnest2d/placers/nfpplacer.hpp | 65 ++- .../libnest2d/placers/placer_boilerplate.hpp | 10 +- .../libnest2d/selections/djd_heuristic.hpp | 4 +- .../include/libnest2d/selections/filler.hpp | 4 + .../include/libnest2d/selections/firstfit.hpp | 10 +- .../selections/selection_boilerplate.hpp | 22 +- src/libslic3r/ModelArrange.cpp | 135 +++++- src/libslic3r/ModelArrange.hpp | 10 +- src/slic3r/GUI/Plater.cpp | 29 +- 14 files changed, 793 insertions(+), 122 deletions(-) diff --git a/src/libnest2d/CMakeLists.txt b/src/libnest2d/CMakeLists.txt index 1faf542dd..7853a48d5 100644 --- a/src/libnest2d/CMakeLists.txt +++ b/src/libnest2d/CMakeLists.txt @@ -70,7 +70,10 @@ if(TBB_FOUND) # The Intel TBB library will use the std::exception_ptr feature of C++11. target_compile_definitions(libnest2d INTERFACE -DTBB_USE_CAPTURED_EXCEPTION=0) - target_link_libraries(libnest2d INTERFACE tbb) + find_package(Threads REQUIRED) + target_link_libraries(libnest2d INTERFACE ${TBB_LIBRARIES} ${CMAKE_DL_LIBS} + Threads::Threads + ) else() find_package(OpenMP QUIET) @@ -88,7 +91,7 @@ endif() add_subdirectory(${SRC_DIR}/libnest2d/backends/${LIBNEST2D_GEOMETRIES}) add_subdirectory(${SRC_DIR}/libnest2d/optimizers/${LIBNEST2D_OPTIMIZER}) -#target_sources(libnest2d INTERFACE ${LIBNEST2D_SRCFILES}) +target_sources(libnest2d INTERFACE ${LIBNEST2D_SRCFILES}) target_include_directories(libnest2d INTERFACE ${SRC_DIR}) if(NOT LIBNEST2D_HEADER_ONLY) diff --git a/src/libnest2d/include/libnest2d/backends/clipper/CMakeLists.txt b/src/libnest2d/include/libnest2d/backends/clipper/CMakeLists.txt index aa53f957e..995afcc76 100644 --- a/src/libnest2d/include/libnest2d/backends/clipper/CMakeLists.txt +++ b/src/libnest2d/include/libnest2d/backends/clipper/CMakeLists.txt @@ -62,9 +62,9 @@ if(NOT Boost_INCLUDE_DIRS_FOUND) endif() target_include_directories(ClipperBackend INTERFACE ${Boost_INCLUDE_DIRS} ) -#target_sources(ClipperBackend INTERFACE -# ${CMAKE_CURRENT_SOURCE_DIR}/geometries.hpp -# ${SRC_DIR}/libnest2d/utils/boost_alg.hpp ) +target_sources(ClipperBackend INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}/geometries.hpp + ${SRC_DIR}/libnest2d/utils/boost_alg.hpp ) target_compile_definitions(ClipperBackend INTERFACE LIBNEST2D_BACKEND_CLIPPER) diff --git a/src/libnest2d/include/libnest2d/geometry_traits_nfp.hpp b/src/libnest2d/include/libnest2d/geometry_traits_nfp.hpp index b57b8dc53..cb0580ef4 100644 --- a/src/libnest2d/include/libnest2d/geometry_traits_nfp.hpp +++ b/src/libnest2d/include/libnest2d/geometry_traits_nfp.hpp @@ -251,6 +251,460 @@ inline NfpResult nfpConvexOnly(const RawShape& sh, return {rsh, top_nfp}; } +template +NfpResult nfpSimpleSimple(const RawShape& cstationary, + const RawShape& cother) +{ + + // Algorithms are from the original algorithm proposed in paper: + // https://eprints.soton.ac.uk/36850/1/CORMSIS-05-05.pdf + + // ///////////////////////////////////////////////////////////////////////// + // Algorithm 1: Obtaining the minkowski sum + // ///////////////////////////////////////////////////////////////////////// + + // I guess this is not a full minkowski sum of the two input polygons by + // definition. This yields a subset that is compatible with the next 2 + // algorithms. + + using Result = NfpResult; + using Vertex = TPoint; + using Coord = TCoord; + using Edge = _Segment; + namespace sl = shapelike; + using std::signbit; + using std::sort; + using std::vector; + using std::ref; + using std::reference_wrapper; + + // TODO The original algorithms expects the stationary polygon in + // counter clockwise and the orbiter in clockwise order. + // So for preventing any further complication, I will make the input + // the way it should be, than make my way around the orientations. + + // Reverse the stationary contour to counter clockwise + auto stcont = sl::contour(cstationary); + { + std::reverse(sl::begin(stcont), sl::end(stcont)); + stcont.pop_back(); + auto it = std::min_element(sl::begin(stcont), sl::end(stcont), + [](const Vertex& v1, const Vertex& v2) { + return getY(v1) < getY(v2); + }); + std::rotate(sl::begin(stcont), it, sl::end(stcont)); + sl::addVertex(stcont, sl::front(stcont)); + } + RawShape stationary; + sl::contour(stationary) = stcont; + + // Reverse the orbiter contour to counter clockwise + auto orbcont = sl::contour(cother); + { + std::reverse(orbcont.begin(), orbcont.end()); + + // Step 1: Make the orbiter reverse oriented + + orbcont.pop_back(); + auto it = std::min_element(orbcont.begin(), orbcont.end(), + [](const Vertex& v1, const Vertex& v2) { + return getY(v1) < getY(v2); + }); + + std::rotate(orbcont.begin(), it, orbcont.end()); + orbcont.emplace_back(orbcont.front()); + + for(auto &v : orbcont) v = -v; + + } + + // Copy the orbiter (contour only), we will have to work on it + RawShape orbiter; + sl::contour(orbiter) = orbcont; + + // An edge with additional data for marking it + struct MarkedEdge { + Edge e; Radians turn_angle = 0; bool is_turning_point = false; + MarkedEdge() = default; + MarkedEdge(const Edge& ed, Radians ta, bool tp): + e(ed), turn_angle(ta), is_turning_point(tp) {} + + // debug + std::string label; + }; + + // Container for marked edges + using EdgeList = vector; + + EdgeList A, B; + + // This is how an edge list is created from the polygons + auto fillEdgeList = [](EdgeList& L, const RawShape& ppoly, int dir) { + auto& poly = sl::contour(ppoly); + + L.reserve(sl::contourVertexCount(poly)); + + if(dir > 0) { + auto it = poly.begin(); + auto nextit = std::next(it); + + double turn_angle = 0; + bool is_turn_point = false; + + while(nextit != poly.end()) { + L.emplace_back(Edge(*it, *nextit), turn_angle, is_turn_point); + it++; nextit++; + } + } else { + auto it = sl::rbegin(poly); + auto nextit = std::next(it); + + double turn_angle = 0; + bool is_turn_point = false; + + while(nextit != sl::rend(poly)) { + L.emplace_back(Edge(*it, *nextit), turn_angle, is_turn_point); + it++; nextit++; + } + } + + auto getTurnAngle = [](const Edge& e1, const Edge& e2) { + auto phi = e1.angleToXaxis(); + auto phi_prev = e2.angleToXaxis(); + auto turn_angle = phi-phi_prev; + if(turn_angle > Pi) turn_angle -= TwoPi; + if(turn_angle < -Pi) turn_angle += TwoPi; + return turn_angle; + }; + + auto eit = L.begin(); + auto enext = std::next(eit); + + eit->turn_angle = getTurnAngle(L.front().e, L.back().e); + + while(enext != L.end()) { + enext->turn_angle = getTurnAngle( enext->e, eit->e); + eit->is_turning_point = + signbit(enext->turn_angle) != signbit(eit->turn_angle); + ++eit; ++enext; + } + + L.back().is_turning_point = signbit(L.back().turn_angle) != + signbit(L.front().turn_angle); + + }; + + // Step 2: Fill the edgelists + fillEdgeList(A, stationary, 1); + fillEdgeList(B, orbiter, 1); + + int i = 1; + for(MarkedEdge& me : A) { + std::cout << "a" << i << ":\n\t" + << getX(me.e.first()) << " " << getY(me.e.first()) << "\n\t" + << getX(me.e.second()) << " " << getY(me.e.second()) << "\n\t" + << "Turning point: " << (me.is_turning_point ? "yes" : "no") + << std::endl; + + me.label = "a"; me.label += std::to_string(i); + i++; + } + + i = 1; + for(MarkedEdge& me : B) { + std::cout << "b" << i << ":\n\t" + << getX(me.e.first()) << " " << getY(me.e.first()) << "\n\t" + << getX(me.e.second()) << " " << getY(me.e.second()) << "\n\t" + << "Turning point: " << (me.is_turning_point ? "yes" : "no") + << std::endl; + me.label = "b"; me.label += std::to_string(i); + i++; + } + + // A reference to a marked edge that also knows its container + struct MarkedEdgeRef { + reference_wrapper eref; + reference_wrapper> container; + Coord dir = 1; // Direction modifier + + inline Radians angleX() const { return eref.get().e.angleToXaxis(); } + inline const Edge& edge() const { return eref.get().e; } + inline Edge& edge() { return eref.get().e; } + inline bool isTurningPoint() const { + return eref.get().is_turning_point; + } + inline bool isFrom(const vector& cont ) { + return &(container.get()) == &cont; + } + inline bool eq(const MarkedEdgeRef& mr) { + return &(eref.get()) == &(mr.eref.get()); + } + + MarkedEdgeRef(reference_wrapper er, + reference_wrapper> ec): + eref(er), container(ec), dir(1) {} + + MarkedEdgeRef(reference_wrapper er, + reference_wrapper> ec, + Coord d): + eref(er), container(ec), dir(d) {} + }; + + using EdgeRefList = vector; + + // Comparing two marked edges + auto sortfn = [](const MarkedEdgeRef& e1, const MarkedEdgeRef& e2) { + return e1.angleX() < e2.angleX(); + }; + + EdgeRefList Aref, Bref; // We create containers for the references + Aref.reserve(A.size()); Bref.reserve(B.size()); + + // Fill reference container for the stationary polygon + std::for_each(A.begin(), A.end(), [&Aref](MarkedEdge& me) { + Aref.emplace_back( ref(me), ref(Aref) ); + }); + + // Fill reference container for the orbiting polygon + std::for_each(B.begin(), B.end(), [&Bref](MarkedEdge& me) { + Bref.emplace_back( ref(me), ref(Bref) ); + }); + + auto mink = [sortfn] // the Mink(Q, R, direction) sub-procedure + (const EdgeRefList& Q, const EdgeRefList& R, bool positive) + { + + // Step 1 "merge sort_list(Q) and sort_list(R) to form merge_list(Q,R)" + // Sort the containers of edge references and merge them. + // Q could be sorted only once and be reused here but we would still + // need to merge it with sorted(R). + + EdgeRefList merged; + EdgeRefList S, seq; + merged.reserve(Q.size() + R.size()); + + merged.insert(merged.end(), R.begin(), R.end()); + std::stable_sort(merged.begin(), merged.end(), sortfn); + merged.insert(merged.end(), Q.begin(), Q.end()); + std::stable_sort(merged.begin(), merged.end(), sortfn); + + // Step 2 "set i = 1, k = 1, direction = 1, s1 = q1" + // we don't use i, instead, q is an iterator into Q. k would be an index + // into the merged sequence but we use "it" as an iterator for that + + // here we obtain references for the containers for later comparisons + const auto& Rcont = R.begin()->container.get(); + const auto& Qcont = Q.begin()->container.get(); + + // Set the initial direction + Coord dir = 1; + + // roughly i = 1 (so q = Q.begin()) and s1 = q1 so S[0] = q; + if(positive) { + auto q = Q.begin(); + S.emplace_back(*q); + + // Roughly step 3 + + std::cout << "merged size: " << merged.size() << std::endl; + auto mit = merged.begin(); + for(bool finish = false; !finish && q != Q.end();) { + ++q; // "Set i = i + 1" + + while(!finish && mit != merged.end()) { + if(mit->isFrom(Rcont)) { + auto s = *mit; + s.dir = dir; + S.emplace_back(s); + } + + if(mit->eq(*q)) { + S.emplace_back(*q); + if(mit->isTurningPoint()) dir = -dir; + if(q == Q.begin()) finish = true; + break; + } + + mit += dir; + // __nfp::advance(mit, merged, dir > 0); + } + } + } else { + auto q = Q.rbegin(); + S.emplace_back(*q); + + // Roughly step 3 + + std::cout << "merged size: " << merged.size() << std::endl; + auto mit = merged.begin(); + for(bool finish = false; !finish && q != Q.rend();) { + ++q; // "Set i = i + 1" + + while(!finish && mit != merged.end()) { + if(mit->isFrom(Rcont)) { + auto s = *mit; + s.dir = dir; + S.emplace_back(s); + } + + if(mit->eq(*q)) { + S.emplace_back(*q); + S.back().dir = -1; + if(mit->isTurningPoint()) dir = -dir; + if(q == Q.rbegin()) finish = true; + break; + } + + mit += dir; + // __nfp::advance(mit, merged, dir > 0); + } + } + } + + + // Step 4: + + // "Let starting edge r1 be in position si in sequence" + // whaaat? I guess this means the following: + auto it = S.begin(); + while(!it->eq(*R.begin())) ++it; + + // "Set j = 1, next = 2, direction = 1, seq1 = si" + // we don't use j, seq is expanded dynamically. + dir = 1; + auto next = std::next(R.begin()); seq.emplace_back(*it); + + // Step 5: + // "If all si edges have been allocated to seqj" should mean that + // we loop until seq has equal size with S + auto send = it; //it == S.begin() ? it : std::prev(it); + while(it != S.end()) { + ++it; if(it == S.end()) it = S.begin(); + if(it == send) break; + + if(it->isFrom(Qcont)) { + seq.emplace_back(*it); // "If si is from Q, j = j + 1, seqj = si" + + // "If si is a turning point in Q, + // direction = - direction, next = next + direction" + if(it->isTurningPoint()) { + dir = -dir; + next += dir; +// __nfp::advance(next, R, dir > 0); + } + } + + if(it->eq(*next) /*&& dir == next->dir*/) { // "If si = direction.rnext" + // "j = j + 1, seqj = si, next = next + direction" + seq.emplace_back(*it); + next += dir; +// __nfp::advance(next, R, dir > 0); + } + } + + return seq; + }; + + std::vector seqlist; + seqlist.reserve(Bref.size()); + + EdgeRefList Bslope = Bref; // copy Bref, we will make a slope diagram + + // make the slope diagram of B + std::sort(Bslope.begin(), Bslope.end(), sortfn); + + auto slopeit = Bslope.begin(); // search for the first turning point + while(!slopeit->isTurningPoint() && slopeit != Bslope.end()) slopeit++; + + if(slopeit == Bslope.end()) { + // no turning point means convex polygon. + seqlist.emplace_back(mink(Aref, Bref, true)); + } else { + int dir = 1; + + auto firstturn = Bref.begin(); + while(!firstturn->eq(*slopeit)) ++firstturn; + + assert(firstturn != Bref.end()); + + EdgeRefList bgroup; bgroup.reserve(Bref.size()); + bgroup.emplace_back(*slopeit); + + auto b_it = std::next(firstturn); + while(b_it != firstturn) { + if(b_it == Bref.end()) b_it = Bref.begin(); + + while(!slopeit->eq(*b_it)) { + __nfp::advance(slopeit, Bslope, dir > 0); + } + + if(!slopeit->isTurningPoint()) { + bgroup.emplace_back(*slopeit); + } else { + if(!bgroup.empty()) { + if(dir > 0) bgroup.emplace_back(*slopeit); + for(auto& me : bgroup) { + std::cout << me.eref.get().label << ", "; + } + std::cout << std::endl; + seqlist.emplace_back(mink(Aref, bgroup, dir == 1 ? true : false)); + bgroup.clear(); + if(dir < 0) bgroup.emplace_back(*slopeit); + } else { + bgroup.emplace_back(*slopeit); + } + + dir *= -1; + } + ++b_it; + } + } + +// while(it != Bref.end()) // This is step 3 and step 4 in one loop +// if(it->isTurningPoint()) { +// R = {R.last, it++}; +// auto seq = mink(Q, R, orientation); + +// // TODO step 6 (should be 5 shouldn't it?): linking edges from A +// // I don't get this step + +// seqlist.insert(seqlist.end(), seq.begin(), seq.end()); +// orientation = !orientation; +// } else ++it; + +// if(seqlist.empty()) seqlist = mink(Q, {Bref.begin(), Bref.end()}, true); + + // ///////////////////////////////////////////////////////////////////////// + // Algorithm 2: breaking Minkowski sums into track line trips + // ///////////////////////////////////////////////////////////////////////// + + + // ///////////////////////////////////////////////////////////////////////// + // Algorithm 3: finding the boundary of the NFP from track line trips + // ///////////////////////////////////////////////////////////////////////// + + + for(auto& seq : seqlist) { + std::cout << "seqlist size: " << seq.size() << std::endl; + for(auto& s : seq) { + std::cout << (s.dir > 0 ? "" : "-") << s.eref.get().label << ", "; + } + std::cout << std::endl; + } + + auto& seq = seqlist.front(); + RawShape rsh; + Vertex top_nfp; + std::vector edgelist; edgelist.reserve(seq.size()); + for(auto& s : seq) { + edgelist.emplace_back(s.eref.get().e); + } + + __nfp::buildPolygon(edgelist, rsh, top_nfp); + + return Result(rsh, top_nfp); +} + // Specializable NFP implementation class. Specialize it if you have a faster // or better NFP implementation template diff --git a/src/libnest2d/include/libnest2d/libnest2d.hpp b/src/libnest2d/include/libnest2d/libnest2d.hpp index aac62e094..104445a28 100644 --- a/src/libnest2d/include/libnest2d/libnest2d.hpp +++ b/src/libnest2d/include/libnest2d/libnest2d.hpp @@ -490,9 +490,32 @@ _Item::isInside(const _Circle>& circ) const { return sl::isInside(transformedShape(), circ); } +template using _ItemRef = std::reference_wrapper<_Item>; +template using _ItemGroup = std::vector<_ItemRef>; -template using _ItemRef = std::reference_wrapper; -template using _ItemGroup = std::vector<_ItemRef>; +/** + * \brief A list of packed item vectors. Each vector represents a bin. + */ +template +using _PackGroup = std::vector>>; + +/** + * \brief A list of packed (index, item) pair vectors. Each vector represents a + * bin. + * + * The index is points to the position of the item in the original input + * sequence. This way the caller can use the items as a transformation data + * carrier and transform the original objects manually. + */ +template +using _IndexedPackGroup = std::vector< + std::vector< + std::pair< + unsigned, + _ItemRef + > + > + >; template struct ConstItemRange { @@ -524,8 +547,10 @@ class PlacementStrategyLike { PlacementStrategy impl_; public: + using RawShape = typename PlacementStrategy::ShapeType; + /// The item type that the placer works with. - using Item = typename PlacementStrategy::Item; + using Item = _Item; /// The placer's config type. Should be a simple struct but can be anything. using Config = typename PlacementStrategy::Config; @@ -544,8 +569,7 @@ public: */ using PackResult = typename PlacementStrategy::PackResult; - using ItemRef = _ItemRef; - using ItemGroup = _ItemGroup; + using ItemGroup = _ItemGroup; using DefaultIterator = typename ItemGroup::const_iterator; /** @@ -619,6 +643,16 @@ public: return impl_.pack(item, remaining); } + /** + * This method makes possible to "preload" some items into the placer. It + * will not move these items but will consider them as already packed. + */ + template> + inline void preload(const Range& packeditems = Range()) + { + impl_.preload(packeditems); + } + /// Unpack the last element (remove it from the list of packed items). inline void unpackLast() { impl_.unpackLast(); } @@ -649,11 +683,11 @@ template class SelectionStrategyLike { SelectionStrategy impl_; public: - using Item = typename SelectionStrategy::Item; + using RawShape = typename SelectionStrategy::ShapeType; + using Item = _Item; + using PackGroup = _PackGroup; using Config = typename SelectionStrategy::Config; - using ItemRef = std::reference_wrapper; - using ItemGroup = std::vector; /** * @brief Provide a different configuration for the selection strategy. @@ -703,60 +737,29 @@ public: std::forward(config)); } - /** - * \brief Get the number of bins opened by the selection algorithm. - * - * Initially it is zero and after the call to packItems it will return - * the number of bins opened by the packing procedure. - * - * \return The number of bins opened. - */ - inline size_t binCount() const { return impl_.binCount(); } - /** * @brief Get the items for a particular bin. * @param binIndex The index of the requested bin. * @return Returns a list of all items packed into the requested bin. */ - inline ItemGroup itemsForBin(size_t binIndex) { - return impl_.itemsForBin(binIndex); + inline const PackGroup& getResult() const { + return impl_.getResult(); } - /// Same as itemsForBin but for a const context. - inline const ItemGroup itemsForBin(size_t binIndex) const { - return impl_.itemsForBin(binIndex); - } + /** + * @brief Loading a group of already packed bins. It is best to use a result + * from a previous packing. The algorithm will consider this input as if the + * objects are already packed and not move them. If any of these items are + * outside the bin, it is up to the placer algorithm what will happen. + * Packing additional items can fail for the bottom-left and nfp placers. + * @param pckgrp A packgroup which is a vector of item vectors. Each item + * vector corresponds to a packed bin. + */ + inline void preload(const PackGroup& pckgrp) { impl_.preload(pckgrp); } + + void clear() { impl_.clear(); } }; - -/** - * \brief A list of packed item vectors. Each vector represents a bin. - */ -template -using _PackGroup = std::vector< - std::vector< - std::reference_wrapper<_Item> - > - >; - -/** - * \brief A list of packed (index, item) pair vectors. Each vector represents a - * bin. - * - * The index is points to the position of the item in the original input - * sequence. This way the caller can use the items as a transformation data - * carrier and transform the original objects manually. - */ -template -using _IndexedPackGroup = std::vector< - std::vector< - std::pair< - unsigned, - std::reference_wrapper<_Item> - > - > - >; - /** * The Arranger is the front-end class for the libnest2d library. It takes the * input items and outputs the items with the proper transformations to be @@ -868,17 +871,29 @@ public: } /// Set a predicate to tell when to abort nesting. - inline Nester& stopCondition(StopCondition fn) { + inline Nester& stopCondition(StopCondition fn) + { selector_.stopCondition(fn); return *this; } - inline PackGroup lastResult() { - PackGroup ret; - for(size_t i = 0; i < selector_.binCount(); i++) { - auto items = selector_.itemsForBin(i); - ret.push_back(items); + inline const PackGroup& lastResult() const + { + return selector_.getResult(); + } + + inline void preload(const PackGroup& pgrp) + { + selector_.preload(pgrp); + } + + inline void preload(const IndexedPackGroup& ipgrp) + { + PackGroup pgrp; pgrp.reserve(ipgrp.size()); + for(auto& ig : ipgrp) { + pgrp.emplace_back(); pgrp.back().reserve(ig.size()); + for(auto& r : ig) pgrp.back().emplace_back(r.second); } - return ret; + preload(pgrp); } private: @@ -892,7 +907,7 @@ private: // have to exist for the lifetime of this call. class T = enable_if_t< std::is_convertible::value, IT> > - inline PackGroup _execute(TIterator from, TIterator to, bool = false) + inline const PackGroup& _execute(TIterator from, TIterator to, bool = false) { __execute(from, to); return lastResult(); @@ -902,7 +917,7 @@ private: class IT = remove_cvref_t, class T = enable_if_t::value, IT> > - inline PackGroup _execute(TIterator from, TIterator to, int = false) + inline const PackGroup& _execute(TIterator from, TIterator to, int = false) { item_cache_ = {from, to}; @@ -946,10 +961,12 @@ private: TSel& selector) { IndexedPackGroup pg; - pg.reserve(selector.binCount()); + pg.reserve(selector.getResult().size()); - for(size_t i = 0; i < selector.binCount(); i++) { - auto items = selector.itemsForBin(i); + const PackGroup& pckgrp = selector.getResult(); + + for(size_t i = 0; i < pckgrp.size(); i++) { + auto items = pckgrp[i]; pg.push_back({}); pg[i].reserve(items.size()); diff --git a/src/libnest2d/include/libnest2d/optimizers/nlopt/CMakeLists.txt b/src/libnest2d/include/libnest2d/optimizers/nlopt/CMakeLists.txt index 2a32019f4..5559ad645 100644 --- a/src/libnest2d/include/libnest2d/optimizers/nlopt/CMakeLists.txt +++ b/src/libnest2d/include/libnest2d/optimizers/nlopt/CMakeLists.txt @@ -48,12 +48,12 @@ else() target_link_libraries(NloptOptimizer INTERFACE Nlopt::Nlopt) endif() -#target_sources( NloptOptimizer INTERFACE -#${CMAKE_CURRENT_SOURCE_DIR}/simplex.hpp -#${CMAKE_CURRENT_SOURCE_DIR}/subplex.hpp -#${CMAKE_CURRENT_SOURCE_DIR}/genetic.hpp -#${CMAKE_CURRENT_SOURCE_DIR}/nlopt_boilerplate.hpp -#) +target_sources( NloptOptimizer INTERFACE +${CMAKE_CURRENT_SOURCE_DIR}/simplex.hpp +${CMAKE_CURRENT_SOURCE_DIR}/subplex.hpp +${CMAKE_CURRENT_SOURCE_DIR}/genetic.hpp +${CMAKE_CURRENT_SOURCE_DIR}/nlopt_boilerplate.hpp +) target_compile_definitions(NloptOptimizer INTERFACE LIBNEST2D_OPTIMIZER_NLOPT) diff --git a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp index 28659c512..3cdc0cca1 100644 --- a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp +++ b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp @@ -130,7 +130,7 @@ namespace placers { template struct NfpPConfig { - using ItemGroup = _ItemGroup<_Item>; + using ItemGroup = _ItemGroup; enum class Alignment { CENTER, @@ -138,6 +138,8 @@ struct NfpPConfig { BOTTOM_RIGHT, TOP_LEFT, TOP_RIGHT, + DONT_ALIGN //!> Warning: parts may end up outside the bin with the + //! default object function. }; /// Which angles to try out for better results. @@ -545,8 +547,8 @@ public: _NofitPolyPlacer& operator=(const _NofitPolyPlacer&) = default; #ifndef BP2D_COMPILER_MSVC12 // MSVC2013 does not support default move ctors - _NofitPolyPlacer(_NofitPolyPlacer&&) /*BP2D_NOEXCEPT*/ = default; - _NofitPolyPlacer& operator=(_NofitPolyPlacer&&) /*BP2D_NOEXCEPT*/ = default; + _NofitPolyPlacer(_NofitPolyPlacer&&) = default; + _NofitPolyPlacer& operator=(_NofitPolyPlacer&&) = default; #endif static inline double overfit(const Box& bb, const RawShape& bin) { @@ -905,26 +907,43 @@ private: // This is the kernel part of the object function that is // customizable by the library client - auto _objfunc = config_.object_function? - config_.object_function : - [norm, bin, binbb, pbb](const Item& item) - { - auto ibb = item.boundingBox(); - auto fullbb = boundingBox(pbb, ibb); + std::function _objfunc; + if(config_.object_function) _objfunc = config_.object_function; + else { - double score = pl::distance(ibb.center(), binbb.center()); - score /= norm; + // Inside check has to be strict if no alignment was enabled. + std::function ins_check; + if(config_.alignment == Config::Alignment::DONT_ALIGN) + ins_check = [&binbb, norm](const Box& fullbb) { + double ret = 0; + if(sl::isInside(fullbb, binbb)) ret += norm; + return ret; + }; + else + ins_check = [&bin](const Box& fullbb) { + double miss = overfit(fullbb, bin); + miss = miss > 0? miss : 0; + return std::pow(miss, 2); + }; - double miss = overfit(fullbb, bin); - miss = miss > 0? miss : 0; - score += std::pow(miss, 2); + _objfunc = [norm, binbb, pbb, ins_check](const Item& item) + { + auto ibb = item.boundingBox(); + auto fullbb = boundingBox(pbb, ibb); - return score; - }; + double score = pl::distance(ibb.center(), + binbb.center()); + score /= norm; + + score += ins_check(fullbb); + + return score; + }; + } // Our object function for placement - auto rawobjfunc = - [_objfunc, iv, startpos] (Vertex v, Item& itm) + auto rawobjfunc = [_objfunc, iv, startpos] + (Vertex v, Item& itm) { auto d = v - iv; d += startpos; @@ -1101,7 +1120,9 @@ private: } inline void finalAlign(_Circle> cbin) { - if(items_.empty()) return; + if(items_.empty() || + config_.alignment == Config::Alignment::DONT_ALIGN) return; + nfp::Shapes m; m.reserve(items_.size()); for(Item& item : items_) m.emplace_back(item.transformedShape()); @@ -1113,7 +1134,9 @@ private: } inline void finalAlign(Box bbin) { - if(items_.empty()) return; + if(items_.empty() || + config_.alignment == Config::Alignment::DONT_ALIGN) return; + nfp::Shapes m; m.reserve(items_.size()); for(Item& item : items_) m.emplace_back(item.transformedShape()); @@ -1147,6 +1170,7 @@ private: cb = bbin.maxCorner(); break; } + default: ; // DONT_ALIGN } auto d = cb - ci; @@ -1184,6 +1208,7 @@ private: cb = bbin.maxCorner(); break; } + default:; } auto d = cb - ci; diff --git a/src/libnest2d/include/libnest2d/placers/placer_boilerplate.hpp b/src/libnest2d/include/libnest2d/placers/placer_boilerplate.hpp index 9f940af4d..ef5056910 100644 --- a/src/libnest2d/include/libnest2d/placers/placer_boilerplate.hpp +++ b/src/libnest2d/include/libnest2d/placers/placer_boilerplate.hpp @@ -12,6 +12,7 @@ class PlacerBoilerplate { mutable bool farea_valid_ = false; mutable double farea_ = 0.0; public: + using ShapeType = RawShape; using Item = _Item; using Vertex = TPoint; using Segment = _Segment; @@ -19,7 +20,7 @@ public: using Coord = TCoord; using Unit = Coord; using Config = Cfg; - using ItemGroup = _ItemGroup; + using ItemGroup = _ItemGroup; using DefaultIter = typename ItemGroup::const_iterator; class PackResult { @@ -69,6 +70,12 @@ public: return r; } + template> + void preload(const Range& packeditems = Range()) { + items_.insert(items_.end(), packeditems.from, packeditems.to); + farea_valid_ = false; + } + void accept(PackResult& r) { if(r) { r.item_ptr_->translation(r.move_); @@ -117,6 +124,7 @@ using Base::bin_; \ using Base::items_; \ using Base::config_; \ public: \ +using typename Base::ShapeType; \ using typename Base::Item; \ using typename Base::ItemGroup; \ using typename Base::BinType; \ diff --git a/src/libnest2d/include/libnest2d/selections/djd_heuristic.hpp b/src/libnest2d/include/libnest2d/selections/djd_heuristic.hpp index 39761f557..b03534dc4 100644 --- a/src/libnest2d/include/libnest2d/selections/djd_heuristic.hpp +++ b/src/libnest2d/include/libnest2d/selections/djd_heuristic.hpp @@ -33,7 +33,7 @@ class _DJDHeuristic: public SelectionBoilerplate { public: using typename Base::Item; - using typename Base::ItemRef; + using ItemRef = std::reference_wrapper; /** * @brief The Config for DJD heuristic. @@ -126,6 +126,8 @@ public: store_.clear(); store_.reserve(last-first); + + // TODO: support preloading packed_bins_.clear(); std::copy(first, last, std::back_inserter(store_)); diff --git a/src/libnest2d/include/libnest2d/selections/filler.hpp b/src/libnest2d/include/libnest2d/selections/filler.hpp index 5f95a6eff..19c44bfaa 100644 --- a/src/libnest2d/include/libnest2d/selections/filler.hpp +++ b/src/libnest2d/include/libnest2d/selections/filler.hpp @@ -34,6 +34,10 @@ public: store_.clear(); auto total = last-first; store_.reserve(total); + + // TODO: support preloading + packed_bins_.clear(); + packed_bins_.emplace_back(); auto makeProgress = [this, &total]( diff --git a/src/libnest2d/include/libnest2d/selections/firstfit.hpp b/src/libnest2d/include/libnest2d/selections/firstfit.hpp index d25487d6b..25fb73590 100644 --- a/src/libnest2d/include/libnest2d/selections/firstfit.hpp +++ b/src/libnest2d/include/libnest2d/selections/firstfit.hpp @@ -36,11 +36,19 @@ public: store_.clear(); store_.reserve(last-first); - packed_bins_.clear(); std::vector placers; placers.reserve(last-first); + // If the packed_items array is not empty we have to create as many + // placers as there are elements in packed bins and preload each item + // into the appropriate placer + for(ItemGroup& ig : packed_bins_) { + placers.emplace_back(bin); + placers.back().configure(pconfig); + placers.back().preload({ig.begin(), ig.end()}); + } + std::copy(first, last, std::back_inserter(store_)); auto sortfunc = [](Item& i1, Item& i2) { diff --git a/src/libnest2d/include/libnest2d/selections/selection_boilerplate.hpp b/src/libnest2d/include/libnest2d/selections/selection_boilerplate.hpp index 8351a99e7..fd6577d97 100644 --- a/src/libnest2d/include/libnest2d/selections/selection_boilerplate.hpp +++ b/src/libnest2d/include/libnest2d/selections/selection_boilerplate.hpp @@ -9,27 +9,23 @@ namespace libnest2d { namespace selections { template class SelectionBoilerplate { public: + using ShapeType = RawShape; using Item = _Item; - using ItemRef = std::reference_wrapper; - using ItemGroup = std::vector; - using PackGroup = std::vector; + using ItemGroup = _ItemGroup; + using PackGroup = _PackGroup; - size_t binCount() const { return packed_bins_.size(); } - - ItemGroup itemsForBin(size_t binIndex) { - assert(binIndex < packed_bins_.size()); - return packed_bins_[binIndex]; - } - - inline const ItemGroup itemsForBin(size_t binIndex) const { - assert(binIndex < packed_bins_.size()); - return packed_bins_[binIndex]; + inline const PackGroup& getResult() const { + return packed_bins_; } inline void progressIndicator(ProgressFunction fn) { progress_ = fn; } inline void stopCondition(StopCondition cond) { stopcond_ = cond; } + inline void preload(const PackGroup& pckgrp) { packed_bins_ = pckgrp; } + + inline void clear() { packed_bins_.clear(); } + protected: PackGroup packed_bins_; diff --git a/src/libslic3r/ModelArrange.cpp b/src/libslic3r/ModelArrange.cpp index 1f517375c..2a6677a6d 100644 --- a/src/libslic3r/ModelArrange.cpp +++ b/src/libslic3r/ModelArrange.cpp @@ -358,6 +358,28 @@ public: m_rtree.clear(); return m_pck.executeIndexed(std::forward(args)...); } + + inline void preload(const PackGroup& pg) { + m_pconf.alignment = PConfig::Alignment::DONT_ALIGN; + m_pconf.object_function = nullptr; // drop the special objectfunction + m_pck.preload(pg); + + // Build the rtree for queries to work + for(const ItemGroup& grp : pg) + for(unsigned idx = 0; idx < grp.size(); ++idx) { + Item& itm = grp[idx]; + m_rtree.insert({itm.boundingBox(), idx}); + } + + m_pck.configure(m_pconf); + } + + bool is_colliding(const Item& item) { + std::vector result; + m_rtree.query(bgi::intersects(item.boundingBox()), + std::back_inserter(result)); + return result.empty(); + } }; // Arranger specialization for a Box shaped bin. @@ -365,8 +387,8 @@ template<> class AutoArranger: public _ArrBase { public: AutoArranger(const Box& bin, Distance dist, - std::function progressind, - std::function stopcond): + std::function progressind = [](unsigned){}, + std::function stopcond = [](){return false;}): _ArrBase(bin, dist, progressind, stopcond) { @@ -791,5 +813,114 @@ bool arrange(Model &model, // The model with the geometries return ret && result.size() == 1; } +void find_new_position(const Model &model, + ModelInstancePtrs toadd, + coord_t min_obj_distance, + const Polyline &bed) +{ + // Get the 2D projected shapes with their 3D model instance pointers + auto shapemap = arr::projectModelFromTop(model); + + // Copy the references for the shapes only as the arranger expects a + // sequence of objects convertible to Item or ClipperPolygon + PackGroup preshapes; preshapes.emplace_back(); + ItemGroup shapes; + preshapes.front().reserve(shapemap.size()); + + std::vector shapes_ptr; shapes_ptr.reserve(toadd.size()); + IndexedPackGroup result; + + // If there is no hint about the shape, we will try to guess + BedShapeHint bedhint = bedShape(bed); + + BoundingBox bbb(bed); + + auto binbb = Box({ + static_cast(bbb.min(0)), + static_cast(bbb.min(1)) + }, + { + static_cast(bbb.max(0)), + static_cast(bbb.max(1)) + }); + + for(auto it = shapemap.begin(); it != shapemap.end(); ++it) { + if(std::find(toadd.begin(), toadd.end(), it->first) == toadd.end() && + it->second.isInside(binbb)) { // just ignore items which are outside + preshapes.front().emplace_back(std::ref(it->second)); + } + else { + shapes_ptr.emplace_back(it->first); + shapes.emplace_back(std::ref(it->second)); + } + } + + switch(bedhint.type) { + case BedShapeType::BOX: { + + // Create the arranger for the box shaped bed + AutoArranger arrange(binbb, min_obj_distance); + std::cout << "preload size: " << preshapes.front().size() << std::endl; + if(!preshapes.front().empty()) arrange.preload(preshapes); + + // Arrange and return the items with their respective indices within the + // input sequence. + result = arrange(shapes.begin(), shapes.end()); + break; + } + case BedShapeType::CIRCLE: { + +// auto c = bedhint.shape.circ; +// auto cc = to_lnCircle(c); + +// AutoArranger arrange(cc, min_obj_distance, progressind, cfn); +// result = arrange(shapes.begin(), shapes.end()); + break; + } + case BedShapeType::IRREGULAR: + case BedShapeType::WHO_KNOWS: { + +// using P = libnest2d::PolygonImpl; + +// auto ctour = Slic3rMultiPoint_to_ClipperPath(bed); +// P irrbed = sl::create(std::move(ctour)); + +// AutoArranger

arrange(irrbed, min_obj_distance, progressind, cfn); + +// // Arrange and return the items with their respective indices within the +// // input sequence. +// result = arrange(shapes.begin(), shapes.end()); + break; + } + }; + + // Now we go through the result which will contain the fixed and the moving + // polygons as well. We will have to search for our item. + + const auto STRIDE_PADDING = 1.2; + Coord stride = Coord(STRIDE_PADDING*binbb.width()*SCALING_FACTOR); + Coord batch_offset = 0; + + for(auto& group : result) { + for(auto& r : group) if(r.first < shapes.size()) { + Item& resultitem = r.second; + unsigned idx = r.first; + auto offset = resultitem.translation(); + Radians rot = resultitem.rotation(); + ModelInstance *minst = shapes_ptr[idx]; + Vec3d foffset(offset.X*SCALING_FACTOR + batch_offset, + offset.Y*SCALING_FACTOR, + minst->get_offset()(Z)); + + // write the transformation data into the model instance + minst->set_rotation(Z, rot); + minst->set_offset(foffset); + } + batch_offset += stride; + } } + +} + + } diff --git a/src/libslic3r/ModelArrange.hpp b/src/libslic3r/ModelArrange.hpp index d62e0df30..d76769081 100644 --- a/src/libslic3r/ModelArrange.hpp +++ b/src/libslic3r/ModelArrange.hpp @@ -73,7 +73,13 @@ bool arrange(Model &model, coord_t min_obj_distance, std::function progressind, std::function stopcondition); -} +/// This will find a suitable position for a new object instance and leave the +/// old items untouched. +void find_new_position(const Model& model, + ModelInstancePtrs instances_to_add, + coord_t min_obj_distance, + const Slic3r::Polyline& bed); -} +} // arr +} // Slic3r #endif // MODELARRANGE_HPP diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index da11044bc..45575546f 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1399,6 +1399,8 @@ std::vector Plater::priv::load_files(const std::vector& input_ if (one_by_one) { auto loaded_idxs = load_model_objects(model.objects); obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end()); + + std::cout << "New model objects added..." << std::endl; } else { // This must be an .stl or .obj file, which may contain a maximum of one volume. for (const ModelObject* model_object : model.objects) { @@ -1448,11 +1450,12 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode const BoundingBoxf bed_shape = bed_shape_bb(); const Vec3d bed_size = Slic3r::to_3d(bed_shape.size().cast(), 1.0) - 2.0 * Vec3d::Ones(); - bool need_arrange = false; +// bool need_arrange = false; bool scaled_down = false; std::vector obj_idxs; unsigned int obj_count = model.objects.size(); + ModelInstancePtrs new_instances; for (ModelObject *model_object : model_objects) { auto *object = model.add_object(*model_object); std::string object_name = object->name.empty() ? fs::path(object->input_file).filename().string() : object->name; @@ -1460,12 +1463,15 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode if (model_object->instances.empty()) { // if object has no defined position(s) we need to rearrange everything after loading - need_arrange = true; +// 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(); - instance->set_offset(Slic3r::to_3d(bed_shape.center().cast(), -object->origin_translation(2))); + object->center_around_origin(); + new_instances.emplace_back(object->add_instance()); + +// // add a default instance and center object around origin +// object->center_around_origin(); // also aligns object to Z = 0 +// ModelInstance* instance = object->add_instance(); +// instance->set_offset(Slic3r::to_3d(bed_shape.center().cast(), -object->origin_translation(2))); } const Vec3d size = object->bounding_box().size(); @@ -1492,6 +1498,17 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode // print.add_model_object(object); } + // FIXME distance should be a config value + auto min_obj_distance = static_cast(6/SCALING_FACTOR); + const auto *bed_shape_opt = config->opt("bed_shape"); + assert(bed_shape_opt); + auto& bedpoints = bed_shape_opt->values; + Polyline bed; bed.points.reserve(bedpoints.size()); + for(auto& v : bedpoints) bed.append(Point::new_scale(v(0), v(1))); + + arr::find_new_position(model, new_instances, + min_obj_distance, bed); + if (scaled_down) { GUI::show_info(q, _(L("Your object appears to be too large, so it was automatically scaled down to fit your print bed.")), From 05032d9760bfdae2dec36a785fa47c17f6c916f7 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Tue, 22 Jan 2019 18:05:11 +0100 Subject: [PATCH 02/23] Trying force center placement with existing objects. --- src/libslic3r/ModelArrange.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/libslic3r/ModelArrange.cpp b/src/libslic3r/ModelArrange.cpp index 2a6677a6d..f88b131de 100644 --- a/src/libslic3r/ModelArrange.cpp +++ b/src/libslic3r/ModelArrange.cpp @@ -861,8 +861,37 @@ void find_new_position(const Model &model, // Create the arranger for the box shaped bed AutoArranger arrange(binbb, min_obj_distance); std::cout << "preload size: " << preshapes.front().size() << std::endl; + if(!preshapes.front().empty()) arrange.preload(preshapes); + auto shptrit = shapes_ptr.begin(); + for(auto shit = shapes.begin(); shit != shapes.end(); ++shit, ++shptrit) + { + // Try to place items to the center + Item& itm = *shit; + auto ibb = itm.boundingBox(); + auto d = ibb.center() - binbb.center(); + itm.translate(d); + if(!arrange.is_colliding(itm)) { + arrange.preload({{itm}}); + + auto offset = itm.translation(); + Radians rot = itm.rotation(); + ModelInstance *minst = *shptrit; + Vec3d foffset(offset.X*SCALING_FACTOR, + offset.Y*SCALING_FACTOR, + minst->get_offset()(Z)); + + // write the transformation data into the model instance + minst->set_rotation(Z, rot); + minst->set_offset(foffset); + + shit = shapes.erase(shit); + shptrit = shapes_ptr.erase(shptrit); + break; + } + } + // Arrange and return the items with their respective indices within the // input sequence. result = arrange(shapes.begin(), shapes.end()); From f129a924057213fe7256a6fc69527fb5b3702ae9 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 23 Jan 2019 10:37:37 +0100 Subject: [PATCH 03/23] fixing is_colliding and centering translation. --- src/libslic3r/ModelArrange.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/ModelArrange.cpp b/src/libslic3r/ModelArrange.cpp index f88b131de..572788925 100644 --- a/src/libslic3r/ModelArrange.cpp +++ b/src/libslic3r/ModelArrange.cpp @@ -375,10 +375,11 @@ public: } bool is_colliding(const Item& item) { + if(m_rtree.empty()) return false; std::vector result; m_rtree.query(bgi::intersects(item.boundingBox()), std::back_inserter(result)); - return result.empty(); + return !result.empty(); } }; @@ -870,7 +871,7 @@ void find_new_position(const Model &model, // Try to place items to the center Item& itm = *shit; auto ibb = itm.boundingBox(); - auto d = ibb.center() - binbb.center(); + auto d = binbb.center() - ibb.center(); itm.translate(d); if(!arrange.is_colliding(itm)) { arrange.preload({{itm}}); From 27b9ceceb526609372ba41093fddf2f7c2e9d9fc Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 23 Jan 2019 13:12:44 +0100 Subject: [PATCH 04/23] Polishing autocenter feature for testing --- .../include/libnest2d/placers/nfpplacer.hpp | 5 +- src/libslic3r/ModelArrange.cpp | 89 +++++++++++++------ src/slic3r/GUI/Plater.cpp | 17 +--- 3 files changed, 66 insertions(+), 45 deletions(-) diff --git a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp index 3cdc0cca1..4573027e4 100644 --- a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp +++ b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp @@ -911,12 +911,13 @@ private: if(config_.object_function) _objfunc = config_.object_function; else { - // Inside check has to be strict if no alignment was enabled. + // Inside check has to be strict if no alignment was enabled std::function ins_check; if(config_.alignment == Config::Alignment::DONT_ALIGN) ins_check = [&binbb, norm](const Box& fullbb) { double ret = 0; - if(sl::isInside(fullbb, binbb)) ret += norm; + if(sl::isInside(fullbb, binbb)) + ret += norm*norm; return ret; }; else diff --git a/src/libslic3r/ModelArrange.cpp b/src/libslic3r/ModelArrange.cpp index 572788925..d527db9da 100644 --- a/src/libslic3r/ModelArrange.cpp +++ b/src/libslic3r/ModelArrange.cpp @@ -434,8 +434,8 @@ template<> class AutoArranger: public _ArrBase { public: AutoArranger(const lnCircle& bin, Distance dist, - std::function progressind, - std::function stopcond): + std::function progressind = [](unsigned){}, + std::function stopcond = [](){return false;}): _ArrBase(bin, dist, progressind, stopcond) { // As with the box, only the inside check is different. @@ -479,8 +479,8 @@ public: template<> class AutoArranger: public _ArrBase { public: AutoArranger(const PolygonImpl& bin, Distance dist, - std::function progressind, - std::function stopcond): + std::function progressind = [](unsigned){}, + std::function stopcond = [](){return false;}): _ArrBase(bin, dist, progressind, stopcond) { m_pconf.object_function = [this, &bin] (const Item &item) { @@ -846,9 +846,9 @@ void find_new_position(const Model &model, }); for(auto it = shapemap.begin(); it != shapemap.end(); ++it) { - if(std::find(toadd.begin(), toadd.end(), it->first) == toadd.end() && - it->second.isInside(binbb)) { // just ignore items which are outside - preshapes.front().emplace_back(std::ref(it->second)); + if(std::find(toadd.begin(), toadd.end(), it->first) == toadd.end()) { + if(it->second.isInside(binbb)) // just ignore items which are outside + preshapes.front().emplace_back(std::ref(it->second)); } else { shapes_ptr.emplace_back(it->first); @@ -856,15 +856,12 @@ void find_new_position(const Model &model, } } - switch(bedhint.type) { - case BedShapeType::BOX: { - - // Create the arranger for the box shaped bed - AutoArranger arrange(binbb, min_obj_distance); - std::cout << "preload size: " << preshapes.front().size() << std::endl; - - if(!preshapes.front().empty()) arrange.preload(preshapes); - + auto try_first_to_center = [&shapes, &shapes_ptr, &binbb] + (std::function is_colliding, + std::function preload) + { + // Try to put the first item to the center, as the arranger will not + // do this for us. auto shptrit = shapes_ptr.begin(); for(auto shit = shapes.begin(); shit != shapes.end(); ++shit, ++shptrit) { @@ -873,8 +870,8 @@ void find_new_position(const Model &model, auto ibb = itm.boundingBox(); auto d = binbb.center() - ibb.center(); itm.translate(d); - if(!arrange.is_colliding(itm)) { - arrange.preload({{itm}}); + if(!is_colliding(itm)) { + preload(itm); auto offset = itm.translation(); Radians rot = itm.rotation(); @@ -892,6 +889,21 @@ void find_new_position(const Model &model, break; } } + }; + + switch(bedhint.type) { + case BedShapeType::BOX: { + + // Create the arranger for the box shaped bed + AutoArranger arrange(binbb, min_obj_distance); + + if(!preshapes.front().empty()) { // If there is something on the plate + arrange.preload(preshapes); + try_first_to_center( + [&arrange](const Item& itm) {return arrange.is_colliding(itm);}, + [&arrange](Item& itm) { arrange.preload({{itm}}); } + ); + } // Arrange and return the items with their respective indices within the // input sequence. @@ -900,26 +912,45 @@ void find_new_position(const Model &model, } case BedShapeType::CIRCLE: { -// auto c = bedhint.shape.circ; -// auto cc = to_lnCircle(c); + auto c = bedhint.shape.circ; + auto cc = to_lnCircle(c); -// AutoArranger arrange(cc, min_obj_distance, progressind, cfn); -// result = arrange(shapes.begin(), shapes.end()); + // Create the arranger for the box shaped bed + AutoArranger arrange(cc, min_obj_distance); + + if(!preshapes.front().empty()) { // If there is something on the plate + arrange.preload(preshapes); + try_first_to_center( + [&arrange](const Item& itm) {return arrange.is_colliding(itm);}, + [&arrange](Item& itm) { arrange.preload({{itm}}); } + ); + } + + // Arrange and return the items with their respective indices within the + // input sequence. + result = arrange(shapes.begin(), shapes.end()); break; } case BedShapeType::IRREGULAR: case BedShapeType::WHO_KNOWS: { + using P = libnest2d::PolygonImpl; -// using P = libnest2d::PolygonImpl; + auto ctour = Slic3rMultiPoint_to_ClipperPath(bed); + P irrbed = sl::create(std::move(ctour)); -// auto ctour = Slic3rMultiPoint_to_ClipperPath(bed); -// P irrbed = sl::create(std::move(ctour)); + AutoArranger

arrange(irrbed, min_obj_distance); -// AutoArranger

arrange(irrbed, min_obj_distance, progressind, cfn); + if(!preshapes.front().empty()) { // If there is something on the plate + arrange.preload(preshapes); + try_first_to_center( + [&arrange](const Item& itm) {return arrange.is_colliding(itm);}, + [&arrange](Item& itm) { arrange.preload({{itm}}); } + ); + } -// // Arrange and return the items with their respective indices within the -// // input sequence. -// result = arrange(shapes.begin(), shapes.end()); + // Arrange and return the items with their respective indices within the + // input sequence. + result = arrange(shapes.begin(), shapes.end()); break; } }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 45575546f..ac4988a6c 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1399,8 +1399,6 @@ std::vector Plater::priv::load_files(const std::vector& input_ if (one_by_one) { auto loaded_idxs = load_model_objects(model.objects); obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end()); - - std::cout << "New model objects added..." << std::endl; } else { // This must be an .stl or .obj file, which may contain a maximum of one volume. for (const ModelObject* model_object : model.objects) { @@ -1450,7 +1448,6 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode const BoundingBoxf bed_shape = bed_shape_bb(); const Vec3d bed_size = Slic3r::to_3d(bed_shape.size().cast(), 1.0) - 2.0 * Vec3d::Ones(); -// bool need_arrange = false; bool scaled_down = false; std::vector obj_idxs; unsigned int obj_count = model.objects.size(); @@ -1462,16 +1459,8 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode obj_idxs.push_back(obj_count++); if (model_object->instances.empty()) { - // if object has no defined position(s) we need to rearrange everything after loading -// need_arrange = true; - object->center_around_origin(); new_instances.emplace_back(object->add_instance()); - -// // add a default instance and center object around origin -// object->center_around_origin(); // also aligns object to Z = 0 -// ModelInstance* instance = object->add_instance(); -// instance->set_offset(Slic3r::to_3d(bed_shape.center().cast(), -object->origin_translation(2))); } const Vec3d size = object->bounding_box().size(); @@ -1498,7 +1487,7 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode // print.add_model_object(object); } - // FIXME distance should be a config value + // FIXME distance should be a config value ///////////////////////////////// auto min_obj_distance = static_cast(6/SCALING_FACTOR); const auto *bed_shape_opt = config->opt("bed_shape"); assert(bed_shape_opt); @@ -1506,8 +1495,8 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode Polyline bed; bed.points.reserve(bedpoints.size()); for(auto& v : bedpoints) bed.append(Point::new_scale(v(0), v(1))); - arr::find_new_position(model, new_instances, - min_obj_distance, bed); + arr::find_new_position(model, new_instances, min_obj_distance, bed); + // ///////////////////////////////////////////////////////////////////////// if (scaled_down) { GUI::show_info(q, From 4e8c570d52f73fb597d4a759a94d2056f295426f Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 23 Jan 2019 13:12:44 +0100 Subject: [PATCH 05/23] Polishing autoplacement feature for testing --- .../include/libnest2d/placers/nfpplacer.hpp | 5 +- src/libslic3r/ModelArrange.cpp | 89 +++++++++++++------ src/slic3r/GUI/Plater.cpp | 17 +--- 3 files changed, 66 insertions(+), 45 deletions(-) diff --git a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp index 3cdc0cca1..4573027e4 100644 --- a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp +++ b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp @@ -911,12 +911,13 @@ private: if(config_.object_function) _objfunc = config_.object_function; else { - // Inside check has to be strict if no alignment was enabled. + // Inside check has to be strict if no alignment was enabled std::function ins_check; if(config_.alignment == Config::Alignment::DONT_ALIGN) ins_check = [&binbb, norm](const Box& fullbb) { double ret = 0; - if(sl::isInside(fullbb, binbb)) ret += norm; + if(sl::isInside(fullbb, binbb)) + ret += norm*norm; return ret; }; else diff --git a/src/libslic3r/ModelArrange.cpp b/src/libslic3r/ModelArrange.cpp index 572788925..d527db9da 100644 --- a/src/libslic3r/ModelArrange.cpp +++ b/src/libslic3r/ModelArrange.cpp @@ -434,8 +434,8 @@ template<> class AutoArranger: public _ArrBase { public: AutoArranger(const lnCircle& bin, Distance dist, - std::function progressind, - std::function stopcond): + std::function progressind = [](unsigned){}, + std::function stopcond = [](){return false;}): _ArrBase(bin, dist, progressind, stopcond) { // As with the box, only the inside check is different. @@ -479,8 +479,8 @@ public: template<> class AutoArranger: public _ArrBase { public: AutoArranger(const PolygonImpl& bin, Distance dist, - std::function progressind, - std::function stopcond): + std::function progressind = [](unsigned){}, + std::function stopcond = [](){return false;}): _ArrBase(bin, dist, progressind, stopcond) { m_pconf.object_function = [this, &bin] (const Item &item) { @@ -846,9 +846,9 @@ void find_new_position(const Model &model, }); for(auto it = shapemap.begin(); it != shapemap.end(); ++it) { - if(std::find(toadd.begin(), toadd.end(), it->first) == toadd.end() && - it->second.isInside(binbb)) { // just ignore items which are outside - preshapes.front().emplace_back(std::ref(it->second)); + if(std::find(toadd.begin(), toadd.end(), it->first) == toadd.end()) { + if(it->second.isInside(binbb)) // just ignore items which are outside + preshapes.front().emplace_back(std::ref(it->second)); } else { shapes_ptr.emplace_back(it->first); @@ -856,15 +856,12 @@ void find_new_position(const Model &model, } } - switch(bedhint.type) { - case BedShapeType::BOX: { - - // Create the arranger for the box shaped bed - AutoArranger arrange(binbb, min_obj_distance); - std::cout << "preload size: " << preshapes.front().size() << std::endl; - - if(!preshapes.front().empty()) arrange.preload(preshapes); - + auto try_first_to_center = [&shapes, &shapes_ptr, &binbb] + (std::function is_colliding, + std::function preload) + { + // Try to put the first item to the center, as the arranger will not + // do this for us. auto shptrit = shapes_ptr.begin(); for(auto shit = shapes.begin(); shit != shapes.end(); ++shit, ++shptrit) { @@ -873,8 +870,8 @@ void find_new_position(const Model &model, auto ibb = itm.boundingBox(); auto d = binbb.center() - ibb.center(); itm.translate(d); - if(!arrange.is_colliding(itm)) { - arrange.preload({{itm}}); + if(!is_colliding(itm)) { + preload(itm); auto offset = itm.translation(); Radians rot = itm.rotation(); @@ -892,6 +889,21 @@ void find_new_position(const Model &model, break; } } + }; + + switch(bedhint.type) { + case BedShapeType::BOX: { + + // Create the arranger for the box shaped bed + AutoArranger arrange(binbb, min_obj_distance); + + if(!preshapes.front().empty()) { // If there is something on the plate + arrange.preload(preshapes); + try_first_to_center( + [&arrange](const Item& itm) {return arrange.is_colliding(itm);}, + [&arrange](Item& itm) { arrange.preload({{itm}}); } + ); + } // Arrange and return the items with their respective indices within the // input sequence. @@ -900,26 +912,45 @@ void find_new_position(const Model &model, } case BedShapeType::CIRCLE: { -// auto c = bedhint.shape.circ; -// auto cc = to_lnCircle(c); + auto c = bedhint.shape.circ; + auto cc = to_lnCircle(c); -// AutoArranger arrange(cc, min_obj_distance, progressind, cfn); -// result = arrange(shapes.begin(), shapes.end()); + // Create the arranger for the box shaped bed + AutoArranger arrange(cc, min_obj_distance); + + if(!preshapes.front().empty()) { // If there is something on the plate + arrange.preload(preshapes); + try_first_to_center( + [&arrange](const Item& itm) {return arrange.is_colliding(itm);}, + [&arrange](Item& itm) { arrange.preload({{itm}}); } + ); + } + + // Arrange and return the items with their respective indices within the + // input sequence. + result = arrange(shapes.begin(), shapes.end()); break; } case BedShapeType::IRREGULAR: case BedShapeType::WHO_KNOWS: { + using P = libnest2d::PolygonImpl; -// using P = libnest2d::PolygonImpl; + auto ctour = Slic3rMultiPoint_to_ClipperPath(bed); + P irrbed = sl::create(std::move(ctour)); -// auto ctour = Slic3rMultiPoint_to_ClipperPath(bed); -// P irrbed = sl::create(std::move(ctour)); + AutoArranger

arrange(irrbed, min_obj_distance); -// AutoArranger

arrange(irrbed, min_obj_distance, progressind, cfn); + if(!preshapes.front().empty()) { // If there is something on the plate + arrange.preload(preshapes); + try_first_to_center( + [&arrange](const Item& itm) {return arrange.is_colliding(itm);}, + [&arrange](Item& itm) { arrange.preload({{itm}}); } + ); + } -// // Arrange and return the items with their respective indices within the -// // input sequence. -// result = arrange(shapes.begin(), shapes.end()); + // Arrange and return the items with their respective indices within the + // input sequence. + result = arrange(shapes.begin(), shapes.end()); break; } }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 45575546f..ac4988a6c 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1399,8 +1399,6 @@ std::vector Plater::priv::load_files(const std::vector& input_ if (one_by_one) { auto loaded_idxs = load_model_objects(model.objects); obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end()); - - std::cout << "New model objects added..." << std::endl; } else { // This must be an .stl or .obj file, which may contain a maximum of one volume. for (const ModelObject* model_object : model.objects) { @@ -1450,7 +1448,6 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode const BoundingBoxf bed_shape = bed_shape_bb(); const Vec3d bed_size = Slic3r::to_3d(bed_shape.size().cast(), 1.0) - 2.0 * Vec3d::Ones(); -// bool need_arrange = false; bool scaled_down = false; std::vector obj_idxs; unsigned int obj_count = model.objects.size(); @@ -1462,16 +1459,8 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode obj_idxs.push_back(obj_count++); if (model_object->instances.empty()) { - // if object has no defined position(s) we need to rearrange everything after loading -// need_arrange = true; - object->center_around_origin(); new_instances.emplace_back(object->add_instance()); - -// // add a default instance and center object around origin -// object->center_around_origin(); // also aligns object to Z = 0 -// ModelInstance* instance = object->add_instance(); -// instance->set_offset(Slic3r::to_3d(bed_shape.center().cast(), -object->origin_translation(2))); } const Vec3d size = object->bounding_box().size(); @@ -1498,7 +1487,7 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode // print.add_model_object(object); } - // FIXME distance should be a config value + // FIXME distance should be a config value ///////////////////////////////// auto min_obj_distance = static_cast(6/SCALING_FACTOR); const auto *bed_shape_opt = config->opt("bed_shape"); assert(bed_shape_opt); @@ -1506,8 +1495,8 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode Polyline bed; bed.points.reserve(bedpoints.size()); for(auto& v : bedpoints) bed.append(Point::new_scale(v(0), v(1))); - arr::find_new_position(model, new_instances, - min_obj_distance, bed); + arr::find_new_position(model, new_instances, min_obj_distance, bed); + // ///////////////////////////////////////////////////////////////////////// if (scaled_down) { GUI::show_info(q, From 22ffb93ee5c57f4a75c5325533f832b9b23e9d12 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 23 Jan 2019 14:07:54 +0100 Subject: [PATCH 06/23] import Libnest2D msvc build fix --- src/libnest2d/include/libnest2d/libnest2d.hpp | 3 +-- .../include/libnest2d/placers/placer_boilerplate.hpp | 8 +++----- src/libnest2d/include/libnest2d/selections/firstfit.hpp | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/libnest2d/include/libnest2d/libnest2d.hpp b/src/libnest2d/include/libnest2d/libnest2d.hpp index 104445a28..3d0c6f9a4 100644 --- a/src/libnest2d/include/libnest2d/libnest2d.hpp +++ b/src/libnest2d/include/libnest2d/libnest2d.hpp @@ -647,8 +647,7 @@ public: * This method makes possible to "preload" some items into the placer. It * will not move these items but will consider them as already packed. */ - template> - inline void preload(const Range& packeditems = Range()) + inline void preload(const ItemGroup& packeditems) { impl_.preload(packeditems); } diff --git a/src/libnest2d/include/libnest2d/placers/placer_boilerplate.hpp b/src/libnest2d/include/libnest2d/placers/placer_boilerplate.hpp index ef5056910..309a5007d 100644 --- a/src/libnest2d/include/libnest2d/placers/placer_boilerplate.hpp +++ b/src/libnest2d/include/libnest2d/placers/placer_boilerplate.hpp @@ -60,8 +60,7 @@ public: } template> - bool pack(Item& item, - const Range& rem = Range()) { + bool pack(Item& item, const Range& rem = Range()) { auto&& r = static_cast(this)->trypack(item, rem); if(r) { items_.push_back(*(r.item_ptr_)); @@ -70,9 +69,8 @@ public: return r; } - template> - void preload(const Range& packeditems = Range()) { - items_.insert(items_.end(), packeditems.from, packeditems.to); + void preload(const ItemGroup& packeditems) { + items_.insert(items_.end(), packeditems.begin(), packeditems.end()); farea_valid_ = false; } diff --git a/src/libnest2d/include/libnest2d/selections/firstfit.hpp b/src/libnest2d/include/libnest2d/selections/firstfit.hpp index 25fb73590..d521673b4 100644 --- a/src/libnest2d/include/libnest2d/selections/firstfit.hpp +++ b/src/libnest2d/include/libnest2d/selections/firstfit.hpp @@ -46,7 +46,7 @@ public: for(ItemGroup& ig : packed_bins_) { placers.emplace_back(bin); placers.back().configure(pconfig); - placers.back().preload({ig.begin(), ig.end()}); + placers.back().preload(ig); } std::copy(first, last, std::back_inserter(store_)); From 6819c506d8dacb389838b8e38a245eca5e52a7eb Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 23 Jan 2019 16:35:21 +0100 Subject: [PATCH 07/23] Fixing items partially outside the bed when auto-placing new items. --- .../libnest2d/backends/clipper/geometries.hpp | 1 + .../include/libnest2d/geometry_traits.hpp | 80 +++++++++++-------- src/libnest2d/include/libnest2d/libnest2d.hpp | 4 +- .../include/libnest2d/placers/nfpplacer.hpp | 18 +++-- .../include/libnest2d/utils/boost_alg.hpp | 6 +- 5 files changed, 65 insertions(+), 44 deletions(-) diff --git a/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp b/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp index c05d08d0d..9f881e7e0 100644 --- a/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp +++ b/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp @@ -113,6 +113,7 @@ template<> struct CountourType { template<> struct ShapeTag { using Type = PolygonTag; }; template<> struct ShapeTag { using Type = PathTag; }; +template<> struct ShapeTag { using Type = PointTag; }; template<> struct ShapeTag> { using Type = MultiPolygonTag; diff --git a/src/libnest2d/include/libnest2d/geometry_traits.hpp b/src/libnest2d/include/libnest2d/geometry_traits.hpp index 828044afe..917f5280d 100644 --- a/src/libnest2d/include/libnest2d/geometry_traits.hpp +++ b/src/libnest2d/include/libnest2d/geometry_traits.hpp @@ -69,12 +69,14 @@ struct PointPair { RawPoint p2; }; +struct PointTag {}; struct PolygonTag {}; struct PathTag {}; struct MultiPolygonTag {}; struct BoxTag {}; struct CircleTag {}; +/// Meta-functions to derive the tags template struct ShapeTag { using Type = typename Shape::Tag; }; template using Tag = typename ShapeTag>::Type; @@ -131,7 +133,7 @@ public: _Circle(const RawPoint& center, double r): center_(center), radius_(r) {} inline const RawPoint& center() const BP2D_NOEXCEPT { return center_; } - inline const void center(const RawPoint& c) { center_ = c; } + inline void center(const RawPoint& c) { center_ = c; } inline double radius() const BP2D_NOEXCEPT { return radius_; } inline void radius(double r) { radius_ = r; } @@ -518,21 +520,19 @@ inline bool intersects(const RawShape& /*sh*/, const RawShape& /*sh*/) return false; } -template -inline bool isInside(const TPoint& /*point*/, - const RawShape& /*shape*/) -{ - static_assert(always_false::value, - "shapelike::isInside(point, shape) unimplemented!"); +template +inline bool isInside(const TGuest&, const THost&, + const PointTag&, const PolygonTag&) { + static_assert(always_false::value, + "shapelike::isInside(point, path) unimplemented!"); return false; } -template -inline bool isInside(const RawShape& /*shape*/, - const RawShape& /*shape*/) -{ - static_assert(always_false::value, - "shapelike::isInside(shape, shape) unimplemented!"); +template +inline bool isInside(const TGuest&, const THost&, + const PolygonTag&, const PolygonTag&) { + static_assert(always_false::value, + "shapelike::isInside(shape, shape) unimplemented!"); return false; } @@ -651,7 +651,7 @@ template inline bool isConvex(const RawPath& sh, const PathTag&) template inline typename TContour::iterator -begin(RawShape& sh, const PolygonTag& t) +begin(RawShape& sh, const PolygonTag&) { return begin(contour(sh), PathTag()); } @@ -818,16 +818,16 @@ inline auto convexHull(const RawShape& sh) return convexHull(sh, Tag()); } -template -inline bool isInside(const TPoint& point, - const _Circle>& circ) +template +inline bool isInside(const TP& point, const TC& circ, + const PointTag&, const CircleTag&) { return pointlike::distance(point, circ.center()) < circ.radius(); } -template -inline bool isInside(const TPoint& point, - const _Box>& box) +template +inline bool isInside(const TP& point, const TB& box, + const PointTag&, const BoxTag&) { auto px = getX(point); auto py = getY(point); @@ -839,27 +839,27 @@ inline bool isInside(const TPoint& point, return px > minx && px < maxx && py > miny && py < maxy; } -template -inline bool isInside(const RawShape& sh, - const _Circle>& circ) +template +inline bool isInside(const RawShape& sh, const TC& circ, + const PolygonTag&, const CircleTag&) { - return std::all_of(cbegin(sh), cend(sh), - [&circ](const TPoint& p){ - return isInside(p, circ); + return std::all_of(cbegin(sh), cend(sh), [&circ](const TPoint& p) + { + return isInside(p, circ, PointTag(), CircleTag()); }); } -template -inline bool isInside(const _Box>& box, - const _Circle>& circ) +template +inline bool isInside(const TB& box, const TC& circ, + const BoxTag&, const CircleTag&) { - return isInside(box.minCorner(), circ) && - isInside(box.maxCorner(), circ); + return isInside(box.minCorner(), circ, BoxTag(), CircleTag()) && + isInside(box.maxCorner(), circ, BoxTag(), CircleTag()); } -template -inline bool isInside(const _Box>& ibb, - const _Box>& box) +template +inline bool isInside(const TBGuest& ibb, const TBHost& box, + const BoxTag&, const BoxTag&) { auto iminX = getX(ibb.minCorner()); auto imaxX = getX(ibb.maxCorner()); @@ -874,6 +874,18 @@ inline bool isInside(const _Box>& ibb, return iminX > minX && imaxX < maxX && iminY > minY && imaxY < maxY; } +template +inline bool isInside(const RawShape& poly, const TB& box, + const PolygonTag&, const BoxTag&) +{ + return isInside(boundingBox(poly), box, BoxTag(), BoxTag()); +} + +template +inline bool isInside(const TGuest& guest, const THost& host) { + return isInside(guest, host, Tag(), Tag()); +} + template // Potential O(1) implementation may exist inline TPoint& vertex(RawShape& sh, unsigned long idx, const PolygonTag&) diff --git a/src/libnest2d/include/libnest2d/libnest2d.hpp b/src/libnest2d/include/libnest2d/libnest2d.hpp index 3d0c6f9a4..49baa65f2 100644 --- a/src/libnest2d/include/libnest2d/libnest2d.hpp +++ b/src/libnest2d/include/libnest2d/libnest2d.hpp @@ -482,12 +482,12 @@ public: template inline bool _Item::isInside(const _Box>& box) const { - return sl::isInside(boundingBox(), box); + return sl::isInside(boundingBox(), box); } template inline bool _Item::isInside(const _Circle>& circ) const { - return sl::isInside(transformedShape(), circ); + return sl::isInside(transformedShape(), circ); } template using _ItemRef = std::reference_wrapper<_Item>; diff --git a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp index 4573027e4..6fb717a7a 100644 --- a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp +++ b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp @@ -916,8 +916,8 @@ private: if(config_.alignment == Config::Alignment::DONT_ALIGN) ins_check = [&binbb, norm](const Box& fullbb) { double ret = 0; - if(sl::isInside(fullbb, binbb)) - ret += norm*norm; + if(!sl::isInside(fullbb, binbb)) + ret += norm; return ret; }; else @@ -958,9 +958,10 @@ private: ecache[opt.nfpidx].coords(opt.hidx, opt.relpos); }; - auto boundaryCheck = - [&merged_pile, &getNfpPoint, &item, &bin, &iv, &startpos] - (const Optimum& o) + auto alignment = config_.alignment; + + auto boundaryCheck = [alignment, &merged_pile, &getNfpPoint, + &item, &bin, &iv, &startpos] (const Optimum& o) { auto v = getNfpPoint(o); auto d = v - iv; @@ -971,7 +972,12 @@ private: auto chull = sl::convexHull(merged_pile); merged_pile.pop_back(); - return overfit(chull, bin); + double miss = 0; + if(alignment == Config::Alignment::DONT_ALIGN) + miss = sl::isInside(chull, bin) ? -1.0 : 1.0; + else miss = overfit(chull, bin); + + return miss; }; Optimum optimum(0, 0); diff --git a/src/libnest2d/include/libnest2d/utils/boost_alg.hpp b/src/libnest2d/include/libnest2d/utils/boost_alg.hpp index c573edb47..a6988ca00 100644 --- a/src/libnest2d/include/libnest2d/utils/boost_alg.hpp +++ b/src/libnest2d/include/libnest2d/utils/boost_alg.hpp @@ -356,13 +356,15 @@ inline double area(const PolygonImpl& shape, const PolygonTag&) #endif template<> -inline bool isInside(const PointImpl& point, const PolygonImpl& shape) +inline bool isInside(const PointImpl& point, const PolygonImpl& shape, + const PointTag&, const PolygonTag&) { return boost::geometry::within(point, shape); } template<> -inline bool isInside(const PolygonImpl& sh1, const PolygonImpl& sh2) +inline bool isInside(const PolygonImpl& sh1, const PolygonImpl& sh2, + const PolygonTag&, const PolygonTag&) { return boost::geometry::within(sh1, sh2); } From d1c569dd5708811ed472c8780e325b6750e4b10a Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Thu, 24 Jan 2019 11:30:29 +0100 Subject: [PATCH 08/23] Mac: Implement Retina for the 3D scene, fix #97 --- CMakeLists.txt | 5 + src/slic3r/CMakeLists.txt | 8 +- src/slic3r/GUI/AppConfig.cpp | 5 + src/slic3r/GUI/GLCanvas3D.cpp | 242 ++++++++++++++++++-------- src/slic3r/GUI/GLCanvas3D.hpp | 36 +++- src/slic3r/GUI/ImGuiWrapper.cpp | 40 +++-- src/slic3r/GUI/ImGuiWrapper.hpp | 3 + src/slic3r/GUI/Preferences.cpp | 16 +- src/slic3r/Utils/RetinaHelper.hpp | 29 +++ src/slic3r/Utils/RetinaHelperImpl.hmm | 15 ++ src/slic3r/Utils/RetinaHelperImpl.mm | 111 ++++++++++++ 11 files changed, 421 insertions(+), 89 deletions(-) create mode 100644 src/slic3r/Utils/RetinaHelper.hpp create mode 100644 src/slic3r/Utils/RetinaHelperImpl.hmm create mode 100644 src/slic3r/Utils/RetinaHelperImpl.mm diff --git a/CMakeLists.txt b/CMakeLists.txt index fd8a27e86..c4e599f36 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -169,6 +169,11 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE endif () endif() +if (APPLE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=partial-availability -Werror=unguarded-availability -Werror=unguarded-availability-new") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=partial-availability -Werror=unguarded-availability -Werror=unguarded-availability-new") +endif () + # Where all the bundled libraries reside? set(LIBDIR ${CMAKE_CURRENT_SOURCE_DIR}/src) set(LIBDIR_BIN ${CMAKE_CURRENT_BINARY_DIR}/src) diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 783c65293..9d65a479f 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.6) include(PrecompiledHeader) -add_library(libslic3r_gui STATIC +set(SLIC3R_GUI_SOURCES pchheader.cpp pchheader.hpp GUI/AboutDialog.cpp @@ -127,6 +127,12 @@ add_library(libslic3r_gui STATIC Utils/HexFile.hpp ) +if (APPLE) + list(APPEND SLIC3R_GUI_SOURCES Utils/RetinaHelperImpl.mm) +endif () + +add_library(libslic3r_gui STATIC ${SLIC3R_GUI_SOURCES}) + target_link_libraries(libslic3r_gui libslic3r avrdude imgui) if (SLIC3R_PCH AND NOT SLIC3R_SYNTAXONLY) add_precompiled_header(libslic3r_gui pchheader.hpp FORCEINCLUDE) diff --git a/src/slic3r/GUI/AppConfig.cpp b/src/slic3r/GUI/AppConfig.cpp index 28e6e1018..a537870ee 100644 --- a/src/slic3r/GUI/AppConfig.cpp +++ b/src/slic3r/GUI/AppConfig.cpp @@ -59,6 +59,11 @@ void AppConfig::set_defaults() if (get("use_legacy_opengl").empty()) set("use_legacy_opengl", "0"); +#if __APPLE__ + if (get("use_retina_opengl").empty()) + set("use_retina_opengl", "1"); +#endif + if (get("remember_output_path").empty()) set("remember_output_path", "1"); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index a4f3f0f04..4c71ff3d8 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -9,6 +9,7 @@ #include "libslic3r/GCode/PreviewData.hpp" #include "libslic3r/Geometry.hpp" #include "libslic3r/Utils.hpp" +#include "libslic3r/Technologies.hpp" #include "slic3r/GUI/3DScene.hpp" #include "slic3r/GUI/BackgroundSlicingProcess.hpp" #include "slic3r/GUI/GLShader.hpp" @@ -20,6 +21,10 @@ #include "GUI_ObjectManipulation.hpp" #include "I18N.hpp" +#if ENABLE_RETINA_GL +#include "slic3r/Utils/RetinaHelper.hpp" +#endif + #include #include @@ -45,6 +50,7 @@ #include #include #include +#include static const float TRACKBALLSIZE = 0.8f; static const float GIMBALL_LOCK_THETA_MAX = 180.0f; @@ -59,8 +65,6 @@ static const float VIEW_BOTTOM[2] = { 0.0f, 180.0f }; static const float VIEW_FRONT[2] = { 0.0f, 90.0f }; static const float VIEW_REAR[2] = { 180.0f, 90.0f }; -static const float VARIABLE_LAYER_THICKNESS_BAR_WIDTH = 70.0f; -static const float VARIABLE_LAYER_THICKNESS_RESET_BUTTON_HEIGHT = 22.0f; static const float GIZMO_RESET_BUTTON_HEIGHT = 22.0f; static const float GIZMO_RESET_BUTTON_WIDTH = 70.f; @@ -194,9 +198,10 @@ Size::Size() { } -Size::Size(int width, int height) +Size::Size(int width, int height, float scale_factor) : m_width(width) , m_height(height) + , m_scale_factor(scale_factor) { } @@ -220,6 +225,16 @@ void Size::set_height(int height) m_height = height; } +int Size::get_scale_factor() const +{ + return m_scale_factor; +} + +void Size::set_scale_factor(int scale_factor) +{ + m_scale_factor = scale_factor; +} + Rect::Rect() : m_left(0.0f) , m_top(0.0f) @@ -869,6 +884,9 @@ GLCanvas3D::LayersEditing::~LayersEditing() delete m_slicing_parameters; } +const float GLCanvas3D::LayersEditing::THICKNESS_BAR_WIDTH = 70.0f; +const float GLCanvas3D::LayersEditing::THICKNESS_RESET_BUTTON_HEIGHT = 22.0f; + bool GLCanvas3D::LayersEditing::init(const std::string& vertex_shader_filename, const std::string& fragment_shader_filename) { if (!m_shader.init(vertex_shader_filename, fragment_shader_filename)) @@ -989,7 +1007,7 @@ Rect GLCanvas3D::LayersEditing::get_bar_rect_screen(const GLCanvas3D& canvas) float w = (float)cnv_size.get_width(); float h = (float)cnv_size.get_height(); - return Rect(w - VARIABLE_LAYER_THICKNESS_BAR_WIDTH, 0.0f, w, h - VARIABLE_LAYER_THICKNESS_RESET_BUTTON_HEIGHT); + return Rect(w - thickness_bar_width(canvas), 0.0f, w, h - reset_button_height(canvas)); } Rect GLCanvas3D::LayersEditing::get_reset_rect_screen(const GLCanvas3D& canvas) @@ -998,7 +1016,7 @@ Rect GLCanvas3D::LayersEditing::get_reset_rect_screen(const GLCanvas3D& canvas) float w = (float)cnv_size.get_width(); float h = (float)cnv_size.get_height(); - return Rect(w - VARIABLE_LAYER_THICKNESS_BAR_WIDTH, h - VARIABLE_LAYER_THICKNESS_RESET_BUTTON_HEIGHT, w, h); + return Rect(w - thickness_bar_width(canvas), h - reset_button_height(canvas), w, h); } Rect GLCanvas3D::LayersEditing::get_bar_rect_viewport(const GLCanvas3D& canvas) @@ -1010,7 +1028,7 @@ Rect GLCanvas3D::LayersEditing::get_bar_rect_viewport(const GLCanvas3D& canvas) float zoom = canvas.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; - return Rect((half_w - VARIABLE_LAYER_THICKNESS_BAR_WIDTH) * inv_zoom, half_h * inv_zoom, half_w * inv_zoom, (-half_h + VARIABLE_LAYER_THICKNESS_RESET_BUTTON_HEIGHT) * inv_zoom); + return Rect((half_w - thickness_bar_width(canvas)) * inv_zoom, half_h * inv_zoom, half_w * inv_zoom, (-half_h + reset_button_height(canvas)) * inv_zoom); } Rect GLCanvas3D::LayersEditing::get_reset_rect_viewport(const GLCanvas3D& canvas) @@ -1022,7 +1040,7 @@ Rect GLCanvas3D::LayersEditing::get_reset_rect_viewport(const GLCanvas3D& canvas float zoom = canvas.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; - return Rect((half_w - VARIABLE_LAYER_THICKNESS_BAR_WIDTH) * inv_zoom, (-half_h + VARIABLE_LAYER_THICKNESS_RESET_BUTTON_HEIGHT) * inv_zoom, half_w * inv_zoom, -half_h * inv_zoom); + return Rect((half_w - thickness_bar_width(canvas)) * inv_zoom, (-half_h + reset_button_height(canvas)) * inv_zoom, half_w * inv_zoom, -half_h * inv_zoom); } @@ -1033,6 +1051,8 @@ bool GLCanvas3D::LayersEditing::_is_initialized() const void GLCanvas3D::LayersEditing::_render_tooltip_texture(const GLCanvas3D& canvas, const Rect& bar_rect, const Rect& reset_rect) const { + // TODO: do this with ImGui + if (m_tooltip_texture.get_id() == 0) { std::string filename = resources_dir() + "/icons/variable_layer_height_tooltip.png"; @@ -1040,6 +1060,15 @@ void GLCanvas3D::LayersEditing::_render_tooltip_texture(const GLCanvas3D& canvas return; } +#if ENABLE_RETINA_GL + const float scale = canvas.get_canvas_size().get_scale_factor(); + const float width = (float)m_tooltip_texture.get_width() * scale; + const float height = (float)m_tooltip_texture.get_height() * scale; +#else + const float width = (float)m_tooltip_texture.get_width(); + const float height = (float)m_tooltip_texture.get_height(); +#endif + float zoom = canvas.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; float gap = 10.0f * inv_zoom; @@ -1047,9 +1076,9 @@ void GLCanvas3D::LayersEditing::_render_tooltip_texture(const GLCanvas3D& canvas float bar_left = bar_rect.get_left(); float reset_bottom = reset_rect.get_bottom(); - float l = bar_left - (float)m_tooltip_texture.get_width() * inv_zoom - gap; + float l = bar_left - width * inv_zoom - gap; float r = bar_left - gap; - float t = reset_bottom + (float)m_tooltip_texture.get_height() * inv_zoom + gap; + float t = reset_bottom + height * inv_zoom + gap; float b = reset_bottom + gap; GLTexture::render_texture(m_tooltip_texture.get_id(), l, r, b, t); @@ -1078,11 +1107,6 @@ void GLCanvas3D::LayersEditing::_render_active_object_annotations(const GLCanvas // The shader requires the original model coordinates when rendering to the texture, so we pass it the unit matrix m_shader.set_uniform("volume_world_matrix", UNIT_MATRIX); - GLsizei w = (GLsizei)m_layers_texture.width; - GLsizei h = (GLsizei)m_layers_texture.height; - GLsizei half_w = w / 2; - GLsizei half_h = h / 2; - ::glPixelStorei(GL_UNPACK_ALIGNMENT, 1); ::glBindTexture(GL_TEXTURE_2D, m_z_texture_id); @@ -1263,6 +1287,25 @@ void GLCanvas3D::LayersEditing::update_slicing_parameters() } } +float GLCanvas3D::LayersEditing::thickness_bar_width(const GLCanvas3D &canvas) +{ +#if ENABLE_RETINA_GL + return canvas.get_canvas_size().get_scale_factor() * THICKNESS_BAR_WIDTH; +#else + return THICKNESS_BAR_WIDTH; +#endif +} + +float GLCanvas3D::LayersEditing::reset_button_height(const GLCanvas3D &canvas) +{ +#if ENABLE_RETINA_GL + return canvas.get_canvas_size().get_scale_factor() * THICKNESS_RESET_BUTTON_HEIGHT; +#else + return THICKNESS_RESET_BUTTON_HEIGHT; +#endif +} + + const Point GLCanvas3D::Mouse::Drag::Invalid_2D_Point(INT_MAX, INT_MAX); const Vec3d GLCanvas3D::Mouse::Drag::Invalid_3D_Point(DBL_MAX, DBL_MAX, DBL_MAX); #if ENABLE_MOVE_MIN_THRESHOLD @@ -2816,14 +2859,11 @@ void GLCanvas3D::Selection::_ensure_on_bed() } #endif // ENABLE_ENSURE_ON_BED_WHILE_SCALING -const float GLCanvas3D::Gizmos::OverlayIconsScale = 1.0f; -const float GLCanvas3D::Gizmos::OverlayBorder = 5.0f; -const float GLCanvas3D::Gizmos::OverlayGapY = 5.0f * OverlayIconsScale; - GLCanvas3D::Gizmos::Gizmos() : m_enabled(false) , m_current(Undefined) { + set_overlay_scale(1.0); } GLCanvas3D::Gizmos::~Gizmos() @@ -2927,6 +2967,13 @@ void GLCanvas3D::Gizmos::set_enabled(bool enable) m_enabled = enable; } +void GLCanvas3D::Gizmos::set_overlay_scale(float scale) +{ + m_overlay_icons_scale = scale; + m_overlay_border = 5.0f * scale; + m_overlay_gap_y = 5.0f * scale; +} + std::string GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const GLCanvas3D::Selection& selection) { std::string name = ""; @@ -2936,22 +2983,22 @@ std::string GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, con float cnv_h = (float)canvas.get_canvas_size().get_height(); float height = _get_total_overlay_height(); - float top_y = 0.5f * (cnv_h - height) + OverlayBorder; + float top_y = 0.5f * (cnv_h - height) + m_overlay_border; for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) { if ((it->second == nullptr) || !it->second->is_selectable()) continue; - float icon_size = (float)it->second->get_textures_size() * OverlayIconsScale; + float icon_size = (float)it->second->get_textures_size() * m_overlay_icons_scale; - bool inside = (OverlayBorder <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= OverlayBorder + icon_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + icon_size); + bool inside = (m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + icon_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + icon_size); if (inside) name = it->second->get_name(); if (it->second->is_activable(selection) && (it->second->get_state() != GLGizmoBase::On)) it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off); - top_y += (icon_size + OverlayGapY); + top_y += (icon_size + m_overlay_gap_y); } return name; @@ -2964,15 +3011,15 @@ void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Vec float cnv_h = (float)canvas.get_canvas_size().get_height(); float height = _get_total_overlay_height(); - float top_y = 0.5f * (cnv_h - height) + OverlayBorder; + float top_y = 0.5f * (cnv_h - height) + m_overlay_border; for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) { if ((it->second == nullptr) || !it->second->is_selectable()) continue; - float icon_size = (float)it->second->get_textures_size() * OverlayIconsScale; + float icon_size = (float)it->second->get_textures_size() * m_overlay_icons_scale; - bool inside = (OverlayBorder <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= OverlayBorder + icon_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + icon_size); + bool inside = (m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + icon_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + icon_size); if (it->second->is_activable(selection) && inside) { if ((it->second->get_state() == GLGizmoBase::On)) @@ -2989,7 +3036,7 @@ void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Vec else it->second->set_state(GLGizmoBase::Off); - top_y += (icon_size + OverlayGapY); + top_y += (icon_size + m_overlay_gap_y); } GizmosMap::iterator it = m_gizmos.find(m_current); @@ -3061,18 +3108,18 @@ bool GLCanvas3D::Gizmos::overlay_contains_mouse(const GLCanvas3D& canvas, const float cnv_h = (float)canvas.get_canvas_size().get_height(); float height = _get_total_overlay_height(); - float top_y = 0.5f * (cnv_h - height) + OverlayBorder; + float top_y = 0.5f * (cnv_h - height) + m_overlay_border; for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) { if ((it->second == nullptr) || !it->second->is_selectable()) continue; - float icon_size = (float)it->second->get_textures_size() * OverlayIconsScale; + float icon_size = (float)it->second->get_textures_size() * m_overlay_icons_scale; - if ((OverlayBorder <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= OverlayBorder + icon_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + icon_size)) + if ((m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + icon_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + icon_size)) return true; - top_y += (icon_size + OverlayGapY); + top_y += (icon_size + m_overlay_gap_y); } return false; @@ -3345,7 +3392,7 @@ void GLCanvas3D::Gizmos::_render_overlay(const GLCanvas3D& canvas, const GLCanva float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; float height = _get_total_overlay_height(); - float scaled_border = OverlayBorder * inv_zoom; + float scaled_border = m_overlay_border * inv_zoom; float top_x = (-0.5f * cnv_w) * inv_zoom; float top_y = (0.5f * height) * inv_zoom; @@ -3390,7 +3437,7 @@ void GLCanvas3D::Gizmos::_render_overlay(const GLCanvas3D& canvas, const GLCanva bg_uv_left = bg_uv_i_left; bg_i_left = bg_left; - if ((OverlayBorder > 0) && (bg_uv_top != bg_uv_i_top)) + if ((m_overlay_border > 0) && (bg_uv_top != bg_uv_i_top)) { if (bg_uv_left != bg_uv_i_left) GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_i_top, bg_top, { { bg_uv_left, bg_uv_i_top }, { bg_uv_i_left, bg_uv_i_top }, { bg_uv_i_left, bg_uv_top }, { bg_uv_left, bg_uv_top } }); @@ -3401,15 +3448,15 @@ void GLCanvas3D::Gizmos::_render_overlay(const GLCanvas3D& canvas, const GLCanva GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_i_top, bg_top, { { bg_uv_i_right, bg_uv_i_top }, { bg_uv_right, bg_uv_i_top }, { bg_uv_right, bg_uv_top }, { bg_uv_i_right, bg_uv_top } }); } - if ((OverlayBorder > 0) && (bg_uv_left != bg_uv_i_left)) + if ((m_overlay_border > 0) && (bg_uv_left != bg_uv_i_left)) GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_i_bottom, bg_i_top, { { bg_uv_left, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_top }, { bg_uv_left, bg_uv_i_top } }); GLTexture::render_sub_texture(bg_tex_id, bg_i_left, bg_i_right, bg_i_bottom, bg_i_top, { { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_top }, { bg_uv_i_left, bg_uv_i_top } }); - if ((OverlayBorder > 0) && (bg_uv_right != bg_uv_i_right)) + if ((m_overlay_border > 0) && (bg_uv_right != bg_uv_i_right)) GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_i_bottom, bg_i_top, { { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_right, bg_uv_i_bottom }, { bg_uv_right, bg_uv_i_top }, { bg_uv_i_right, bg_uv_i_top } }); - if ((OverlayBorder > 0) && (bg_uv_bottom != bg_uv_i_bottom)) + if ((m_overlay_border > 0) && (bg_uv_bottom != bg_uv_i_bottom)) { if (bg_uv_left != bg_uv_i_left) GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_bottom, bg_i_bottom, { { bg_uv_left, bg_uv_bottom }, { bg_uv_i_left, bg_uv_bottom }, { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_left, bg_uv_i_bottom } }); @@ -3421,19 +3468,19 @@ void GLCanvas3D::Gizmos::_render_overlay(const GLCanvas3D& canvas, const GLCanva } } - top_x += OverlayBorder * inv_zoom; - top_y -= OverlayBorder * inv_zoom; - float scaled_gap_y = OverlayGapY * inv_zoom; + top_x += m_overlay_border * inv_zoom; + top_y -= m_overlay_border * inv_zoom; + float scaled_gap_y = m_overlay_gap_y * inv_zoom; for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) { if ((it->second == nullptr) || !it->second->is_selectable()) continue; - float icon_size = (float)it->second->get_textures_size() * OverlayIconsScale * inv_zoom; + float icon_size = (float)it->second->get_textures_size() * m_overlay_icons_scale * inv_zoom; GLTexture::render_texture(it->second->get_texture_id(), top_x, top_x + icon_size, top_y - icon_size, top_y); #if ENABLE_IMGUI if (it->second->get_state() == GLGizmoBase::On) - it->second->render_input_window(2.0f * OverlayBorder + icon_size * zoom, 0.5f * cnv_h - top_y * zoom, selection); + it->second->render_input_window(2.0f * m_overlay_border + icon_size * zoom, 0.5f * cnv_h - top_y * zoom, selection); #endif // ENABLE_IMGUI top_y -= (icon_size + scaled_gap_y); } @@ -3448,17 +3495,17 @@ void GLCanvas3D::Gizmos::_render_current_gizmo(const GLCanvas3D::Selection& sele float GLCanvas3D::Gizmos::_get_total_overlay_height() const { - float height = 2.0f * OverlayBorder; + float height = 2.0f * m_overlay_border; for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) { if ((it->second == nullptr) || !it->second->is_selectable()) continue; - height += (float)it->second->get_textures_size() * OverlayIconsScale + OverlayGapY; + height += (float)it->second->get_textures_size() * m_overlay_icons_scale + m_overlay_gap_y; } - return height - OverlayGapY; + return height - m_overlay_gap_y; } float GLCanvas3D::Gizmos::_get_total_overlay_width() const @@ -3469,10 +3516,10 @@ float GLCanvas3D::Gizmos::_get_total_overlay_width() const if ((it->second == nullptr) || !it->second->is_selectable()) continue; - max_icon_width = std::max(max_icon_width, (float)it->second->get_textures_size() * OverlayIconsScale); + max_icon_width = std::max(max_icon_width, (float)it->second->get_textures_size() * m_overlay_icons_scale); } - return max_icon_width + 2.0f * OverlayBorder; + return max_icon_width + 2.0f * m_overlay_border; } GLGizmoBase* GLCanvas3D::Gizmos::_get_current() const @@ -3491,7 +3538,7 @@ GLCanvas3D::WarningTexture::WarningTexture() { } -bool GLCanvas3D::WarningTexture::generate(const std::string& msg) +bool GLCanvas3D::WarningTexture::generate(const std::string& msg, const GLCanvas3D& canvas) { reset(); @@ -3500,7 +3547,8 @@ bool GLCanvas3D::WarningTexture::generate(const std::string& msg) wxMemoryDC memDC; // select default font - wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + const float scale = canvas.get_canvas_size().get_scale_factor(); + wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Scale(scale); font.MakeLarger(); font.MakeBold(); memDC.SetFont(font); @@ -3648,9 +3696,18 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c wxMemoryDC memDC; wxMemoryDC mask_memDC; + // calculate scaling + const float scale = canvas.get_canvas_size().get_scale_factor(); + const int scaled_square = std::floor((float)Px_Square * scale); + const int scaled_title_offset = Px_Title_Offset * scale; + const int scaled_text_offset = Px_Text_Offset * scale; + const int scaled_square_contour = Px_Square_Contour * scale; + const int scaled_border = Px_Border * scale; + // select default font - memDC.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); - mask_memDC.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); + const wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Scale(scale); + memDC.SetFont(font); + mask_memDC.SetFont(font); // calculates texture size wxCoord w, h; @@ -3667,10 +3724,10 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c max_text_height = std::max(max_text_height, (int)h); } - m_original_width = std::max(2 * Px_Border + title_width, 2 * (Px_Border + Px_Square_Contour) + Px_Square + Px_Text_Offset + max_text_width); - m_original_height = 2 * (Px_Border + Px_Square_Contour) + title_height + Px_Title_Offset + items_count * Px_Square; + m_original_width = std::max(2 * scaled_border + title_width, 2 * (scaled_border + scaled_square_contour) + scaled_square + scaled_text_offset + max_text_width); + m_original_height = 2 * (scaled_border + scaled_square_contour) + title_height + scaled_title_offset + items_count * scaled_square; if (items_count > 1) - m_original_height += (items_count - 1) * Px_Square_Contour; + m_original_height += (items_count - 1) * scaled_square_contour; int pow_of_two_size = (int)next_highest_power_of_2(std::max(m_original_width, m_original_height)); @@ -3694,8 +3751,8 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c memDC.SetTextForeground(use_error_colors ? *wxWHITE : *wxBLACK); mask_memDC.SetTextForeground(*wxWHITE); - int title_x = Px_Border; - int title_y = Px_Border; + int title_x = scaled_border; + int title_y = scaled_border; memDC.DrawText(title, title_x, title_y); mask_memDC.DrawText(title, title_x, title_y); @@ -3703,12 +3760,12 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c mask_memDC.SetBrush(wxBrush(*wxWHITE)); // draw icons contours as background - int squares_contour_x = Px_Border; - int squares_contour_y = Px_Border + title_height + Px_Title_Offset; - int squares_contour_width = Px_Square + 2 * Px_Square_Contour; - int squares_contour_height = items_count * Px_Square + 2 * Px_Square_Contour; + int squares_contour_x = scaled_border; + int squares_contour_y = scaled_border + title_height + scaled_title_offset; + int squares_contour_width = scaled_square + 2 * scaled_square_contour; + int squares_contour_height = items_count * scaled_square + 2 * scaled_square_contour; if (items_count > 1) - squares_contour_height += (items_count - 1) * Px_Square_Contour; + squares_contour_height += (items_count - 1) * scaled_square_contour; wxColour color(Squares_Border_Color[0], Squares_Border_Color[1], Squares_Border_Color[2]); wxPen pen(color); @@ -3719,15 +3776,15 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c mask_memDC.DrawRectangle(wxRect(squares_contour_x, squares_contour_y, squares_contour_width, squares_contour_height)); // draw items (colored icon + text) - int icon_x = squares_contour_x + Px_Square_Contour; + int icon_x = squares_contour_x + scaled_square_contour; int icon_x_inner = icon_x + 1; - int icon_y = squares_contour_y + Px_Square_Contour; - int icon_y_step = Px_Square + Px_Square_Contour; + int icon_y = squares_contour_y + scaled_square_contour; + int icon_y_step = scaled_square + scaled_square_contour; - int text_x = icon_x + Px_Square + Px_Text_Offset; - int text_y_offset = (Px_Square - max_text_height) / 2; + int text_x = icon_x + scaled_square + scaled_text_offset; + int text_y_offset = (scaled_square - max_text_height) / 2; - int px_inner_square = Px_Square - 2; + int px_inner_square = scaled_square - 2; for (const GCodePreviewData::LegendItem& item : items) { @@ -3741,7 +3798,7 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c brush.SetColour(color); memDC.SetPen(pen); memDC.SetBrush(brush); - memDC.DrawRectangle(wxRect(icon_x, icon_y, Px_Square, Px_Square)); + memDC.DrawRectangle(wxRect(icon_x, icon_y, scaled_square, scaled_square)); // draw icon interior color.Set(item_color_bytes[0], item_color_bytes[1], item_color_bytes[2], item_color_bytes[3]); @@ -3850,6 +3907,9 @@ wxDEFINE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent); GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) : m_canvas(canvas) , m_context(nullptr) +#if ENABLE_RETINA_GL + , m_retina_helper(nullptr) +#endif , m_in_render(false) , m_toolbar(GLToolbar::Normal) , m_view_toolbar(nullptr) @@ -3889,6 +3949,15 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) m_context = new wxGLContext(m_canvas); #endif // !ENABLE_USE_UNIQUE_GLCONTEXT m_timer.SetOwner(m_canvas); + +#if ENABLE_RETINA_GL + m_retina_helper.reset(new RetinaHelper(canvas)); + + const bool use_retina = wxGetApp().app_config->get("use_retina_opengl") == "1"; + BOOST_LOG_TRIVIAL(debug) << "GLCanvas3D: Use Retina OpenGL: " << use_retina; + m_retina_helper->set_use_retina(use_retina); + BOOST_LOG_TRIVIAL(debug) << "GLCanvas3D: Scaling factor: " << m_retina_helper->get_scale_factor(); +#endif } m_selection.set_volumes(&m_volumes.volumes); @@ -5063,6 +5132,12 @@ void GLCanvas3D::on_timer(wxTimerEvent& evt) void GLCanvas3D::on_mouse(wxMouseEvent& evt) { +#if ENABLE_RETINA_GL + const float scale = m_retina_helper->get_scale_factor(); + evt.SetX(evt.GetX() * scale); + evt.SetY(evt.GetY() * scale); +#endif + #if ENABLE_IMGUI auto imgui = wxGetApp().imgui(); if (imgui->update_mouse_data(evt)) { @@ -5552,7 +5627,15 @@ Size GLCanvas3D::get_canvas_size() const if (m_canvas != nullptr) m_canvas->GetSize(&w, &h); - return Size(w, h); +#if ENABLE_RETINA_GL + const float factor = m_retina_helper->get_scale_factor(); + w *= factor; + h *= factor; +#else + const float factor = 1.0; +#endif + + return Size(w, h, factor); } Point GLCanvas3D::get_local_mouse_position() const @@ -6019,6 +6102,9 @@ void GLCanvas3D::_resize(unsigned int w, unsigned int h) #if ENABLE_IMGUI wxGetApp().imgui()->set_display_size((float)w, (float)h); +#if ENABLE_RETINA_GL + wxGetApp().imgui()->set_style_scaling(m_retina_helper->get_scale_factor()); +#endif // ENABLE_RETINA_GL #endif // ENABLE_IMGUI // ensures that this canvas is current @@ -6497,18 +6583,28 @@ void GLCanvas3D::_render_current_gizmo() const void GLCanvas3D::_render_gizmos_overlay() const { +#if ENABLE_RETINA_GL + m_gizmos.set_overlay_scale(m_retina_helper->get_scale_factor()); +#endif m_gizmos.render_overlay(*this, m_selection); } void GLCanvas3D::_render_toolbar() const { +#if ENABLE_RETINA_GL + m_toolbar.set_icons_scale(m_retina_helper->get_scale_factor()); +#endif m_toolbar.render(*this); } void GLCanvas3D::_render_view_toolbar() const { - if (m_view_toolbar != nullptr) + if (m_view_toolbar != nullptr) { +#if ENABLE_RETINA_GL + m_view_toolbar->set_icons_scale(m_retina_helper->get_scale_factor()); +#endif m_view_toolbar->render(*this); + } } #if ENABLE_SHOW_CAMERA_TARGET @@ -8224,7 +8320,7 @@ void GLCanvas3D::_generate_warning_texture(const std::string& msg) return; #endif // !ENABLE_USE_UNIQUE_GLCONTEXT - m_warning_texture.generate(msg); + m_warning_texture.generate(msg, *this); } void GLCanvas3D::_reset_warning_texture() @@ -8254,6 +8350,10 @@ void GLCanvas3D::_resize_toolbars() const float zoom = get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; +#if ENABLE_RETINA_GL + m_toolbar.set_icons_scale(m_retina_helper->get_scale_factor()); +#endif + GLToolbar::Layout::EOrientation orientation = m_toolbar.get_layout_orientation(); switch (m_toolbar.get_layout_type()) @@ -8297,6 +8397,10 @@ void GLCanvas3D::_resize_toolbars() const if (m_view_toolbar != nullptr) { +#if ENABLE_RETINA_GL + m_view_toolbar->set_icons_scale(m_retina_helper->get_scale_factor()); +#endif + // places the toolbar on the bottom-left corner of the 3d scene float top = (-0.5f * (float)cnv_size.get_height() + m_view_toolbar->get_height()) * inv_zoom; float left = -0.5f * (float)cnv_size.get_width() * inv_zoom; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 1ca9c234f..5d9aafd80 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -2,7 +2,9 @@ #define slic3r_GLCanvas3D_hpp_ #include +#include +#include "libslic3r/Technologies.hpp" #include "3DScene.hpp" #include "GLToolbar.hpp" #include "Event.hpp" @@ -20,6 +22,9 @@ class wxTimerEvent; class wxPaintEvent; class wxGLCanvas; +// Support for Retina OpenGL on Mac OS +#define ENABLE_RETINA_GL __APPLE__ + class GLUquadric; typedef class GLUquadric GLUquadricObj; @@ -36,6 +41,10 @@ namespace GUI { class GLGizmoBase; +#if ENABLE_RETINA_GL +class RetinaHelper; +#endif + class GeometryBuffer { std::vector m_vertices; @@ -55,16 +64,20 @@ class Size { int m_width; int m_height; + float m_scale_factor; public: Size(); - Size(int width, int height); + Size(int width, int height, float scale_factor = 1.0); int get_width() const; void set_width(int width); int get_height() const; void set_height(int height); + + int get_scale_factor() const; + void set_scale_factor(int height); }; class Rect @@ -297,6 +310,9 @@ class GLCanvas3D }; private: + static const float THICKNESS_BAR_WIDTH; + static const float THICKNESS_RESET_BUTTON_HEIGHT; + bool m_use_legacy_opengl; bool m_enabled; Shader m_shader; @@ -380,6 +396,9 @@ class GLCanvas3D void _render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) const; void _render_profile(const Rect& bar_rect) const; void update_slicing_parameters(); + + static float thickness_bar_width(const GLCanvas3D &canvas); + static float reset_button_height(const GLCanvas3D &canvas); }; struct Mouse @@ -690,10 +709,6 @@ public: private: class Gizmos { - static const float OverlayIconsScale; - static const float OverlayBorder; - static const float OverlayGapY; - public: enum EType : unsigned char { @@ -714,6 +729,10 @@ private: BackgroundTexture m_background_texture; EType m_current; + float m_overlay_icons_scale; + float m_overlay_border; + float m_overlay_gap_y; + public: Gizmos(); ~Gizmos(); @@ -723,6 +742,8 @@ private: bool is_enabled() const; void set_enabled(bool enable); + void set_overlay_scale(float scale); + std::string update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection); void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection); void update_on_off_state(const Selection& selection); @@ -812,7 +833,7 @@ private: public: WarningTexture(); - bool generate(const std::string& msg); + bool generate(const std::string& msg, const GLCanvas3D& canvas); void render(const GLCanvas3D& canvas) const; }; @@ -842,6 +863,9 @@ private: wxGLCanvas* m_canvas; wxGLContext* m_context; +#if ENABLE_RETINA_GL + std::unique_ptr m_retina_helper; +#endif bool m_in_render; LegendTexture m_legend_texture; WarningTexture m_warning_texture; diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index 7ce34d4e2..ed2654f51 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -2,6 +2,8 @@ #include #include +#include +#include #include #include @@ -24,6 +26,7 @@ namespace GUI { ImGuiWrapper::ImGuiWrapper() : m_font_texture(0) + , m_style_scaling(1.0) , m_mouse_buttons(0) , m_disabled(false) { @@ -39,18 +42,9 @@ bool ImGuiWrapper::init() { ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); - ImFont* font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/NotoSans-Regular.ttf").c_str(), 18.0f); - if (font == nullptr) { - font = io.Fonts->AddFontDefault(); - if (font == nullptr) - return false; - } - else { - m_fonts.insert(FontsMap::value_type("Noto Sans Regular 18", font)); - } + init_default_font(m_style_scaling); - io.IniFilename = nullptr; + ImGui::GetIO().IniFilename = nullptr; return true; } @@ -62,6 +56,15 @@ void ImGuiWrapper::set_display_size(float w, float h) io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f); } +void ImGuiWrapper::set_style_scaling(float scaling) +{ + if (!std::isnan(scaling) && !std::isinf(scaling) && scaling != m_style_scaling) { + ImGui::GetStyle().ScaleAllSizes(scaling / m_style_scaling); + init_default_font(scaling); + m_style_scaling = scaling; + } +} + bool ImGuiWrapper::update_mouse_data(wxMouseEvent& evt) { ImGuiIO& io = ImGui::GetIO(); @@ -198,6 +201,21 @@ bool ImGuiWrapper::want_any_input() const return io.WantCaptureMouse || io.WantCaptureKeyboard || io.WantTextInput; } +void ImGuiWrapper::init_default_font(float scaling) +{ + static const float font_size = 18.0f; + + ImGuiIO& io = ImGui::GetIO(); + io.Fonts->Clear(); + ImFont* font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/NotoSans-Regular.ttf").c_str(), font_size * scaling); + if (font == nullptr) { + font = io.Fonts->AddFontDefault(); + if (font == nullptr) { + throw std::runtime_error("ImGui: Could not load deafult font"); + } + } +} + void ImGuiWrapper::create_device_objects() { create_fonts_texture(); diff --git a/src/slic3r/GUI/ImGuiWrapper.hpp b/src/slic3r/GUI/ImGuiWrapper.hpp index 5293bee26..47a1fb937 100644 --- a/src/slic3r/GUI/ImGuiWrapper.hpp +++ b/src/slic3r/GUI/ImGuiWrapper.hpp @@ -21,6 +21,7 @@ class ImGuiWrapper FontsMap m_fonts; unsigned m_font_texture; + float m_style_scaling; unsigned m_mouse_buttons; bool m_disabled; @@ -32,6 +33,7 @@ public: void read_glsl_version(); void set_display_size(float w, float h); + void set_style_scaling(float scaling); bool update_mouse_data(wxMouseEvent &evt); void new_frame(); @@ -58,6 +60,7 @@ public: bool want_text_input() const; bool want_any_input() const; private: + void init_default_font(float scaling); void create_device_objects(); void create_fonts_texture(); void render_draw_data(ImDrawData *draw_data); diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 5f5da8bd4..2aa5ecadd 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -87,6 +87,7 @@ void PreferencesDialog::build() option = Option (def,"show_incompatible_presets"); m_optgroup->append_single_option_line(option); + // TODO: remove? def.label = L("Use legacy OpenGL 1.1 rendering"); def.type = coBool; def.tooltip = L("If you have rendering issues caused by a buggy OpenGL 2.0 driver, " @@ -96,6 +97,16 @@ void PreferencesDialog::build() option = Option (def,"use_legacy_opengl"); m_optgroup->append_single_option_line(option); +#if __APPLE__ + def.label = L("Use Retina resolution for the 3D scene"); + def.type = coBool; + def.tooltip = L("If enabled, the 3D scene will be rendered in Retina resolution. " + "If you are experiencing 3D performance problems, disabling this option may help."); + def.default_value = new ConfigOptionBool{ app_config->get("use_retina_opengl") == "1" }; + option = Option (def, "use_retina_opengl"); + m_optgroup->append_single_option_line(option); +#endif + auto sizer = new wxBoxSizer(wxVERTICAL); sizer->Add(m_optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10); @@ -110,8 +121,9 @@ void PreferencesDialog::build() void PreferencesDialog::accept() { - if (m_values.find("no_defaults") != m_values.end()|| - m_values.find("use_legacy_opengl")!= m_values.end()) { + if (m_values.find("no_defaults") != m_values.end() || + m_values.find("use_legacy_opengl") != m_values.end() || + m_values.find("use_retina_opengl") != m_values.end()) { warning_catcher(this, _(L("You need to restart Slic3r to make the changes effective."))); } diff --git a/src/slic3r/Utils/RetinaHelper.hpp b/src/slic3r/Utils/RetinaHelper.hpp new file mode 100644 index 000000000..659bc7f56 --- /dev/null +++ b/src/slic3r/Utils/RetinaHelper.hpp @@ -0,0 +1,29 @@ +#ifndef slic3r_RetinaHelper_hpp_ +#define slic3r_RetinaHelper_hpp_ + +class wxWindow; + + +namespace Slic3r { +namespace GUI { + +class RetinaHelper +{ +public: + RetinaHelper(wxWindow* window); + ~RetinaHelper(); + + void set_use_retina(bool value); + bool get_use_retina(); + float get_scale_factor(); + +private: + wxWindow* m_window; + void* m_self; +}; + + +} // namespace GUI +} // namespace Slic3r + +#endif // RetinaHelper_h diff --git a/src/slic3r/Utils/RetinaHelperImpl.hmm b/src/slic3r/Utils/RetinaHelperImpl.hmm new file mode 100644 index 000000000..0edde2990 --- /dev/null +++ b/src/slic3r/Utils/RetinaHelperImpl.hmm @@ -0,0 +1,15 @@ +#import + +class wxEvtHandler; + +@interface RetinaHelperImpl : NSObject +{ + NSView *view; + wxEvtHandler* handler; +} + +-(id)initWithView:(NSView *)view handler:(wxEvtHandler *)handler; +-(void)setViewWantsBestResolutionOpenGLSurface:(BOOL)value; +-(BOOL)getViewWantsBestResolutionOpenGLSurface; +-(float)getBackingScaleFactor; +@end diff --git a/src/slic3r/Utils/RetinaHelperImpl.mm b/src/slic3r/Utils/RetinaHelperImpl.mm new file mode 100644 index 000000000..de0402d34 --- /dev/null +++ b/src/slic3r/Utils/RetinaHelperImpl.mm @@ -0,0 +1,111 @@ +// The RetinaHelper was originally written by Andreas Stahl, 2013 + +#import "RetinaHelper.hpp" +#import "RetinaHelperImpl.hmm" +#import + +#import "wx/window.h" + +@implementation RetinaHelperImpl + +namespace Slic3r { +namespace GUI { + +RetinaHelper::RetinaHelper(wxWindow* window) : + m_window(window) +{ + m_self = nullptr; + m_self = [[RetinaHelperImpl alloc] initWithView:window->GetHandle() handler:window->GetEventHandler()]; +} + +RetinaHelper::~RetinaHelper() +{ + [m_self release]; +} + +void RetinaHelper::set_use_retina(bool aValue) +{ + [(id)m_self setViewWantsBestResolutionOpenGLSurface:aValue]; +} + +bool RetinaHelper::get_use_retina() +{ + return [(id)m_self getViewWantsBestResolutionOpenGLSurface]; +} + +float RetinaHelper::get_scale_factor() +{ + return [(id)m_self getViewWantsBestResolutionOpenGLSurface] ? [(id)m_self getBackingScaleFactor] : 1.0f; +} + +} // namespace GUI +} // namespace Slic3r + + +-(id)initWithView:(NSView *)aView handler:(wxEvtHandler *)aHandler +{ + self = [super init]; + if (self) { + handler = aHandler; + view = aView; + // register for backing change notifications + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + if (nc) { + [nc addObserver:self selector:@selector(windowDidChangeBackingProperties:) + name:NSWindowDidChangeBackingPropertiesNotification object:nil]; + } + } + return self; +} + +-(void) dealloc +{ + // unregister from all notifications + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + if (nc) { + [nc removeObserver:self]; + } + [super dealloc]; +} + +-(void)setViewWantsBestResolutionOpenGLSurface:(BOOL)value +{ + [view setWantsBestResolutionOpenGLSurface:value]; +} + +-(BOOL)getViewWantsBestResolutionOpenGLSurface +{ + return [view wantsBestResolutionOpenGLSurface]; +} + +-(float)getBackingScaleFactor +{ + return [[view window] backingScaleFactor]; +} + +- (void)windowDidChangeBackingProperties:(NSNotification *)notification +{ + NSWindow *theWindow = (NSWindow *)[notification object]; + + if (theWindow == [view window]) { + CGFloat newBackingScaleFactor = [theWindow backingScaleFactor]; + CGFloat oldBackingScaleFactor = [[[notification userInfo] + objectForKey:@"NSBackingPropertyOldScaleFactorKey"] + doubleValue]; + + if (newBackingScaleFactor != oldBackingScaleFactor) { + // generate a wx resize event and pass it to the handler's queue + wxSizeEvent *event = new wxSizeEvent(); + // use the following line if this resize event should have the physical pixel resolution + // but that is not recommended, because ordinary resize events won't do so either + // which would necessitate a case-by-case switch in the resize handler method. + // NSRect nsrect = [view convertRectToBacking:[view bounds]]; + NSRect nsrect = [view bounds]; + wxRect rect = wxRect(nsrect.origin.x, nsrect.origin.y, nsrect.size.width, nsrect.size.height); + event->SetRect(rect); + event->SetSize(rect.GetSize()); + handler->QueueEvent(event); + } + } +} +@end From 3df1ed8f6b3dcda7f615db33bfee7eb721db8e5c Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Thu, 24 Jan 2019 13:16:46 +0100 Subject: [PATCH 09/23] Mac: Retina OpenGL: Fix ImGui font switch, dynamic switching, toolbar fixes --- src/slic3r/GUI/GLCanvas3D.cpp | 25 ++++++++++++++++++++----- src/slic3r/GUI/GLCanvas3D.hpp | 2 ++ src/slic3r/GUI/GLToolbar.cpp | 32 +++++++++++++++++++------------- src/slic3r/GUI/GUI_Preview.hpp | 1 + src/slic3r/GUI/ImGuiWrapper.cpp | 2 ++ src/slic3r/GUI/Plater.cpp | 5 +++++ src/slic3r/GUI/Preferences.cpp | 3 +-- 7 files changed, 50 insertions(+), 20 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 4c71ff3d8..cfb7d3dce 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3952,11 +3952,6 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) #if ENABLE_RETINA_GL m_retina_helper.reset(new RetinaHelper(canvas)); - - const bool use_retina = wxGetApp().app_config->get("use_retina_opengl") == "1"; - BOOST_LOG_TRIVIAL(debug) << "GLCanvas3D: Use Retina OpenGL: " << use_retina; - m_retina_helper->set_use_retina(use_retina); - BOOST_LOG_TRIVIAL(debug) << "GLCanvas3D: Scaling factor: " << m_retina_helper->get_scale_factor(); #endif } @@ -5947,6 +5942,26 @@ void GLCanvas3D::handle_sidebar_focus_event(const std::string& opt_key, bool foc } } +void GLCanvas3D::update_ui_from_settings() +{ +#if ENABLE_RETINA_GL + const float orig_scaling = m_retina_helper->get_scale_factor(); + + const bool use_retina = wxGetApp().app_config->get("use_retina_opengl") == "1"; + BOOST_LOG_TRIVIAL(debug) << "GLCanvas3D: Use Retina OpenGL: " << use_retina; + m_retina_helper->set_use_retina(use_retina); + const float new_scaling = m_retina_helper->get_scale_factor(); + + if (new_scaling != orig_scaling) { + BOOST_LOG_TRIVIAL(debug) << "GLCanvas3D: Scaling factor: " << new_scaling; + + m_camera.zoom /= orig_scaling; + m_camera.zoom *= new_scaling; + _refresh_if_shown_on_screen(); + } +#endif +} + bool GLCanvas3D::_is_shown_on_screen() const { return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 5d9aafd80..0f998276d 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -1070,6 +1070,8 @@ public: void handle_sidebar_focus_event(const std::string& opt_key, bool focus_on); + void update_ui_from_settings(); + private: bool _is_shown_on_screen() const; #if !ENABLE_REWORKED_BED_SHAPE_CHANGE diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index 8a9c12f26..e9ca9a6b1 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -468,12 +468,12 @@ float GLToolbar::get_width_horizontal() const float GLToolbar::get_width_vertical() const { - return 2.0f * m_layout.border + m_icons_texture.metadata.icon_size * m_layout.icons_scale; + return 2.0f * m_layout.border * m_layout.icons_scale + m_icons_texture.metadata.icon_size * m_layout.icons_scale; } float GLToolbar::get_height_horizontal() const { - return 2.0f * m_layout.border + m_icons_texture.metadata.icon_size * m_layout.icons_scale; + return 2.0f * m_layout.border * m_layout.icons_scale + m_icons_texture.metadata.icon_size * m_layout.icons_scale; } float GLToolbar::get_height_vertical() const @@ -483,23 +483,25 @@ float GLToolbar::get_height_vertical() const float GLToolbar::get_main_size() const { - float size = 2.0f * m_layout.border; + float size = 2.0f * m_layout.border * m_layout.icons_scale; for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i) { if (m_items[i]->is_separator()) - size += m_layout.separator_size; + size += m_layout.separator_size * m_layout.icons_scale; else size += (float)m_icons_texture.metadata.icon_size * m_layout.icons_scale; } if (m_items.size() > 1) - size += ((float)m_items.size() - 1.0f) * m_layout.gap_size; + size += ((float)m_items.size() - 1.0f) * m_layout.gap_size * m_layout.icons_scale; return size; } std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent) { + // Note: m_layout.icons_scale is not applied here because mouse_pos is already in scaled coordinates + float zoom = parent.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; @@ -591,6 +593,8 @@ std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLC std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D& parent) { + // Note: m_layout.icons_scale is not applied here because mouse_pos is already in scaled coordinates + float zoom = parent.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; @@ -774,11 +778,12 @@ void GLToolbar::render_horizontal(const GLCanvas3D& parent) const float zoom = parent.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; + float factor = inv_zoom * m_layout.icons_scale; - float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_layout.icons_scale * inv_zoom; - float scaled_separator_size = m_layout.separator_size * inv_zoom; - float scaled_gap_size = m_layout.gap_size * inv_zoom; - float scaled_border = m_layout.border * inv_zoom; + float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * factor; + float scaled_separator_size = m_layout.separator_size * factor; + float scaled_gap_size = m_layout.gap_size * factor; + float scaled_border = m_layout.border * factor; float scaled_width = get_width() * inv_zoom; float scaled_height = get_height() * inv_zoom; @@ -899,11 +904,12 @@ void GLToolbar::render_vertical(const GLCanvas3D& parent) const float zoom = parent.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; + float factor = inv_zoom * m_layout.icons_scale; - float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_layout.icons_scale * inv_zoom; - float scaled_separator_size = m_layout.separator_size * inv_zoom; - float scaled_gap_size = m_layout.gap_size * inv_zoom; - float scaled_border = m_layout.border * inv_zoom; + float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_layout.icons_scale * factor; + float scaled_separator_size = m_layout.separator_size * factor; + float scaled_gap_size = m_layout.gap_size * factor; + float scaled_border = m_layout.border * factor; float scaled_width = get_width() * inv_zoom; float scaled_height = get_height() * inv_zoom; diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index ccff885f2..d4410c589 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -109,6 +109,7 @@ public: virtual ~Preview(); wxGLCanvas* get_wxglcanvas() { return m_canvas_widget; } + GLCanvas3D* get_canvas3d() { return m_canvas; } void set_view_toolbar(GLToolbar* toolbar); diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index ed2654f51..2f231b2e1 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -205,6 +205,8 @@ void ImGuiWrapper::init_default_font(float scaling) { static const float font_size = 18.0f; + destroy_fonts_texture(); + ImGuiIO& io = ImGui::GetIO(); io.Fonts->Clear(); ImFont* font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/NotoSans-Regular.ttf").c_str(), font_size * scaling); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 530b64474..ee1473401 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1266,6 +1266,11 @@ void Plater::priv::update_ui_from_settings() // $self->{buttons_sizer}->Show($self->{btn_reslice}, ! wxTheApp->{app_config}->get("background_processing")); // $self->{buttons_sizer}->Layout; // } + +#if ENABLE_RETINA_GL + view3D->get_canvas3d()->update_ui_from_settings(); + preview->get_canvas3d()->update_ui_from_settings(); +#endif } ProgressStatusBar* Plater::priv::statusbar() diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 2aa5ecadd..b58ce5900 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -122,8 +122,7 @@ void PreferencesDialog::build() void PreferencesDialog::accept() { if (m_values.find("no_defaults") != m_values.end() || - m_values.find("use_legacy_opengl") != m_values.end() || - m_values.find("use_retina_opengl") != m_values.end()) { + m_values.find("use_legacy_opengl") != m_values.end()) { warning_catcher(this, _(L("You need to restart Slic3r to make the changes effective."))); } From 7d30323f46e1e87ecf5b1be01972cc54072f580d Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Thu, 24 Jan 2019 15:44:00 +0100 Subject: [PATCH 10/23] Mac: Retina OpenGL: Fix imgui windows, right-click menu, misc --- src/slic3r/GUI/GLCanvas3D.cpp | 42 ++++++++++++++++++++++++++------- src/slic3r/GUI/GLCanvas3D.hpp | 10 +++++--- src/slic3r/GUI/ImGuiWrapper.cpp | 1 + 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index cfb7d3dce..801ad3d98 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -341,6 +341,7 @@ void GLCanvas3D::Camera::set_scene_box(const BoundingBoxf3& box, GLCanvas3D& can GLCanvas3D::Bed::Bed() : m_type(Custom) + , m_scale_factor(1.0f) { } @@ -403,8 +404,10 @@ Point GLCanvas3D::Bed::point_projection(const Point& point) const } #if ENABLE_PRINT_BED_MODELS -void GLCanvas3D::Bed::render(float theta, bool useVBOs) const +void GLCanvas3D::Bed::render(float theta, bool useVBOs, float scale_factor) const { + m_scale_factor = scale_factor; + switch (m_type) { case MK2: @@ -431,8 +434,10 @@ void GLCanvas3D::Bed::render(float theta, bool useVBOs) const } } #else -void GLCanvas3D::Bed::render(float theta) const +void GLCanvas3D::Bed::render(float theta, float scale_factor) const { + m_scale_factor = scale_factor; + switch (m_type) { case MK2: @@ -686,7 +691,7 @@ void GLCanvas3D::Bed::_render_custom() const // we need depth test for grid, otherwise it would disappear when looking the object from below ::glEnable(GL_DEPTH_TEST); - ::glLineWidth(3.0f); + ::glLineWidth(3.0f * m_scale_factor); ::glColor4f(0.2f, 0.2f, 0.2f, 0.4f); ::glVertexPointer(3, GL_FLOAT, 0, (GLvoid*)m_gridlines.get_vertices()); ::glDrawArrays(GL_LINES, 0, (GLsizei)gridlines_vcount); @@ -1368,6 +1373,7 @@ GLCanvas3D::Selection::Selection() , m_valid(false) , m_bounding_box_dirty(true) , m_curved_arrow(16) + , m_scale_factor(1.0f) { #if ENABLE_RENDER_SELECTION_CENTER m_quadric = ::gluNewQuadric(); @@ -2166,11 +2172,13 @@ void GLCanvas3D::Selection::erase() } } -void GLCanvas3D::Selection::render() const +void GLCanvas3D::Selection::render(float scale_factor) const { if (!m_valid || is_empty()) return; + m_scale_factor = scale_factor; + // render cumulative bounding box of selected volumes _render_selected_volumes(); _render_synchronized_volumes(); @@ -2617,7 +2625,7 @@ void GLCanvas3D::Selection::_render_bounding_box(const BoundingBoxf3& box, float ::glEnable(GL_DEPTH_TEST); ::glColor3fv(color); - ::glLineWidth(2.0f); + ::glLineWidth(2.0f * m_scale_factor); ::glBegin(GL_LINES); @@ -5355,7 +5363,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) wxGetApp().obj_manipul()->update_settings_value(m_selection); // forces a frame render to update the view before the context menu is shown render(); - post_event(Vec2dEvent(EVT_GLCANVAS_RIGHT_CLICK, pos.cast())); + + Vec2d logical_pos = pos.cast(); +#if ENABLE_RETINA_GL + const float factor = m_retina_helper->get_scale_factor(); + logical_pos = logical_pos.cwiseQuotient(Vec2d(factor, factor)); +#endif + post_event(Vec2dEvent(EVT_GLCANVAS_RIGHT_CLICK, logical_pos)); } } } @@ -6404,10 +6418,15 @@ void GLCanvas3D::_render_background() const void GLCanvas3D::_render_bed(float theta) const { + float scale_factor = 1.0; +#if ENABLE_RETINA_GL + scale_factor = m_retina_helper->get_scale_factor(); +#endif + #if ENABLE_PRINT_BED_MODELS - m_bed.render(theta, m_use_VBOs); + m_bed.render(theta, m_use_VBOs, scale_factor); #else - m_bed.render(theta); + m_bed.render(theta, scale_factor); #endif // ENABLE_PRINT_BED_MODELS } @@ -6514,8 +6533,13 @@ void GLCanvas3D::_render_objects() const void GLCanvas3D::_render_selection() const { + float scale_factor = 1.0; +#if ENABLE_RETINA_GL + scale_factor = m_retina_helper->get_scale_factor(); +#endif + if (!m_gizmos.is_running()) - m_selection.render(); + m_selection.render(scale_factor); } #if ENABLE_RENDER_SELECTION_CENTER diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 0f998276d..e80189cce 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -222,6 +222,8 @@ class GLCanvas3D mutable GLBed m_model; #endif // ENABLE_PRINT_BED_MODELS + mutable float m_scale_factor; + public: Bed(); @@ -237,9 +239,9 @@ class GLCanvas3D Point point_projection(const Point& point) const; #if ENABLE_PRINT_BED_MODELS - void render(float theta, bool useVBOs) const; + void render(float theta, bool useVBOs, float scale_factor) const; #else - void render(float theta) const; + void render(float theta, float scale_factor) const; #endif // ENABLE_PRINT_BED_MODELS private: @@ -557,6 +559,8 @@ public: mutable GLCurvedArrow m_curved_arrow; #endif // ENABLE_SIDEBAR_VISUAL_HINTS + mutable float m_scale_factor; + public: Selection(); #if ENABLE_RENDER_SELECTION_CENTER @@ -640,7 +644,7 @@ public: void erase(); - void render() const; + void render(float scale_factor = 1.0) const; #if ENABLE_RENDER_SELECTION_CENTER void render_center() const; #endif // ENABLE_RENDER_SELECTION_CENTER diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index 2f231b2e1..e36a68eda 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -96,6 +96,7 @@ void ImGuiWrapper::render() void ImGuiWrapper::set_next_window_pos(float x, float y, int flag) { ImGui::SetNextWindowPos(ImVec2(x, y), (ImGuiCond)flag); + ImGui::SetNextWindowSize(ImVec2(0.0, 0.0)); } void ImGuiWrapper::set_next_window_bg_alpha(float alpha) From 2159273a1ea91d6d880dc641486dbdcc77f53513 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Thu, 24 Jan 2019 17:02:13 +0100 Subject: [PATCH 11/23] Mac: Retina OpenGL: Fix toolbar mouse hover --- src/slic3r/GUI/GLToolbar.cpp | 44 +++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index e9ca9a6b1..b15048ec6 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -500,18 +500,19 @@ float GLToolbar::get_main_size() const std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent) { - // Note: m_layout.icons_scale is not applied here because mouse_pos is already in scaled coordinates + // NB: mouse_pos is already scaled appropriately float zoom = parent.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; + float factor = m_layout.icons_scale * inv_zoom; Size cnv_size = parent.get_canvas_size(); Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom); - float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_layout.icons_scale * inv_zoom; - float scaled_separator_size = m_layout.separator_size * inv_zoom; - float scaled_gap_size = m_layout.gap_size * inv_zoom; - float scaled_border = m_layout.border * inv_zoom; + float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * factor; + float scaled_separator_size = m_layout.separator_size * factor; + float scaled_gap_size = m_layout.gap_size * factor; + float scaled_border = m_layout.border * factor; float separator_stride = scaled_separator_size + scaled_gap_size; float icon_stride = scaled_icons_size + scaled_gap_size; @@ -593,18 +594,19 @@ std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLC std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D& parent) { - // Note: m_layout.icons_scale is not applied here because mouse_pos is already in scaled coordinates + // NB: mouse_pos is already scaled appropriately float zoom = parent.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; + float factor = m_layout.icons_scale * inv_zoom; Size cnv_size = parent.get_canvas_size(); Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom); - float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_layout.icons_scale * inv_zoom; - float scaled_separator_size = m_layout.separator_size * inv_zoom; - float scaled_gap_size = m_layout.gap_size * inv_zoom; - float scaled_border = m_layout.border * inv_zoom; + float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * factor; + float scaled_separator_size = m_layout.separator_size * factor; + float scaled_gap_size = m_layout.gap_size * factor; + float scaled_border = m_layout.border * factor; float separator_stride = scaled_separator_size + scaled_gap_size; float icon_stride = scaled_icons_size + scaled_gap_size; @@ -686,16 +688,19 @@ std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCan int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const { + // NB: mouse_pos is already scaled appropriately + float zoom = parent.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; + float factor = m_layout.icons_scale * inv_zoom; Size cnv_size = parent.get_canvas_size(); Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom); - float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_layout.icons_scale * inv_zoom; - float scaled_separator_size = m_layout.separator_size * inv_zoom; - float scaled_gap_size = m_layout.gap_size * inv_zoom; - float scaled_border = m_layout.border * inv_zoom; + float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * factor; + float scaled_separator_size = m_layout.separator_size * factor; + float scaled_gap_size = m_layout.gap_size * factor; + float scaled_border = m_layout.border * factor; float separator_stride = scaled_separator_size + scaled_gap_size; float icon_stride = scaled_icons_size + scaled_gap_size; @@ -728,16 +733,19 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3 int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const { + // NB: mouse_pos is already scaled appropriately + float zoom = parent.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; + float factor = m_layout.icons_scale * inv_zoom; Size cnv_size = parent.get_canvas_size(); Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom); - float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_layout.icons_scale * inv_zoom; - float scaled_separator_size = m_layout.separator_size * inv_zoom; - float scaled_gap_size = m_layout.gap_size * inv_zoom; - float scaled_border = m_layout.border * inv_zoom; + float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * factor; + float scaled_separator_size = m_layout.separator_size * factor; + float scaled_gap_size = m_layout.gap_size * factor; + float scaled_border = m_layout.border * factor; float separator_stride = scaled_separator_size + scaled_gap_size; float icon_stride = scaled_icons_size + scaled_gap_size; From 708a14c22847789c222bdfac5aa245c211769257 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 25 Jan 2019 14:56:41 +0100 Subject: [PATCH 12/23] Fix of instance synchronization. It seems to be working, but one may want to review the center of rotation of the instances when rotating around a general axis (zero component of the rotation axis in the world Z). --- src/slic3r/GUI/GLCanvas3D.cpp | 111 +++++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 30 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index a97c98135..79b9ffa68 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1731,55 +1731,64 @@ void GLCanvas3D::Selection::translate(const Vec3d& displacement, bool local) void GLCanvas3D::Selection::rotate(const Vec3d& rotation, bool local) { - if (!m_valid) + int rot_axis_max; + if (!m_valid || rotation.cwiseAbs().maxCoeff(&rot_axis_max) < EPSILON) return; + // For generic rotation, we want to rotate the first volume in selection, and then to synchronize the other volumes with it. + std::vector object_instance_first(m_model->objects.size(), -1); + auto rotate_instance = [this, &rotation, &object_instance_first, rot_axis_max, local](GLVolume &volume, int i) { + int first_volume_idx = object_instance_first[volume.object_idx()]; + if (rot_axis_max != 2 && first_volume_idx != -1) { + // Generic rotation, but no rotation around the Z axis. + // Always do a local rotation (do not consider the selection to be a rigid body). + assert(rotation.z() == 0); + const GLVolume &first_volume = *(*m_volumes)[first_volume_idx]; + const Vec3d &rotation = first_volume.get_instance_rotation(); + double z_diff = m_cache.volumes_data[i].get_instance_rotation()(2) - m_cache.volumes_data[first_volume_idx].get_instance_rotation()(2); + volume.set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff)); + } else { + // extracts rotations from the composed transformation + Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); + Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_instance_rotation_matrix()); + if (!local) + volume.set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center)); + volume.set_instance_rotation(new_rotation); + object_instance_first[volume.object_idx()] = i; + } + }; + for (unsigned int i : m_list) { + GLVolume &volume = *(*m_volumes)[i]; if (is_single_full_instance()) - { - if (local) - (*m_volumes)[i]->set_instance_rotation(rotation); - else - { - Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); - Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_instance_rotation_matrix()); - (*m_volumes)[i]->set_instance_rotation(new_rotation); - } - } + rotate_instance(volume, i); else if (is_single_volume() || is_single_modifier()) { if (local) - (*m_volumes)[i]->set_volume_rotation(rotation); + volume.set_volume_rotation(rotation); else { Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix()); - (*m_volumes)[i]->set_volume_rotation(new_rotation); + volume.set_volume_rotation(new_rotation); } } else { - Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); if (m_mode == Instance) - { - // extracts rotations from the composed transformation - Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_instance_rotation_matrix()); - if (!local) - (*m_volumes)[i]->set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center)); - - (*m_volumes)[i]->set_instance_rotation(new_rotation); - } + rotate_instance(volume, i); else if (m_mode == Volume) { // extracts rotations from the composed transformation + Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix()); if (!local) { Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() + m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center); - (*m_volumes)[i]->set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset); + volume.set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset); } - (*m_volumes)[i]->set_volume_rotation(new_rotation); + volume.set_volume_rotation(new_rotation); } } } @@ -2699,6 +2708,40 @@ void GLCanvas3D::Selection::_render_sidebar_size_hint(Axis axis, double length) { } +#ifdef _DEBUG +static bool is_rotation_xy_synchronized(const Vec3d &rotation1, const Vec3d &rotation2) +{ + // The XYZ Euler angles are not unique. Rather then comparing the XY components of the two rotations, + // transform the up vector to one instance and back, which should lead to the same up vector. + Transform3d m1 = Geometry::assemble_transform(Vec3d::Zero(), rotation1); + Transform3d m2 = Geometry::assemble_transform(Vec3d::Zero(), rotation2); + Vec3d up0(0., 0., 1.); + Vec3d up = m1.rotation() * m2.rotation().inverse() * up0; + return (up - up0).cwiseAbs().maxCoeff() < EPSILON; +} +static void verify_instances_rotation_synchronized(const Model &model, const GLVolumePtrs &volumes) +{ + for (size_t idx_object = 0; idx_object < model.objects.size(); ++ idx_object) { + int idx_volume_first = -1; + for (int i = 0; i < (int)volumes.size(); ++ i) { + if (volumes[i]->object_idx() == idx_object) { + idx_volume_first = i; + break; + } + } + assert(idx_volume_first != -1); // object without instances? + if (idx_volume_first == -1) + continue; + const Vec3d &rotation0 = volumes[idx_volume_first]->get_instance_rotation(); + for (int i = idx_volume_first + 1; i < (int)volumes.size(); ++ i) + if (volumes[i]->object_idx() == idx_object) { + const Vec3d &rotation = volumes[i]->get_instance_rotation(); + assert(is_rotation_xy_synchronized(rotation, rotation0)); + } + } +} +#endif /* _DEBUG */ + void GLCanvas3D::Selection::_synchronize_unselected_instances(bool including_z) { std::set done; // prevent processing volumes twice @@ -2738,12 +2781,16 @@ void GLCanvas3D::Selection::_synchronize_unselected_instances(bool including_z) if (including_z) // rotation comes from place on face -> force given z z = rotation(2); - else if (is_approx(rotation(0), m_cache.volumes_data[j].get_instance_rotation()(0)) && is_approx(rotation(1), m_cache.volumes_data[j].get_instance_rotation()(1))) - // z only rotation -> keep instance z - z = v->get_instance_rotation()(2); - else - // generic rotation -> update instance z - z = m_cache.volumes_data[j].get_instance_rotation()(2) + rotation(2); + else if (is_approx(rotation(0), m_cache.volumes_data[j].get_instance_rotation()(0)) && is_approx(rotation(1), m_cache.volumes_data[j].get_instance_rotation()(1))) { + // z only rotation -> keep instance z + z = v->get_instance_rotation()(2); + // The X,Y rotations should be synchronized from start to end of the rotation. + assert(is_rotation_xy_synchronized(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation())); + assert(is_rotation_xy_synchronized(rotation, v->get_instance_rotation())); + } else { + // generic rotation -> update instance z with the delta of the rotation. + z = rotation(2) + m_cache.volumes_data[j].get_instance_rotation()(2) - m_cache.volumes_data[i].get_instance_rotation()(2); + } v->set_instance_rotation(Vec3d(rotation(0), rotation(1), z)); v->set_instance_scaling_factor(scaling_factor); @@ -2752,6 +2799,10 @@ void GLCanvas3D::Selection::_synchronize_unselected_instances(bool including_z) done.insert(j); } } + +#ifdef _DEBUG + verify_instances_rotation_synchronized(*m_model, *m_volumes); +#endif /* _DEBUG */ } void GLCanvas3D::Selection::_synchronize_unselected_volumes() From 48d64b0842f5b13ba197d759d95c7929072efd74 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sat, 26 Jan 2019 14:12:57 +0100 Subject: [PATCH 13/23] Fixed compilation on Visual Studio in Debug mode. --- src/libnest2d/CMakeLists.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libnest2d/CMakeLists.txt b/src/libnest2d/CMakeLists.txt index 7853a48d5..514498ee8 100644 --- a/src/libnest2d/CMakeLists.txt +++ b/src/libnest2d/CMakeLists.txt @@ -70,10 +70,12 @@ if(TBB_FOUND) # The Intel TBB library will use the std::exception_ptr feature of C++11. target_compile_definitions(libnest2d INTERFACE -DTBB_USE_CAPTURED_EXCEPTION=0) - find_package(Threads REQUIRED) - target_link_libraries(libnest2d INTERFACE ${TBB_LIBRARIES} ${CMAKE_DL_LIBS} - Threads::Threads - ) + target_link_libraries(libnest2d INTERFACE tbb) + # The following breaks compilation on Visual Studio in Debug mode. + #find_package(Threads REQUIRED) + #target_link_libraries(libnest2d INTERFACE ${TBB_LIBRARIES} ${CMAKE_DL_LIBS} + # Threads::Threads + # ) else() find_package(OpenMP QUIET) From 588c07c12a143474730875c38012cf6edb15905b Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sat, 26 Jan 2019 18:51:34 +0100 Subject: [PATCH 14/23] Performance improvements: Lazy "Place on face" gizmo update. Caching of MeshObject::raw_mesh_bounding_box() for the object size display. ModelObject::bounding_box(), raw_mesh_bounding_box(), full_raw_mesh_bounding_box() will not copy the mesh. TriangleMesh::transformed_bounding_box(const Transform3d &trafo) will not copy the mesh data. get_options_for_bundle() will not return reference to temp value is_splittable() calls cheap mesh.has_multiple_patches() --- src/libslic3r/BoundingBox.hpp | 1 + src/libslic3r/Model.cpp | 54 +++++++++-------- src/libslic3r/Model.hpp | 13 ++-- src/libslic3r/TriangleMesh.cpp | 72 +++++------------------ src/libslic3r/TriangleMesh.hpp | 2 +- src/slic3r/GUI/GLGizmo.cpp | 17 ++++-- src/slic3r/GUI/GLGizmo.hpp | 1 + src/slic3r/GUI/GUI_ObjectList.cpp | 18 +++--- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 4 +- src/slic3r/GUI/Plater.cpp | 2 +- 10 files changed, 76 insertions(+), 108 deletions(-) diff --git a/src/libslic3r/BoundingBox.hpp b/src/libslic3r/BoundingBox.hpp index b3a1c2f5c..26302f702 100644 --- a/src/libslic3r/BoundingBox.hpp +++ b/src/libslic3r/BoundingBox.hpp @@ -32,6 +32,7 @@ public: } this->defined = (this->min(0) < this->max(0)) && (this->min(1) < this->max(1)); } + void reset() { this->defined = false; this->min = PointClass::Zero(); this->max = PointClass::Zero(); } void merge(const PointClass &point); void merge(const std::vector &points); void merge(const BoundingBoxBase &bb); diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index b13b00e57..593f716fa 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -573,6 +573,8 @@ ModelObject& ModelObject::assign_copy(const ModelObject &rhs) this->origin_translation = rhs.origin_translation; m_bounding_box = rhs.m_bounding_box; m_bounding_box_valid = rhs.m_bounding_box_valid; + m_raw_mesh_bounding_box = rhs.m_raw_mesh_bounding_box; + m_raw_mesh_bounding_box_valid = rhs.m_raw_mesh_bounding_box_valid; this->clear_volumes(); this->volumes.reserve(rhs.volumes.size()); @@ -604,6 +606,8 @@ ModelObject& ModelObject::assign_copy(ModelObject &&rhs) this->origin_translation = std::move(rhs.origin_translation); m_bounding_box = std::move(rhs.m_bounding_box); m_bounding_box_valid = std::move(rhs.m_bounding_box_valid); + m_raw_mesh_bounding_box = rhs.m_raw_mesh_bounding_box; + m_raw_mesh_bounding_box_valid = rhs.m_raw_mesh_bounding_box_valid; this->clear_volumes(); this->volumes = std::move(rhs.volumes); @@ -783,19 +787,11 @@ void ModelObject::clear_instances() const BoundingBoxf3& ModelObject::bounding_box() const { if (! m_bounding_box_valid) { - BoundingBoxf3 raw_bbox; - for (const ModelVolume *v : this->volumes) - if (v->is_model_part()) - { - TriangleMesh m = v->mesh; - m.transform(v->get_matrix()); - raw_bbox.merge(m.bounding_box()); - } - BoundingBoxf3 bb; - for (const ModelInstance *i : this->instances) - bb.merge(i->transform_bounding_box(raw_bbox)); - m_bounding_box = bb; m_bounding_box_valid = true; + BoundingBoxf3 raw_bbox = this->raw_mesh_bounding_box(); + m_bounding_box.reset(); + for (const ModelInstance *i : this->instances) + m_bounding_box.merge(i->transform_bounding_box(raw_bbox)); } return m_bounding_box; } @@ -842,6 +838,26 @@ TriangleMesh ModelObject::full_raw_mesh() const return mesh; } +BoundingBoxf3 ModelObject::raw_mesh_bounding_box() const +{ + if (! m_raw_mesh_bounding_box_valid) { + m_raw_mesh_bounding_box_valid = true; + m_raw_mesh_bounding_box.reset(); + for (const ModelVolume *v : this->volumes) + if (v->is_model_part()) + m_raw_mesh_bounding_box.merge(v->mesh.transformed_bounding_box(v->get_matrix())); + } + return m_raw_mesh_bounding_box; +} + +BoundingBoxf3 ModelObject::full_raw_mesh_bounding_box() const +{ + BoundingBoxf3 bb; + for (const ModelVolume *v : this->volumes) + bb.merge(v->mesh.transformed_bounding_box(v->get_matrix())); + return bb; +} + // A transformed snug bounding box around the non-modifier object volumes, without the translation applied. // This bounding box is only used for the actual slicing. BoundingBoxf3 ModelObject::raw_bounding_box() const @@ -896,20 +912,6 @@ BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_ return bb; } -#if ENABLE_VOLUMES_CENTERING_FIXES -BoundingBoxf3 ModelObject::full_raw_mesh_bounding_box() const -{ - BoundingBoxf3 bb; - for (const ModelVolume *v : this->volumes) - { - TriangleMesh vol_mesh(v->mesh); - vol_mesh.transform(v->get_matrix()); - bb.merge(vol_mesh.bounding_box()); - } - return bb; -} -#endif // ENABLE_VOLUMES_CENTERING_FIXES - void ModelObject::center_around_origin() { // calculate the displacements needed to diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index f13baee08..0dd73f62f 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -205,7 +205,7 @@ public: // This bounding box is approximate and not snug. // This bounding box is being cached. const BoundingBoxf3& bounding_box() const; - void invalidate_bounding_box() { m_bounding_box_valid = false; } + void invalidate_bounding_box() { m_bounding_box_valid = false; m_raw_mesh_bounding_box_valid = false; } // A mesh containing all transformed instances of this object. TriangleMesh mesh() const; @@ -219,10 +219,10 @@ public: BoundingBoxf3 raw_bounding_box() const; // A snug bounding box around the transformed non-modifier object volumes. BoundingBoxf3 instance_bounding_box(size_t instance_idx, bool dont_translate = false) const; -#if ENABLE_VOLUMES_CENTERING_FIXES - // Bounding box of non-transformed (non-rotated, non-scaled, non-translated) sum of all object volumes. + // A snug bounding box of non-transformed (non-rotated, non-scaled, non-translated) sum of non-modifier object volumes. + BoundingBoxf3 raw_mesh_bounding_box() const; + // A snug bounding box of non-transformed (non-rotated, non-scaled, non-translated) sum of all object volumes. BoundingBoxf3 full_raw_mesh_bounding_box() const; -#endif // ENABLE_VOLUMES_CENTERING_FIXES void center_around_origin(); void ensure_on_bed(); void translate_instances(const Vec3d& vector); @@ -261,7 +261,8 @@ protected: void set_model(Model *model) { m_model = model; } private: - ModelObject(Model *model) : m_model(model), origin_translation(Vec3d::Zero()), m_bounding_box_valid(false) {} + ModelObject(Model *model) : m_model(model), origin_translation(Vec3d::Zero()), + m_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) {} ~ModelObject(); /* To be able to return an object from own copy / clone methods. Hopefully the compiler will do the "Copy elision" */ @@ -280,6 +281,8 @@ private: // Bounding box, cached. mutable BoundingBoxf3 m_bounding_box; mutable bool m_bounding_box_valid; + mutable BoundingBoxf3 m_raw_mesh_bounding_box; + mutable bool m_raw_mesh_bounding_box_valid; }; // An object STL, or a modifier volume, over which a different set of parameters shall be applied. diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 4648b95c0..8b69a9e5c 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -525,67 +525,22 @@ BoundingBoxf3 TriangleMesh::bounding_box() const return bb; } -BoundingBoxf3 TriangleMesh::transformed_bounding_box(const Transform3d& t) const +BoundingBoxf3 TriangleMesh::transformed_bounding_box(const Transform3d &trafo) const { - bool has_shared = (stl.v_shared != nullptr); - if (!has_shared) - stl_generate_shared_vertices(const_cast(&stl)); - - unsigned int vertices_count = (stl.stats.shared_vertices > 0) ? (unsigned int)stl.stats.shared_vertices : 3 * (unsigned int)stl.stats.number_of_facets; - - if (vertices_count == 0) - return BoundingBoxf3(); - - Eigen::MatrixXd src_vertices(3, vertices_count); - - if (stl.stats.shared_vertices > 0) - { - assert(stl.v_shared != nullptr); - stl_vertex* vertex_ptr = stl.v_shared; - for (int i = 0; i < stl.stats.shared_vertices; ++i) - { - src_vertices(0, i) = (double)(*vertex_ptr)(0); - src_vertices(1, i) = (double)(*vertex_ptr)(1); - src_vertices(2, i) = (double)(*vertex_ptr)(2); - vertex_ptr += 1; + BoundingBoxf3 bbox; + if (stl.v_shared == nullptr) { + // Using the STL faces. + for (int i = 0; i < this->facets_count(); ++ i) { + const stl_facet &facet = this->stl.facet_start[i]; + for (size_t j = 0; j < 3; ++ j) + bbox.merge(trafo * facet.vertex[j].cast()); } + } else { + // Using the shared vertices should be a bit quicker than using the STL faces. + for (int i = 0; i < stl.stats.shared_vertices; ++ i) + bbox.merge(trafo * this->stl.v_shared[i].cast()); } - else - { - stl_facet* facet_ptr = stl.facet_start; - unsigned int v_id = 0; - while (facet_ptr < stl.facet_start + stl.stats.number_of_facets) - { - for (int i = 0; i < 3; ++i) - { - src_vertices(0, v_id) = (double)facet_ptr->vertex[i](0); - src_vertices(1, v_id) = (double)facet_ptr->vertex[i](1); - src_vertices(2, v_id) = (double)facet_ptr->vertex[i](2); - ++v_id; - } - facet_ptr += 1; - } - } - - if (!has_shared && (stl.stats.shared_vertices > 0)) - stl_invalidate_shared_vertices(const_cast(&stl)); - - Eigen::MatrixXd dst_vertices(3, vertices_count); - dst_vertices = t * src_vertices.colwise().homogeneous(); - - Vec3d v_min(dst_vertices(0, 0), dst_vertices(1, 0), dst_vertices(2, 0)); - Vec3d v_max = v_min; - - for (int i = 1; i < vertices_count; ++i) - { - for (int j = 0; j < 3; ++j) - { - v_min(j) = std::min(v_min(j), dst_vertices(j, i)); - v_max(j) = std::max(v_max(j), dst_vertices(j, i)); - } - } - - return BoundingBoxf3(v_min, v_max); + return bbox; } TriangleMesh TriangleMesh::convex_hull_3d() const @@ -2010,4 +1965,5 @@ TriangleMesh make_sphere(double rho, double fa) { TriangleMesh mesh(vertices, facets); return mesh; } + } diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index fc2b40013..be70ee79d 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -60,7 +60,7 @@ public: Polygon convex_hull(); BoundingBoxf3 bounding_box() const; // Returns the bbox of this TriangleMesh transformed by the given transformation - BoundingBoxf3 transformed_bounding_box(const Transform3d& t) const; + BoundingBoxf3 transformed_bounding_box(const Transform3d &trafo) const; // Returns the convex hull of this TriangleMesh TriangleMesh convex_hull_3d() const; void reset_repair_stats(); diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index cb9a5abc9..1660976a1 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -1428,6 +1428,7 @@ void GLGizmoFlatten::on_start_dragging(const GLCanvas3D::Selection& selection) { if (m_hover_id != -1) { + assert(m_planes_valid); m_normal = m_planes[m_hover_id].normal; m_starting_center = selection.get_bounding_box().center(); } @@ -1446,6 +1447,8 @@ void GLGizmoFlatten::on_render(const GLCanvas3D::Selection& selection) const ::glPushMatrix(); ::glMultMatrixd(m.data()); ::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z()); + if (this->is_plane_update_necessary()) + const_cast(this)->update_planes(); for (int i = 0; i < (int)m_planes.size(); ++i) { if (i == m_hover_id) @@ -1478,6 +1481,8 @@ void GLGizmoFlatten::on_render_for_picking(const GLCanvas3D::Selection& selectio ::glPushMatrix(); ::glMultMatrixd(m.data()); ::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z()); + if (this->is_plane_update_necessary()) + const_cast(this)->update_planes(); for (int i = 0; i < (int)m_planes.size(); ++i) { ::glColor3f(1.0f, 1.0f, picking_color_component(i)); @@ -1497,11 +1502,11 @@ void GLGizmoFlatten::on_render_for_picking(const GLCanvas3D::Selection& selectio void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object) { m_starting_center = Vec3d::Zero(); - bool object_changed = m_model_object != model_object; + if (m_model_object != model_object) { + m_planes.clear(); + m_planes_valid = false; + } m_model_object = model_object; - - if (model_object && (object_changed || is_plane_update_necessary())) - update_planes(); } void GLGizmoFlatten::update_planes() @@ -1701,6 +1706,8 @@ void GLGizmoFlatten::update_planes() } m_first_instance_scale = m_model_object->instances.front()->get_scaling_factor(); m_first_instance_mirror = m_model_object->instances.front()->get_mirror(); + + m_planes_valid = true; } @@ -1709,7 +1716,7 @@ bool GLGizmoFlatten::is_plane_update_necessary() const if (m_state != On || !m_model_object || m_model_object->instances.empty()) return false; - if (m_model_object->volumes.size() != m_volumes_matrices.size()) + if (! m_planes_valid || m_model_object->volumes.size() != m_volumes_matrices.size()) return true; // We want to recalculate when the scale changes - some planes could (dis)appear. diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp index 02b637a35..7a55a2392 100644 --- a/src/slic3r/GUI/GLGizmo.hpp +++ b/src/slic3r/GUI/GLGizmo.hpp @@ -408,6 +408,7 @@ private: Vec3d m_first_instance_mirror; std::vector m_planes; + bool m_planes_valid = false; mutable Vec3d m_starting_center; const ModelObject* m_model_object = nullptr; std::vector instances_matrices; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 62c00d02d..d62548d48 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -621,7 +621,8 @@ const std::vector& get_options_for_bundle(const wxString& bundle_na if (bundle_name == _(it.first)) return it.second; } - return std::vector {}; + static std::vector empty; + return empty; } // category -> vector ( option ; label ) @@ -1276,15 +1277,12 @@ bool ObjectList::is_splittable() if (!get_volume_by_item(item, volume) || !volume) return false; - if (volume->is_splittable() != -1) // if is_splittable value is already known - return volume->is_splittable() == 0 ? false : true; - - TriangleMeshPtrs meshptrs = volume->mesh.split(); - bool splittable = meshptrs.size() > 1; - for (TriangleMesh* m : meshptrs) { delete m; } - - volume->set_splittable(splittable ? 1 : 0); - return splittable; + int splittable = volume->is_splittable(); + if (splittable == -1) { + splittable = (int)volume->mesh.has_multiple_patches(); + volume->set_splittable(splittable); + } + return splittable != 0; } bool ObjectList::selected_instances_of_same_object() diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 363294ce8..5157dc9c5 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -267,7 +267,7 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele bool changed_box = false; if (!m_cache.instance.matches_object(obj_idx)) { - m_cache.instance.set(obj_idx, instance_idx, (*wxGetApp().model_objects())[obj_idx]->raw_mesh().bounding_box().size()); + m_cache.instance.set(obj_idx, instance_idx, (*wxGetApp().model_objects())[obj_idx]->raw_mesh_bounding_box().size()); changed_box = true; } if (changed_box || !m_cache.instance.matches_instance(instance_idx) || !m_cache.scale.isApprox(100.0 * m_new_scale)) @@ -278,7 +278,7 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele m_new_size = Vec3d::Zero(); #else if ((0 <= obj_idx) && (obj_idx < (int)wxGetApp().model_objects()->size())) - m_new_size = volume->get_instance_transformation().get_matrix(true, true) * (*wxGetApp().model_objects())[obj_idx]->raw_mesh().bounding_box().size(); + m_new_size = volume->get_instance_transformation().get_matrix(true, true) * (*wxGetApp().model_objects())[obj_idx]->raw_mesh_bounding_box().size(); else // this should never happen m_new_size = Vec3d::Zero(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index cb08ea3f3..bc65d9784 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2105,7 +2105,7 @@ void Plater::priv::fix_through_netfabb(const int obj_idx) o->clear_instances(); for (auto instance: model_object->instances) o->add_instance(*instance); - // o->invalidate_bounding_box(); + o->invalidate_bounding_box(); if (o->volumes.size() == model_object->volumes.size()) { for (int i = 0; i < o->volumes.size(); i++) { From 282ef552f9111583dc9bcfba641ecd41c74353ff Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sat, 26 Jan 2019 18:52:31 +0100 Subject: [PATCH 15/23] SLA print bed rotated by 180 degrees, simplified by removing some internal pieces. --- resources/models/sl1_bed.stl | Bin 472884 -> 416084 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/resources/models/sl1_bed.stl b/resources/models/sl1_bed.stl index 28601b288a29535686acf800bc517a6e5777c806..b2cadde4bd50b42ae247da4abba4dfb0b74d1413 100644 GIT binary patch literal 416084 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

vPy}ccX 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­}`MFNPt(BYELYOjR&g?m>&HKSL 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 QRWJ=TRyYih-J1#ScEbU4# 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 Z)5ZTmCFfLJK3fi{E3Okx#pR2_{|EY6!1w?F literal 472884 zcmb@v3Ah|pwZ7jXB4lDPAVV0$aG4Xx;LX74Cfy*DU;t?l6@e>=2>cu_Dj4K2d1Z(S ziV~Gs5HJviG$aR47lX(kLINT10{{KhuGQ<^)pdaTJpbs?_4HbAeYLCh zu=cL0R{Q_=-?I~IwT~~HmL2}wynzJ^r!|h*eROO4**|U8Y6s6baLVY`)vcd4mwn-& zIs5E1x;1~%J^AmQ_L3{6Wjnm%gna1fwP$Ke~0&hNf}RM<-^Z z_gv7uFYFaPBvv|XbZhL}Oyl9Nj?Y#ezpOhpl$->k4!vY_>$A=+0G?`QGb1KbnDz*OylGoL-g*o?0c6?YtTbt z){jTG-nFS|yl?EX?p@y%N-*lcv13}>zjS9&j{C+e>#i5da!9Bp^pM!-En`~0 zy!Xzc953v;pu5FKCT4%UCM6j4*!#w`Ubxvb&fR@Mcl`q#Pwx~%H z#-bd*y?frkI-wm-40}ZniDNbyi*j6f%k282q2$k(2u3~r(XlumGjE$+pE_xBc3L3l zAyGeKEY8Q-yDz9ee$d3MRw5X6_=RIpuRgTzg8C_kOw6)Sa(YNy@WZjFSKT$2)xZ1A z@!3m1NC`&W_sCeZkJbju>PLNRd^QwnJ3S;$etIn0$6mYE8k@9g+2)}|kzmw;qsF0~ z-#@+9IJ;5H?h7@M9un(pI1cUnlGDdGmWEb!OlapM81>aD}k3+xv(tk{D zEbGqh-Wqyp5{%mG&~X?)7H&7W@saChcV~oh&_m+ToXVB*Sjet7^S+fV9vco-~PjcCN>t&T~L3js3qnhk)Qtq?=AZFFb+1t zI9S&>$Zau7b@~&FO(TqhjW7<@H4f54LiPBU51Pi&jauU!p;cM?ux&9)ZS(YZ{;Vj+ zxK^$4>@Ky&=ZaQq9ujJguk7%%q8vl(EURyI-uT9Mik`s;MyXf&%g0UQoItGkjq#0# zi{8gPB-F3$e2!@}_gYYYIJCnHiyqDhMyYq*@>0_{bk7C#a}Jx>*yr-t@0y2%`p5N_ zo5tyP&91*^`sBvk62T~q5}&@)G-ljAyS`-F}UF{wj=vSr`ZF8V5-* zO0x{>T|4bxePCjC<}M5BcZ7bI9uk@-c)#13I5~Un*4g!LiC`4xaGiD-2eU8^)-?{& zLxS_RPP>?44%TXeIbriCjU{Gt)|V3@TK@)<`5+07k3Ee(f>GStRD&K8(zEd~)gZwr z9`#g%9un!unHM_z&ug!pn4CdIu`Z+<^pN0amzIMBqgba?4SGm$d`vY+Fp8}?)u4w& zI&#{vQY|6DDE2X_20bLwk&_xE7{$KQHFO5)A(4)p)F8nq_W7=%lG8(i<6}T5s$;(TVH$bK;US?q{l)~NRL6YvgBtXZ zP@V24RB{rGQXTWv4{FduLUsC$2}Y@o`RWHX=pmsx{l)~NRL6Yv!!%TKdPt~F_Y*pU zBp9Vy>8l^6A%Y$fs?%>wFiN%ES3jVU*@{Q4ws4MROR`01T|;)#J~DdB#QcyazCIz^ zqHL9-pP;8qC{Ij@a6U2;mc1&Sr zl&wk~HHR+Oz$^b_=y39U1{K4Gf{in3LTgcww9XS-tywz)_`gyue&(NiY0 zTAL7qWkR$?*<2(cat(UQgjSssBG(`x+oEhPk`TEDJ!L|x=LwN(kdSRrHWx{VT!Wr6 z(bqn54HB{~%H|^d8uauL;c7-gwxVn#iW(&7sUo7rJs*FhyXQ(ro)F44m6%jRd z3>tsF@cLnCkTBcI;Vbkcv|aO55mBQkdDqHegwcx9QSg-_67*CNQ6sd!Osz^9B+OP+ zel~k6UL@$LBBDl76EkU$Fk4ZomA-OEf}ScOYMk_z>Dk9tot|ruFk4Y-UA_WIf}ScO zY7{*~u0g_VMX8tYl~fY+R1s0*xDP+l{rk#CUlArjPZbe0ik>>xAYrzm z)NA|7HVJyFh^V2qp&GAqPQq+OY4p*YDz-rq^i&Z&jRDgjVYZ?)?s_?bMvtJUiijGa z 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�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 E2SFoUY5)KL From bb0cf221bcfd68e5e729be787b3dc29dbd25fe81 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 28 Jan 2019 08:52:22 +0100 Subject: [PATCH 16/23] WIP synchronization of Z rotation of the instances --- src/libslic3r/Geometry.cpp | 12 ++--- src/libslic3r/Geometry.hpp | 2 +- src/libslic3r/Model.hpp | 2 +- src/slic3r/GUI/GLCanvas3D.cpp | 97 ++++++++++++++++++++++++----------- src/slic3r/GUI/GLCanvas3D.hpp | 10 +++- 5 files changed, 84 insertions(+), 39 deletions(-) diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index b84e2f13d..cbb38b9bb 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -1189,16 +1189,16 @@ Vec3d extract_euler_angles(const Eigen::Matrix& Vec3d angles2 = Vec3d::Zero(); if (is_approx(std::abs(rotation_matrix(2, 0)), 1.0)) { - angles1(0) = 0.0; - if (rotation_matrix(2, 0) > 0.0) // == +1.0 + angles1(2) = 0.0; + if (rotation_matrix(2, 0) < 0.0) // == -1.0 { angles1(1) = 0.5 * (double)PI; - angles1(2) = angles1(0) + ::atan2(rotation_matrix(0, 1), rotation_matrix(0, 2)); + angles1(0) = angles1(2) + ::atan2(rotation_matrix(0, 1), rotation_matrix(0, 2)); } - else // == -1.0 + else // == 1.0 { - angles1(1) = 0.5 * (double)PI; - angles1(2) = -angles1(0) - ::atan2(rotation_matrix(0, 1), rotation_matrix(0, 2)); + angles1(1) = - 0.5 * (double)PI; + angles1(0) = - angles1(2) + ::atan2(- rotation_matrix(0, 1), - rotation_matrix(0, 2)); } angles2 = angles1; } diff --git a/src/libslic3r/Geometry.hpp b/src/libslic3r/Geometry.hpp index deefaa789..b43d59143 100644 --- a/src/libslic3r/Geometry.hpp +++ b/src/libslic3r/Geometry.hpp @@ -237,7 +237,7 @@ public: void set_rotation(const Vec3d& rotation); void set_rotation(Axis axis, double rotation); - Vec3d get_scaling_factor() const { return m_scaling_factor; } + const Vec3d& get_scaling_factor() const { return m_scaling_factor; } double get_scaling_factor(Axis axis) const { return m_scaling_factor(axis); } void set_scaling_factor(const Vec3d& scaling_factor); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index f13baee08..1448ee447 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -464,7 +464,7 @@ public: void set_rotation(const Vec3d& rotation) { m_transformation.set_rotation(rotation); } void set_rotation(Axis axis, double rotation) { m_transformation.set_rotation(axis, rotation); } - Vec3d get_scaling_factor() const { return m_transformation.get_scaling_factor(); } + const Vec3d& get_scaling_factor() const { return m_transformation.get_scaling_factor(); } double get_scaling_factor(Axis axis) const { return m_transformation.get_scaling_factor(axis); } void set_scaling_factor(const Vec3d& scaling_factor) { m_transformation.set_scaling_factor(scaling_factor); } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 79b9ffa68..f193af9e0 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1,3 +1,13 @@ +#if 1 +#pragma optimize("", off) +// Enable debugging and assert in this file. +#define DEBUG +#define _DEBUG +#undef NDEBUG +#endif + +#include + #include "slic3r/GUI/GLGizmo.hpp" #include "GLCanvas3D.hpp" @@ -1721,7 +1731,7 @@ void GLCanvas3D::Selection::translate(const Vec3d& displacement, bool local) #if !DISABLE_INSTANCES_SYNCH if (m_mode == Instance) - _synchronize_unselected_instances(); + _synchronize_unselected_instances(SYNC_ROTATION_NONE); else if (m_mode == Volume) _synchronize_unselected_volumes(); #endif // !DISABLE_INSTANCES_SYNCH @@ -1729,6 +1739,30 @@ void GLCanvas3D::Selection::translate(const Vec3d& displacement, bool local) m_bounding_box_dirty = true; } +static Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to) +{ + return + // From the current coordinate system to world. + Eigen::AngleAxisd(rot_xyz_to(2), Vec3d::UnitZ()) * Eigen::AngleAxisd(rot_xyz_to(1), Vec3d::UnitY()) * Eigen::AngleAxisd(rot_xyz_to(0), Vec3d::UnitX()) * + // From world to the initial coordinate system. + Eigen::AngleAxisd(-rot_xyz_from(0), Vec3d::UnitX()) * Eigen::AngleAxisd(-rot_xyz_from(1), Vec3d::UnitY()) * Eigen::AngleAxisd(-rot_xyz_from(2), Vec3d::UnitZ()); +} + +// This should only be called if it is known, that the two rotations only differ in rotation around the Z axis. +static double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to) +{ + Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to)); + Vec3d axis = angle_axis.axis(); + double angle = angle_axis.angle(); +#ifdef _DEBUG + if (std::abs(angle) > 1e-8) { + assert(std::abs(axis.x()) < 1e-8); + assert(std::abs(axis.y()) < 1e-8); + } +#endif /* _DEBUG */ + return (axis.z() < 0) ? -angle : angle; +} + void GLCanvas3D::Selection::rotate(const Vec3d& rotation, bool local) { int rot_axis_max; @@ -1745,13 +1779,14 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation, bool local) assert(rotation.z() == 0); const GLVolume &first_volume = *(*m_volumes)[first_volume_idx]; const Vec3d &rotation = first_volume.get_instance_rotation(); - double z_diff = m_cache.volumes_data[i].get_instance_rotation()(2) - m_cache.volumes_data[first_volume_idx].get_instance_rotation()(2); + double z_diff = rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation()); volume.set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff)); } else { // extracts rotations from the composed transformation Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_instance_rotation_matrix()); - if (!local) + if (rot_axis_max == 2 && !local) + // Only allow rotation of multiple instances as a single rigid body when rotating around the Z axis. volume.set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center)); volume.set_instance_rotation(new_rotation); object_instance_first[volume.object_idx()] = i; @@ -1795,7 +1830,7 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation, bool local) #if !DISABLE_INSTANCES_SYNCH if (m_mode == Instance) - _synchronize_unselected_instances(); + _synchronize_unselected_instances((rot_axis_max == 2) ? SYNC_ROTATION_NONE : SYNC_ROTATION_GENERAL); else if (m_mode == Volume) _synchronize_unselected_volumes(); #endif // !DISABLE_INSTANCES_SYNCH @@ -1838,7 +1873,7 @@ void GLCanvas3D::Selection::flattening_rotate(const Vec3d& normal) // we want to synchronize z-rotation as well, otherwise the flattening behaves funny // when applied on one of several identical instances if (m_mode == Instance) - _synchronize_unselected_instances(true); + _synchronize_unselected_instances(SYNC_ROTATION_FULL); #endif // !DISABLE_INSTANCES_SYNCH m_bounding_box_dirty = true; @@ -1885,7 +1920,7 @@ void GLCanvas3D::Selection::scale(const Vec3d& scale, bool local) #if !DISABLE_INSTANCES_SYNCH if (m_mode == Instance) - _synchronize_unselected_instances(); + _synchronize_unselected_instances(SYNC_ROTATION_NONE); else if (m_mode == Volume) _synchronize_unselected_volumes(); #endif // !DISABLE_INSTANCES_SYNCH @@ -1912,7 +1947,7 @@ void GLCanvas3D::Selection::mirror(Axis axis) #if !DISABLE_INSTANCES_SYNCH if (m_mode == Instance) - _synchronize_unselected_instances(); + _synchronize_unselected_instances(SYNC_ROTATION_NONE); else if (m_mode == Volume) _synchronize_unselected_volumes(); #endif // !DISABLE_INSTANCES_SYNCH @@ -2709,15 +2744,17 @@ void GLCanvas3D::Selection::_render_sidebar_size_hint(Axis axis, double length) } #ifdef _DEBUG -static bool is_rotation_xy_synchronized(const Vec3d &rotation1, const Vec3d &rotation2) +static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to) { - // The XYZ Euler angles are not unique. Rather then comparing the XY components of the two rotations, - // transform the up vector to one instance and back, which should lead to the same up vector. - Transform3d m1 = Geometry::assemble_transform(Vec3d::Zero(), rotation1); - Transform3d m2 = Geometry::assemble_transform(Vec3d::Zero(), rotation2); - Vec3d up0(0., 0., 1.); - Vec3d up = m1.rotation() * m2.rotation().inverse() * up0; - return (up - up0).cwiseAbs().maxCoeff() < EPSILON; + Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to)); + Vec3d axis = angle_axis.axis(); + double angle = angle_axis.angle(); + if (std::abs(angle) < 1e-8) + return true; + assert(std::abs(axis.x()) < 1e-8); + assert(std::abs(axis.y()) < 1e-8); + assert(std::abs(std::abs(axis.z()) - 1.) < 1e-8); + return std::abs(axis.x()) < 1e-8 && std::abs(axis.y()) < 1e-8 && std::abs(std::abs(axis.z()) - 1.) < 1e-8; } static void verify_instances_rotation_synchronized(const Model &model, const GLVolumePtrs &volumes) { @@ -2742,7 +2779,7 @@ static void verify_instances_rotation_synchronized(const Model &model, const GLV } #endif /* _DEBUG */ -void GLCanvas3D::Selection::_synchronize_unselected_instances(bool including_z) +void GLCanvas3D::Selection::_synchronize_unselected_instances(SyncRotationType sync_rotation_type) { std::set done; // prevent processing volumes twice done.insert(m_list.begin(), m_list.end()); @@ -2758,7 +2795,7 @@ void GLCanvas3D::Selection::_synchronize_unselected_instances(bool including_z) continue; int instance_idx = volume->instance_idx(); - const Vec3d& rotation = volume->get_instance_rotation(); + const Vec3d& rotation = volume->get_instance_rotation(); const Vec3d& scaling_factor = volume->get_instance_scaling_factor(); const Vec3d& mirror = volume->get_instance_mirror(); @@ -2775,24 +2812,24 @@ void GLCanvas3D::Selection::_synchronize_unselected_instances(bool including_z) if ((v->object_idx() != object_idx) || (v->instance_idx() == instance_idx)) continue; - auto is_approx = [](double value, double test_value) -> bool { return std::abs(value - test_value) < EPSILON; }; - - double z; - if (including_z) - // rotation comes from place on face -> force given z - z = rotation(2); - else if (is_approx(rotation(0), m_cache.volumes_data[j].get_instance_rotation()(0)) && is_approx(rotation(1), m_cache.volumes_data[j].get_instance_rotation()(1))) { + assert(is_rotation_xy_synchronized(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation())); + switch (sync_rotation_type) { + case SYNC_ROTATION_NONE: // z only rotation -> keep instance z - z = v->get_instance_rotation()(2); // The X,Y rotations should be synchronized from start to end of the rotation. - assert(is_rotation_xy_synchronized(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation())); assert(is_rotation_xy_synchronized(rotation, v->get_instance_rotation())); - } else { + break; + case SYNC_ROTATION_FULL: + // rotation comes from place on face -> force given z + v->set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2))); + break; + case SYNC_ROTATION_GENERAL: // generic rotation -> update instance z with the delta of the rotation. - z = rotation(2) + m_cache.volumes_data[j].get_instance_rotation()(2) - m_cache.volumes_data[i].get_instance_rotation()(2); + double z_diff = rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation()); + v->set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff)); + break; } - v->set_instance_rotation(Vec3d(rotation(0), rotation(1), z)); v->set_instance_scaling_factor(scaling_factor); v->set_instance_mirror(mirror); @@ -4570,7 +4607,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re } if (printer_technology == ptSLA) { const SLAPrint *sla_print = this->sla_print(); - #ifdef _DEBUG + #if 0 // #ifdef _DEBUG // Verify that the SLAPrint object is synchronized with m_model. check_model_ids_equal(*m_model, sla_print->model()); #endif /* _DEBUG */ diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index fb4a465d2..53ab1ed09 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -647,7 +647,15 @@ public: void _render_sidebar_rotation_hint(Axis axis) const; void _render_sidebar_scale_hint(Axis axis) const; void _render_sidebar_size_hint(Axis axis, double length) const; - void _synchronize_unselected_instances(bool including_z = false); + enum SyncRotationType { + // Do not synchronize rotation. Either not rotating at all, or rotating by world Z axis. + SYNC_ROTATION_NONE = 0, + // Synchronize fully. Used from "place on bed" feature. + SYNC_ROTATION_FULL = 1, + // Synchronize after rotation by an axis not parallel with Z. + SYNC_ROTATION_GENERAL = 2, + }; + void _synchronize_unselected_instances(SyncRotationType sync_rotation_type); void _synchronize_unselected_volumes(); void _ensure_on_bed(); }; From 66ecdf61ec6831dc9c6f0a2c130428c1aa252466 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 28 Jan 2019 08:53:02 +0100 Subject: [PATCH 17/23] FIx of the previous commit --- src/slic3r/GUI/GLCanvas3D.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f193af9e0..d96db8945 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1,13 +1,3 @@ -#if 1 -#pragma optimize("", off) -// Enable debugging and assert in this file. -#define DEBUG -#define _DEBUG -#undef NDEBUG -#endif - -#include - #include "slic3r/GUI/GLGizmo.hpp" #include "GLCanvas3D.hpp" @@ -4607,7 +4597,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re } if (printer_technology == ptSLA) { const SLAPrint *sla_print = this->sla_print(); - #if 0 // #ifdef _DEBUG + #ifdef _DEBUG // Verify that the SLAPrint object is synchronized with m_model. check_model_ids_equal(*m_model, sla_print->model()); #endif /* _DEBUG */ From 7c6572025d6c4c300fd02a93274c4007cf1e7e2a Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 28 Jan 2019 09:06:14 +0100 Subject: [PATCH 18/23] Fixed bed centering when changing printer with preview active --- src/slic3r/GUI/GLCanvas3D.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index dd1668831..cfe1a1b56 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4310,9 +4310,6 @@ void GLCanvas3D::set_viewport_from_scene(const GLCanvas3D& other) m_camera.set_scene_box(other.m_camera.get_scene_box(), *this); m_camera.set_target(other.m_camera.get_target(), *this); m_camera.zoom = other.m_camera.zoom; -#if ENABLE_REWORKED_BED_SHAPE_CHANGE - m_requires_zoom_to_bed = false; -#endif // ENABLE_REWORKED_BED_SHAPE_CHANGE m_dirty = true; } From 6f25a933b63a00a639c1aebcb425fed9ff5d678d Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 28 Jan 2019 09:59:22 +0100 Subject: [PATCH 19/23] Removed check of max rotation close to zero in GLCanvas3D::Selection::rotate() --- src/slic3r/GUI/GLCanvas3D.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index fb0768e75..a65478bdc 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1804,10 +1804,12 @@ static double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to void GLCanvas3D::Selection::rotate(const Vec3d& rotation, bool local) { - int rot_axis_max; - if (!m_valid || rotation.cwiseAbs().maxCoeff(&rot_axis_max) < EPSILON) + if (!m_valid) return; + int rot_axis_max; + rotation.cwiseAbs().maxCoeff(&rot_axis_max); + // For generic rotation, we want to rotate the first volume in selection, and then to synchronize the other volumes with it. std::vector object_instance_first(m_model->objects.size(), -1); auto rotate_instance = [this, &rotation, &object_instance_first, rot_axis_max, local](GLVolume &volume, int i) { From adb96bdc2ed13fee2c74e515ec05ed6429c91b30 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 28 Jan 2019 10:10:23 +0100 Subject: [PATCH 20/23] WIP: Optimization of the object's 2D convex silhouette for arrangement, not working yet. --- src/libslic3r/Geometry.cpp | 3 +- src/libslic3r/Model.cpp | 56 +++++++++++++++++++++++++++++++++- src/libslic3r/Model.hpp | 6 ++++ src/libslic3r/ModelArrange.cpp | 53 +++++++++++++++++++++++--------- 4 files changed, 100 insertions(+), 18 deletions(-) diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index b84e2f13d..d8770cbfe 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -207,8 +207,7 @@ static bool sort_pointfs(const Vec3d& a, const Vec3d& b) } // This implementation is based on Andrew's monotone chain 2D convex hull algorithm -Polygon -convex_hull(Points points) +Polygon convex_hull(Points points) { assert(points.size() >= 3); // sort input points diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 593f716fa..d86a180b8 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -912,6 +912,60 @@ BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_ return bb; } +// Calculate 2D convex hull of of a projection of the transformed printable volumes into the XY plane. +// This method is cheap in that it does not make any unnecessary copy of the volume meshes. +// This method is used by the auto arrange function. +Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance) +{ + Points pts; + for (const ModelVolume *v : this->volumes) + if (v->is_model_part()) { + const stl_file &stl = v->mesh.stl; + Transform3d trafo = trafo_instance * v->get_matrix(); + if (stl.v_shared == nullptr) { + // Using the STL faces. + for (unsigned int i = 0; i < stl.stats.number_of_facets; ++ i) { + const stl_facet &facet = stl.facet_start[i]; + for (size_t j = 0; j < 3; ++ j) { + Vec3d p = trafo * facet.vertex[j].cast(); + pts.emplace_back(coord_t(scale_(p.x())), coord_t(scale_(p.y()))); + } + } + } else { + // Using the shared vertices should be a bit quicker than using the STL faces. + for (int i = 0; i < stl.stats.shared_vertices; ++ i) { + Vec3d p = trafo * stl.v_shared[i].cast(); + pts.emplace_back(coord_t(scale_(p.x())), coord_t(scale_(p.y()))); + } + } + } + std::sort(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) < b(0) || (a(0) == b(0) && a(1) < b(1)); }); + pts.erase(std::unique(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) == b(0) && a(1) == b(1); }), pts.end()); + + Polygon hull; + int n = (int)pts.size(); + if (n >= 3) { + int k = 0; + hull.points.resize(2 * n); + // Build lower hull + for (int i = 0; i < n; ++ i) { + while (k >= 2 && pts[i].ccw(hull[k-2], hull[k-1]) <= 0) + -- k; + hull[k ++] = pts[i]; + } + // Build upper hull + for (int i = n-2, t = k+1; i >= 0; i--) { + while (k >= t && pts[i].ccw(hull[k-2], hull[k-1]) <= 0) + -- k; + hull[k ++] = pts[i]; + } + hull.points.resize(k); + assert(hull.points.front() == hull.points.back()); + hull.points.pop_back(); + } + return hull; +} + void ModelObject::center_around_origin() { // calculate the displacements needed to @@ -1099,7 +1153,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b // Perform cut TriangleMeshSlicer tms(&volume->mesh); - tms.cut(z, &upper_mesh, &lower_mesh); + tms.cut(float(z), &upper_mesh, &lower_mesh); // Reset volume transformation except for offset const Vec3d offset = volume->get_offset(); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 0dd73f62f..afc5d0741 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -223,6 +223,12 @@ public: BoundingBoxf3 raw_mesh_bounding_box() const; // A snug bounding box of non-transformed (non-rotated, non-scaled, non-translated) sum of all object volumes. BoundingBoxf3 full_raw_mesh_bounding_box() const; + + // Calculate 2D convex hull of of a projection of the transformed printable volumes into the XY plane. + // This method is cheap in that it does not make any unnecessary copy of the volume meshes. + // This method is used by the auto arrange function. + Polygon convex_hull_2d(const Transform3d &trafo_instance); + void center_around_origin(); void ensure_on_bed(); void translate_instances(const Vec3d& vector); diff --git a/src/libslic3r/ModelArrange.cpp b/src/libslic3r/ModelArrange.cpp index d527db9da..fd3cf8648 100644 --- a/src/libslic3r/ModelArrange.cpp +++ b/src/libslic3r/ModelArrange.cpp @@ -553,24 +553,47 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) { for(ModelObject* objptr : model.objects) { if(objptr) { - TriangleMesh rmesh = objptr->raw_mesh(); - - ModelInstance * finst = objptr->instances.front(); - - // Object instances should carry the same scaling and - // x, y rotation that is why we use the first instance. - // The next line will apply only the full mirroring and scaling - rmesh.transform(finst->get_matrix(true, true, false, false)); - rmesh.rotate_x(float(finst->get_rotation()(X))); - rmesh.rotate_y(float(finst->get_rotation()(Y))); - // TODO export the exact 2D projection. Cannot do it as libnest2d // does not support concave shapes (yet). - auto p = rmesh.convex_hull(); + ClipperLib::Path clpath; +//WIP Vojtech's optimization of the calculation of the convex hull is not working correctly yet. +#if 1 + { + TriangleMesh rmesh = objptr->raw_mesh(); - p.make_clockwise(); - p.append(p.first_point()); - auto clpath = Slic3rMultiPoint_to_ClipperPath(p); + ModelInstance * finst = objptr->instances.front(); + + // Object instances should carry the same scaling and + // x, y rotation that is why we use the first instance. + // The next line will apply only the full mirroring and scaling + rmesh.transform(finst->get_matrix(true, true, false, false)); + rmesh.rotate_x(float(finst->get_rotation()(X))); + rmesh.rotate_y(float(finst->get_rotation()(Y))); + + // TODO export the exact 2D projection. Cannot do it as libnest2d + // does not support concave shapes (yet). + auto p = rmesh.convex_hull(); + + p.make_clockwise(); + p.append(p.first_point()); + clpath = Slic3rMultiPoint_to_ClipperPath(p); + } +#else + // Object instances should carry the same scaling and + // x, y rotation that is why we use the first instance. + { + ModelInstance *finst = objptr->instances.front(); + Vec3d rotation = finst->get_rotation(); + rotation.z() = 0.; + Transform3d trafo_instance = Geometry::assemble_transform(Vec3d::Zero(), rotation, finst->get_scaling_factor(), finst->get_mirror()); + Polygon p = objptr->convex_hull_2d(trafo_instance); + assert(! p.points.empty()); + p.reverse(); + assert(! p.is_counter_clockwise()); + p.append(p.first_point()); + clpath = Slic3rMultiPoint_to_ClipperPath(p); + } +#endif for(ModelInstance* objinst : objptr->instances) { if(objinst) { From 4a5cff3ee2d66a2aae807a96a8cf5abdc3e9b307 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 28 Jan 2019 10:56:02 +0100 Subject: [PATCH 21/23] Reverted the slow auto arrangement of objects on loading. (made configurable, once it is sped up, it will be re-enabled) --- src/slic3r/GUI/Plater.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index bc65d9784..42e404106 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1468,24 +1468,40 @@ std::vector Plater::priv::load_files(const std::vector& input_ return obj_idxs; } +// #define AUTOPLACEMENT_ON_LOAD + std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &model_objects) { const BoundingBoxf bed_shape = bed_shape_bb(); const Vec3d bed_size = Slic3r::to_3d(bed_shape.size().cast(), 1.0) - 2.0 * Vec3d::Ones(); +#ifndef AUTOPLACEMENT_ON_LOAD + bool need_arrange = false; +#endif /* AUTOPLACEMENT_ON_LOAD */ bool scaled_down = false; std::vector obj_idxs; unsigned int obj_count = model.objects.size(); +#ifdef AUTOPLACEMENT_ON_LOAD ModelInstancePtrs new_instances; +#endif /* AUTOPLACEMENT_ON_LOAD */ for (ModelObject *model_object : model_objects) { auto *object = model.add_object(*model_object); std::string object_name = object->name.empty() ? fs::path(object->input_file).filename().string() : object->name; obj_idxs.push_back(obj_count++); if (model_object->instances.empty()) { +#ifdef AUTOPLACEMENT_ON_LOAD 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; + // add a default instance and center object around origin + object->center_around_origin(); // also aligns object to Z = 0 + ModelInstance* instance = object->add_instance(); + instance->set_offset(Slic3r::to_3d(bed_shape.center().cast(), -object->origin_translation(2))); +#endif /* AUTOPLACEMENT_ON_LOAD */ } const Vec3d size = object->bounding_box().size(); @@ -1513,6 +1529,7 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode // print.add_model_object(object); } +#ifdef AUTOPLACEMENT_ON_LOAD // FIXME distance should be a config value ///////////////////////////////// auto min_obj_distance = static_cast(6/SCALING_FACTOR); const auto *bed_shape_opt = config->opt("bed_shape"); @@ -1522,7 +1539,7 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode for(auto& v : bedpoints) bed.append(Point::new_scale(v(0), v(1))); arr::find_new_position(model, new_instances, min_obj_distance, bed); - // ///////////////////////////////////////////////////////////////////////// +#endif /* AUTOPLACEMENT_ON_LOAD */ if (scaled_down) { GUI::show_info(q, From 61d59a7a2e6118c9a5f67207c0ae648f1385d84b Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Mon, 28 Jan 2019 11:58:25 +0100 Subject: [PATCH 22/23] Fix for erroneous support slicing. Adding upper and lower closure for pillars and bridges. --- src/libslic3r/SLA/SLABoilerPlate.hpp | 17 +++++++++-- src/libslic3r/SLA/SLASupportTree.cpp | 43 ++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/SLA/SLABoilerPlate.hpp b/src/libslic3r/SLA/SLABoilerPlate.hpp index 1436be17f..c1096206a 100644 --- a/src/libslic3r/SLA/SLABoilerPlate.hpp +++ b/src/libslic3r/SLA/SLABoilerPlate.hpp @@ -5,8 +5,8 @@ #include #include -#include "ExPolygon.hpp" -#include "TriangleMesh.hpp" +#include +#include namespace Slic3r { namespace sla { @@ -53,7 +53,7 @@ struct Contour3D { void merge(const Contour3D& ctr) { auto s3 = coord_t(points.size()); - auto s = coord_t(indices.size()); + auto s = indices.size(); points.insert(points.end(), ctr.points.begin(), ctr.points.end()); indices.insert(indices.end(), ctr.indices.begin(), ctr.indices.end()); @@ -62,6 +62,17 @@ struct Contour3D { auto& idx = indices[n]; x(idx) += s3; y(idx) += s3; z(idx) += s3; } } + + // Write the index triangle structure to OBJ file for debugging purposes. + void to_obj(std::ostream& stream) { + for(auto& p : points) { + stream << "v " << p.transpose() << "\n"; + } + + for(auto& f : indices) { + stream << "f " << (f + Vec3i(1, 1, 1)).transpose() << "\n"; + } + } }; //using PointSet = Eigen::Matrix; //Eigen::MatrixXd; diff --git a/src/libslic3r/SLA/SLASupportTree.cpp b/src/libslic3r/SLA/SLASupportTree.cpp index 1d7858ead..b7ae95fda 100644 --- a/src/libslic3r/SLA/SLASupportTree.cpp +++ b/src/libslic3r/SLA/SLASupportTree.cpp @@ -9,8 +9,8 @@ #include "SLASpatIndex.hpp" #include "SLABasePool.hpp" -#include "ClipperUtils.hpp" -#include "Model.hpp" +#include +#include #include @@ -176,6 +176,7 @@ Contour3D cylinder(double r, double h, size_t ssteps) { Vec3d jp = {0, 0, 0}; Vec3d endp = {0, 0, h}; + // Upper circle points for(int i = 0; i < steps; ++i) { double phi = i*a; double ex = endp(X) + r*std::cos(phi); @@ -183,6 +184,7 @@ Contour3D cylinder(double r, double h, size_t ssteps) { points.emplace_back(ex, ey, endp(Z)); } + // Lower circle points for(int i = 0; i < steps; ++i) { double phi = i*a; double x = jp(X) + r*std::cos(phi); @@ -190,6 +192,7 @@ Contour3D cylinder(double r, double h, size_t ssteps) { points.emplace_back(x, y, jp(Z)); } + // Now create long triangles connecting upper and lower circles indices.reserve(2*ssteps); auto offs = steps; for(int i = 0; i < steps - 1; ++i) { @@ -197,10 +200,26 @@ Contour3D cylinder(double r, double h, size_t ssteps) { indices.emplace_back(i, offs + i + 1, i + 1); } + // Last triangle connecting the first and last vertices auto last = steps - 1; indices.emplace_back(0, last, offs); indices.emplace_back(last, offs + last, offs); + // According to the slicing algorithms, we need to aid them with generating + // a watertight body. So we create a triangle fan for the upper and lower + // ending of the cylinder to close the geometry. + points.emplace_back(jp); size_t ci = points.size() - 1; + for(int i = 0; i < steps - 1; ++i) + indices.emplace_back(i + offs + 1, i + offs, ci); + + indices.emplace_back(offs, steps + offs - 1, ci); + + points.emplace_back(endp); ci = points.size() - 1; + for(int i = 0; i < steps - 1; ++i) + indices.emplace_back(ci, i, i + 1); + + indices.emplace_back(steps - 1, 0, ci); + return ret; } @@ -352,6 +371,8 @@ struct Pillar { r(radius), steps(st), endpoint(endp), starts_from_head(false) { assert(steps > 0); + assert(jp(Z) > endp(Z)); // Endpoint is below the starting point + int steps_1 = int(steps - 1); auto& points = mesh.points; @@ -382,6 +403,22 @@ struct Pillar { indices.emplace_back(0, steps_1, offs); indices.emplace_back(steps_1, offs + steps_1, offs); + + // According to the slicing algorithms, we need to aid them with + // generating a watertight body. So we create a triangle fan for the + // upper and lower ending of the cylinder to close the geometry. + points.emplace_back(jp); size_t ci = points.size() - 1; + int stepsi = int(steps); + for(int i = 0; i < stepsi - 1; ++i) + indices.emplace_back(ci, i, i + 1); + + indices.emplace_back(stepsi - 1, 0, ci); + + points.emplace_back(endp); ci = points.size() - 1; + for(int i = 0; i < stepsi - 1; ++i) + indices.emplace_back(i + offs + 1, i + offs, ci); + + indices.emplace_back(offs, stepsi + offs - 1, ci); } Pillar(const Junction& junc, const Vec3d& endp): @@ -461,6 +498,8 @@ struct Bridge { Vec3d dir = (j2 - j1).normalized(); double d = distance(j2, j1); + assert(d > 0); + mesh = cylinder(r, d, steps); auto quater = Quaternion::FromTwoVectors(Vec3d{0,0,1}, dir); From ddcb2b1c232041ac8739620bc1acd65b203414bf Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 28 Jan 2019 12:12:14 +0100 Subject: [PATCH 23/23] Fixed a crash caused by double-free on application close event (Linux) --- src/slic3r/GUI/GUI_App.cpp | 22 ++++------------------ src/slic3r/GUI/GUI_App.hpp | 1 - src/slic3r/GUI/MainFrame.cpp | 11 ++++------- 3 files changed, 8 insertions(+), 26 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index c22219fea..9991d98ea 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -270,16 +270,11 @@ void GUI_App::set_label_clr_sys(const wxColour& clr) { void GUI_App::recreate_GUI() { - std::cerr << "recreate_GUI" << std::endl; + // to make sure nobody accesses data from the soon-to-be-destroyed widgets: + tabs_list.clear(); + plater_ = nullptr; - clear_tabs_list(); - if (plater_) { - // before creating a new plater let's delete old one - plater_->Destroy(); - plater_ = nullptr; - } - - MainFrame* topwindow = dynamic_cast(GetTopWindow()); + MainFrame* topwindow = mainframe; mainframe = new MainFrame(); sidebar().obj_list()->init_objects(); // propagate model objects to object list @@ -691,15 +686,6 @@ void GUI_App::load_current_presets() } } -void GUI_App::clear_tabs_list() -{ - for (auto tab : tabs_list) { - tab->Destroy(); - tab = nullptr; - } - tabs_list.clear(); -} - #ifdef __APPLE__ // wxWidgets override to get an event on open files. void GUI_App::MacOpenFiles(const wxArrayString &fileNames) diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index a5b96598f..79da4531d 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -134,7 +134,6 @@ public: bool check_unsaved_changes(); bool checked_tab(Tab* tab); void load_current_presets(); - void clear_tabs_list(); #ifdef __APPLE__ // wxWidgets override to get an event on open files. diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index d47c7f4e8..2df3429fe 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -95,14 +95,10 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL _3DScene::remove_all_canvases(); // Slic3r::GUI::deregister_on_request_update_callback(); - // destroy and set to null tabs and a platter + // set to null tabs and a platter // to avoid any manipulations with them from App->wxEVT_IDLE after of the mainframe closing - wxGetApp().clear_tabs_list(); - if (wxGetApp().plater_) { - // before creating a new plater let's delete old one - wxGetApp().plater_->Destroy(); - wxGetApp().plater_ = nullptr; - } + wxGetApp().tabs_list.clear(); + wxGetApp().plater_ = nullptr; // propagate event event.Skip(); @@ -113,6 +109,7 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL update_ui_from_settings(); // FIXME (?) } + void MainFrame::init_tabpanel() { m_tabpanel = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL);