From 7a82429cf62071b9ab44799a88ca311c983c94e6 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 26 Apr 2023 15:25:49 +0200 Subject: [PATCH 01/17] SPE-1682 - Toolpaths conflicts detection, 1st installment Succesfully enhanced and integrated into PrusaSlicer from BambuStudio: https://github.com/bambulab/BambuStudio/commit/d43c7d5c9293508241ee88cee860ea7ea51c2080 https://github.com/bambulab/BambuStudio/commit/d72b4c1bfe3f0c275241250a0b1797944147b3b7 https://github.com/bambulab/BambuStudio/commit/87eb0f366560b895cb7219a2eb6820027aaf69d3 https://github.com/bambulab/BambuStudio/commit/b5b7264e99ea0872d39455bf61af56209cb4cd39 Code taken from BambuStudio is embedded into tech ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION Changes to adapt the code to PrusaSlicer is embedded into tech ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD Co-authored-by: manch1n Co-authored-by: miaoxin Co-authored-by: lane.wei --- src/libslic3r/CMakeLists.txt | 2 + src/libslic3r/GCode/ConflictChecker.cpp | 301 ++++++++++++++++++++++++ src/libslic3r/GCode/ConflictChecker.hpp | 143 +++++++++++ src/libslic3r/GCode/GCodeProcessor.hpp | 22 ++ src/libslic3r/Print.cpp | 45 ++++ src/libslic3r/Print.hpp | 77 ++++++ src/libslic3r/Technologies.hpp | 23 ++ src/slic3r/GUI/GCodeViewer.cpp | 9 + src/slic3r/GUI/GCodeViewer.hpp | 14 ++ src/slic3r/GUI/GLCanvas3D.cpp | 98 +++++++- src/slic3r/GUI/GLCanvas3D.hpp | 5 + 11 files changed, 738 insertions(+), 1 deletion(-) create mode 100644 src/libslic3r/GCode/ConflictChecker.cpp create mode 100644 src/libslic3r/GCode/ConflictChecker.hpp diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index b578932d4..0de0b4e51 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -138,6 +138,8 @@ set(SLIC3R_SOURCES GCode/ThumbnailData.hpp GCode/Thumbnails.cpp GCode/Thumbnails.hpp + GCode/ConflictChecker.cpp + GCode/ConflictChecker.hpp GCode/CoolingBuffer.cpp GCode/CoolingBuffer.hpp GCode/FindReplace.cpp diff --git a/src/libslic3r/GCode/ConflictChecker.cpp b/src/libslic3r/GCode/ConflictChecker.cpp new file mode 100644 index 000000000..7f8ba2d0c --- /dev/null +++ b/src/libslic3r/GCode/ConflictChecker.cpp @@ -0,0 +1,301 @@ +#include "libslic3r.h" +#include "ConflictChecker.hpp" + +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + +#include +#include + +#include +#include +#include + +namespace Slic3r { + +namespace RasterizationImpl { +using IndexPair = std::pair; +using Grids = std::vector; + +inline constexpr int64_t RasteXDistance = scale_(1); +inline constexpr int64_t RasteYDistance = scale_(1); + +inline IndexPair point_map_grid_index(const Point &pt, int64_t xdist, int64_t ydist) +{ + auto x = pt.x() / xdist; + auto y = pt.y() / ydist; + return std::make_pair(x, y); +} + +inline bool nearly_equal(const Point &p1, const Point &p2) { return std::abs(p1.x() - p2.x()) < SCALED_EPSILON && std::abs(p1.y() - p2.y()) < SCALED_EPSILON; } + +inline Grids line_rasterization(const Line &line, int64_t xdist = RasteXDistance, int64_t ydist = RasteYDistance) +{ + Grids res; + Point rayStart = line.a; + Point rayEnd = line.b; + IndexPair currentVoxel = point_map_grid_index(rayStart, xdist, ydist); + IndexPair firstVoxel = currentVoxel; + IndexPair lastVoxel = point_map_grid_index(rayEnd, xdist, ydist); + + Point ray = rayEnd - rayStart; + + double stepX = ray.x() >= 0 ? 1 : -1; + double stepY = ray.y() >= 0 ? 1 : -1; + + double nextVoxelBoundaryX = (currentVoxel.first + stepX) * xdist; + double nextVoxelBoundaryY = (currentVoxel.second + stepY) * ydist; + + if (stepX < 0) { nextVoxelBoundaryX += xdist; } + if (stepY < 0) { nextVoxelBoundaryY += ydist; } + + double tMaxX = ray.x() != 0 ? (nextVoxelBoundaryX - rayStart.x()) / ray.x() : DBL_MAX; + double tMaxY = ray.y() != 0 ? (nextVoxelBoundaryY - rayStart.y()) / ray.y() : DBL_MAX; + + double tDeltaX = ray.x() != 0 ? static_cast(xdist) / ray.x() * stepX : DBL_MAX; + double tDeltaY = ray.y() != 0 ? static_cast(ydist) / ray.y() * stepY : DBL_MAX; + + res.push_back(currentVoxel); + + double tx = tMaxX; + double ty = tMaxY; + + while (lastVoxel != currentVoxel) { + if (lastVoxel.first == currentVoxel.first) { + for (int64_t i = currentVoxel.second; i != lastVoxel.second; i += (int64_t) stepY) { + currentVoxel.second += (int64_t) stepY; + res.push_back(currentVoxel); + } + break; + } + if (lastVoxel.second == currentVoxel.second) { + for (int64_t i = currentVoxel.first; i != lastVoxel.first; i += (int64_t) stepX) { + currentVoxel.first += (int64_t) stepX; + res.push_back(currentVoxel); + } + break; + } + + if (tx < ty) { + currentVoxel.first += (int64_t) stepX; + tx += tDeltaX; + } else { + currentVoxel.second += (int64_t) stepY; + ty += tDeltaY; + } + res.push_back(currentVoxel); + if (res.size() >= 100000) { // bug + assert(0); + } + } + + return res; +} +} // namespace RasterizationImpl + +void LinesBucketQueue::emplace_back_bucket(std::vector &&paths, const void *objPtr, Point offset) +{ + auto oldSize = _buckets.capacity(); + if (_objsPtrToId.find(objPtr) == _objsPtrToId.end()) { + _objsPtrToId.insert({objPtr, _objsPtrToId.size()}); + _idToObjsPtr.insert({_objsPtrToId.size() - 1, objPtr}); + } + _buckets.emplace_back(std::move(paths), _objsPtrToId[objPtr], offset); + _pq.push(&_buckets.back()); + auto newSize = _buckets.capacity(); + if (oldSize != newSize) { // pointers change + decltype(_pq) newQueue; + for (LinesBucket &bucket : _buckets) { newQueue.push(&bucket); } + std::swap(_pq, newQueue); + } +} + +double LinesBucketQueue::removeLowests() +{ + auto lowest = _pq.top(); + _pq.pop(); + double curHeight = lowest->curHeight(); + std::vector lowests; + lowests.push_back(lowest); + + while (_pq.empty() == false && std::abs(_pq.top()->curHeight() - lowest->curHeight()) < EPSILON) { + lowests.push_back(_pq.top()); + _pq.pop(); + } + + for (LinesBucket *bp : lowests) { + bp->raise(); + if (bp->valid()) { _pq.push(bp); } + } + return curHeight; +} + +LineWithIDs LinesBucketQueue::getCurLines() const +{ + LineWithIDs lines; + for (const LinesBucket &bucket : _buckets) { + if (bucket.valid()) { + LineWithIDs tmpLines = bucket.curLines(); + lines.insert(lines.end(), tmpLines.begin(), tmpLines.end()); + } + } + return lines; +} + +void getExtrusionPathsFromEntity(const ExtrusionEntityCollection *entity, ExtrusionPaths &paths) +{ + std::function getExtrusionPathImpl = [&](const ExtrusionEntityCollection *entity, ExtrusionPaths &paths) { + for (auto entityPtr : entity->entities) { + if (const ExtrusionEntityCollection *collection = dynamic_cast(entityPtr)) { + getExtrusionPathImpl(collection, paths); + } else if (const ExtrusionPath *path = dynamic_cast(entityPtr)) { + paths.push_back(*path); + } else if (const ExtrusionMultiPath *multipath = dynamic_cast(entityPtr)) { + for (const ExtrusionPath &path : multipath->paths) { paths.push_back(path); } + } else if (const ExtrusionLoop *loop = dynamic_cast(entityPtr)) { + for (const ExtrusionPath &path : loop->paths) { paths.push_back(path); } + } + } + }; + getExtrusionPathImpl(entity, paths); +} + +ExtrusionPaths getExtrusionPathsFromLayer(LayerRegionPtrs layerRegionPtrs) +{ + ExtrusionPaths paths; + for (auto regionPtr : layerRegionPtrs) { +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + getExtrusionPathsFromEntity(®ionPtr->perimeters(), paths); + if (!regionPtr->perimeters().empty()) { getExtrusionPathsFromEntity(®ionPtr->fills(), paths); } +#else + getExtrusionPathsFromEntity(®ionPtr->perimeters, paths); + if (regionPtr->perimeters.empty() == false) { getExtrusionPathsFromEntity(®ionPtr->fills, paths); } +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + } + return paths; +} + +ExtrusionPaths getExtrusionPathsFromSupportLayer(SupportLayer *supportLayer) +{ + ExtrusionPaths paths; + getExtrusionPathsFromEntity(&supportLayer->support_fills, paths); + return paths; +} + +std::pair, std::vector> getAllLayersExtrusionPathsFromObject(PrintObject *obj) +{ + std::vector objPaths, supportPaths; + + for (auto layerPtr : obj->layers()) { objPaths.push_back(getExtrusionPathsFromLayer(layerPtr->regions())); } + + for (auto supportLayerPtr : obj->support_layers()) { supportPaths.push_back(getExtrusionPathsFromSupportLayer(supportLayerPtr)); } + + return {std::move(objPaths), std::move(supportPaths)}; +} + +ConflictComputeOpt ConflictChecker::find_inter_of_lines(const LineWithIDs &lines) +{ + using namespace RasterizationImpl; + std::map> indexToLine; + + for (int i = 0; i < lines.size(); ++i) { + const LineWithID &l1 = lines[i]; + auto indexes = line_rasterization(l1._line); + for (auto index : indexes) { + const auto &possibleIntersectIdxs = indexToLine[index]; + for (auto possibleIntersectIdx : possibleIntersectIdxs) { + const LineWithID &l2 = lines[possibleIntersectIdx]; + if (auto interRes = line_intersect(l1, l2); interRes.has_value()) { return interRes; } + } + indexToLine[index].push_back(i); + } + } + return {}; +} + +ConflictResultOpt ConflictChecker::find_inter_of_lines_in_diff_objs(PrintObjectPtrs objs, + std::optional wtdptr) // find the first intersection point of lines in different objects +{ + if (objs.size() <= 1) { return {}; } + LinesBucketQueue conflictQueue; + if (wtdptr.has_value()) { // wipe tower at 0 by default +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + auto wtpaths = (*wtdptr)->getFakeExtrusionPathsFromWipeTower(); + conflictQueue.emplace_back_bucket(std::move(wtpaths), *wtdptr, { (*wtdptr)->plate_origin.x(), (*wtdptr)->plate_origin.y() }); +#else + auto wtpaths = wtdptr.value()->getFakeExtrusionPathsFromWipeTower(); + conflictQueue.emplace_back_bucket(std::move(wtpaths), wtdptr.value(), {wtdptr.value()->plate_origin.x(),wtdptr.value()->plate_origin.y()}); +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + } + for (PrintObject *obj : objs) { + auto layers = getAllLayersExtrusionPathsFromObject(obj); + conflictQueue.emplace_back_bucket(std::move(layers.first), obj, obj->instances().front().shift); + conflictQueue.emplace_back_bucket(std::move(layers.second), obj, obj->instances().front().shift); + } + + std::vector layersLines; + std::vector heights; + while (conflictQueue.valid()) { + LineWithIDs lines = conflictQueue.getCurLines(); + double curHeight = conflictQueue.removeLowests(); + heights.push_back(curHeight); + layersLines.push_back(std::move(lines)); + } + + bool find = false; + tbb::concurrent_vector> conflict; + + tbb::parallel_for(tbb::blocked_range(0, layersLines.size()), [&](tbb::blocked_range range) { + for (size_t i = range.begin(); i < range.end(); i++) { + auto interRes = find_inter_of_lines(layersLines[i]); + if (interRes.has_value()) { + find = true; +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + conflict.emplace_back(*interRes, heights[i]); +#else + conflict.emplace_back(interRes.value(),heights[i]); +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + break; + } + } + }); + + if (find) { + const void *ptr1 = conflictQueue.idToObjsPtr(conflict[0].first._obj1); + const void *ptr2 = conflictQueue.idToObjsPtr(conflict[0].first._obj2); + double conflictHeight = conflict[0].second; + if (wtdptr.has_value()) { +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + const FakeWipeTower* wtdp = *wtdptr; +#else + const FakeWipeTower *wtdp = wtdptr.value(); +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + if (ptr1 == wtdp || ptr2 == wtdp) { + if (ptr2 == wtdp) { std::swap(ptr1, ptr2); } + const PrintObject *obj2 = reinterpret_cast(ptr2); + return std::make_optional("WipeTower", obj2->model_object()->name, conflictHeight, nullptr, ptr2); + } + } + const PrintObject *obj1 = reinterpret_cast(ptr1); + const PrintObject *obj2 = reinterpret_cast(ptr2); + return std::make_optional(obj1->model_object()->name, obj2->model_object()->name, conflictHeight, ptr1, ptr2); + } else + return {}; +} + +ConflictComputeOpt ConflictChecker::line_intersect(const LineWithID &l1, const LineWithID &l2) +{ + if (l1._id == l2._id) { return {}; } // return true if lines are from same object + Point inter; + bool intersect = l1._line.intersection(l2._line, &inter); + if (intersect) { + auto dist1 = std::min(unscale(Point(l1._line.a - inter)).norm(), unscale(Point(l1._line.b - inter)).norm()); + auto dist2 = std::min(unscale(Point(l2._line.a - inter)).norm(), unscale(Point(l2._line.b - inter)).norm()); + auto dist = std::min(dist1, dist2); + if (dist > 0.01) { return std::make_optional(l1._id, l2._id); } // the two lines intersects if dist>0.01mm + } + return {}; +} + +} // namespace Slic3r + +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION diff --git a/src/libslic3r/GCode/ConflictChecker.hpp b/src/libslic3r/GCode/ConflictChecker.hpp new file mode 100644 index 000000000..00c975c37 --- /dev/null +++ b/src/libslic3r/GCode/ConflictChecker.hpp @@ -0,0 +1,143 @@ +#ifndef slic3r_ConflictChecker_hpp_ +#define slic3r_ConflictChecker_hpp_ + +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + +#include "../Utils.hpp" +#include "../Model.hpp" +#include "../Print.hpp" +#include "../Layer.hpp" + +#include +#include +#include + +namespace Slic3r { + +struct LineWithID +{ + Line _line; + int _id; +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + ExtrusionRole _role; + + LineWithID(const Line& line, int id, const ExtrusionRole& role) : _line(line), _id(id), _role(role) {} +#else + int _role; + + LineWithID(const Line& line, int id, int role) : _line(line), _id(id), _role(role) {} +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD +}; + +using LineWithIDs = std::vector; + +class LinesBucket +{ +private: + double _curHeight = 0.0; + unsigned _curPileIdx = 0; + + std::vector _piles; + int _id; + Point _offset; + +public: + LinesBucket(std::vector &&paths, int id, Point offset) : _piles(paths), _id(id), _offset(offset) {} + LinesBucket(LinesBucket &&) = default; + + bool valid() const { return _curPileIdx < _piles.size(); } + void raise() + { + if (valid()) { + if (_piles[_curPileIdx].empty() == false) { _curHeight += _piles[_curPileIdx].front().height; } + _curPileIdx++; + } + } + double curHeight() const { return _curHeight; } + LineWithIDs curLines() const + { + LineWithIDs lines; + for (const ExtrusionPath &path : _piles[_curPileIdx]) { +#if !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + // + // INTEGRATION WHAT TO DO ??? + // we do not define path.is_force_no_extrusion() + // + if (path.is_force_no_extrusion() == false) { +#endif // !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + Polyline check_polyline = path.polyline; + check_polyline.translate(_offset); + Lines tmpLines = check_polyline.lines(); + for (const Line &line : tmpLines) { lines.emplace_back(line, _id, path.role()); } +#if !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + } +#endif // !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + } + return lines; + } + + friend bool operator>(const LinesBucket &left, const LinesBucket &right) { return left._curHeight > right._curHeight; } + friend bool operator<(const LinesBucket &left, const LinesBucket &right) { return left._curHeight < right._curHeight; } + friend bool operator==(const LinesBucket &left, const LinesBucket &right) { return left._curHeight == right._curHeight; } +}; + +struct LinesBucketPtrComp +{ + bool operator()(const LinesBucket *left, const LinesBucket *right) { return *left > *right; } +}; + +class LinesBucketQueue +{ +private: + std::vector _buckets; + std::priority_queue, LinesBucketPtrComp> _pq; + std::map _idToObjsPtr; + std::map _objsPtrToId; + +public: + void emplace_back_bucket(std::vector &&paths, const void *objPtr, Point offset); + bool valid() const { return _pq.empty() == false; } + const void *idToObjsPtr(int id) + { + if (_idToObjsPtr.find(id) != _idToObjsPtr.end()) + return _idToObjsPtr[id]; + else + return nullptr; + } + double removeLowests(); + LineWithIDs getCurLines() const; +}; + +void getExtrusionPathsFromEntity(const ExtrusionEntityCollection *entity, ExtrusionPaths &paths); + +ExtrusionPaths getExtrusionPathsFromLayer(LayerRegionPtrs layerRegionPtrs); + +ExtrusionPaths getExtrusionPathsFromSupportLayer(SupportLayer *supportLayer); + +std::pair, std::vector> getAllLayersExtrusionPathsFromObject(PrintObject *obj); + +struct ConflictComputeResult +{ + int _obj1; + int _obj2; + + ConflictComputeResult(int o1, int o2) : _obj1(o1), _obj2(o2) {} + ConflictComputeResult() = default; +}; + +using ConflictComputeOpt = std::optional; + +using ConflictObjName = std::optional>; + +struct ConflictChecker +{ + static ConflictResultOpt find_inter_of_lines_in_diff_objs(PrintObjectPtrs objs, std::optional wtdptr); + static ConflictComputeOpt find_inter_of_lines(const LineWithIDs &lines); + static ConflictComputeOpt line_intersect(const LineWithID &l1, const LineWithID &l2); +}; + +} // namespace Slic3r + +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + +#endif diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 26cb89894..6a9d5606e 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -82,6 +82,24 @@ namespace Slic3r { } }; +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + struct ConflictResult + { + std::string _objName1; + std::string _objName2; + double _height; + const void* _obj1; // nullptr means wipe tower + const void* _obj2; + int layer = -1; + ConflictResult(const std::string& objName1, const std::string& objName2, double height, const void* obj1, const void* obj2) + : _objName1(objName1), _objName2(objName2), _height(height), _obj1(obj1), _obj2(obj2) + {} + ConflictResult() = default; + }; + + using ConflictResultOpt = std::optional; +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + struct GCodeProcessorResult { struct SettingsIds @@ -137,6 +155,10 @@ namespace Slic3r { std::vector custom_gcode_per_print_z; std::vector>> spiral_vase_layers; +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + ConflictResultOpt conflict_result; +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + #if ENABLE_GCODE_VIEWER_STATISTICS int64_t time{ 0 }; #endif // ENABLE_GCODE_VIEWER_STATISTICS diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index ca3feb04e..b00b8e218 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -11,6 +11,9 @@ #include "Thread.hpp" #include "GCode.hpp" #include "GCode/WipeTower.hpp" +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION +#include "GCode/ConflictChecker.hpp" +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION #include "Utils.hpp" #include "BuildVolume.hpp" #include "format.hpp" @@ -962,6 +965,43 @@ void Print::process() this->finalize_first_layer_convex_hull(); this->set_done(psSkirtBrim); } + +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION +#if !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + // + // INTEGRATION WHAT TO DO ??? + // we do not define m_no_check + // + if (!m_no_check) { + using Clock = std::chrono::high_resolution_clock; + auto startTime = Clock::now(); +#endif // !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + std::optional wipe_tower_opt = {}; + if (this->has_wipe_tower()) { +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + m_fake_wipe_tower.set_pos({ m_config.wipe_tower_x, m_config.wipe_tower_y }); +#else + m_fake_wipe_tower.set_pos({ m_config.wipe_tower_x.get_at(m_plate_index), m_config.wipe_tower_y.get_at(m_plate_index) }); +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + wipe_tower_opt = std::make_optional(&m_fake_wipe_tower); + } + auto conflictRes = ConflictChecker::find_inter_of_lines_in_diff_objs(m_objects, wipe_tower_opt); +#if !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + auto endTime = Clock::now(); + volatile double seconds = std::chrono::duration_cast(endTime - startTime).count() / (double)1000; + BOOST_LOG_TRIVIAL(info) << "gcode path conflicts check takes " << seconds << " secs."; +#endif // !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + + m_conflict_result = conflictRes; + if (conflictRes.has_value()) +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + BOOST_LOG_TRIVIAL(error) << boost::format("gcode path conflicts found between %1% and %2%") % conflictRes->_objName1 % conflictRes->_objName2; +#else + BOOST_LOG_TRIVIAL(error) << boost::format("gcode path conflicts found between %1% and %2%") % conflictRes.value()._objName1 % conflictRes.value()._objName2; + } +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + BOOST_LOG_TRIVIAL(info) << "Slicing process finished." << log_memory_info(); } @@ -987,6 +1027,11 @@ std::string Print::export_gcode(const std::string& path_template, GCodeProcessor // Create GCode on heap, it has quite a lot of data. std::unique_ptr gcode(new GCode); gcode->do_export(this, path.c_str(), result, thumbnail_cb); + +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + result->conflict_result = m_conflict_result; +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + return path.c_str(); } diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 5c42709b1..12058734b 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -418,6 +418,78 @@ private: FillLightning::GeneratorPtr m_lightning_generator; }; +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION +struct FakeWipeTower +{ + // generate fake extrusion + Vec2f pos; + float width; + float height; + float layer_height; + float depth; + float brim_width; + Vec2d plate_origin; + +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + void set_fake_extrusion_data(const Vec2f& p, float w, float h, float lh, float d, float bd, const Vec2d& o) +#else + void set_fake_extrusion_data(Vec2f p, float w, float h, float lh, float d, float bd, Vec2d o) +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + { + pos = p; + width = w; + height = h; + layer_height = lh; + depth = d; + brim_width = bd; + plate_origin = o; + } + +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + void set_pos(const Vec2f& p) { pos = p; } +#else + void set_pos(Vec2f p) { pos = p; } +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + + std::vector getFakeExtrusionPathsFromWipeTower() const + { + float h = height; + float lh = layer_height; + int d = scale_(depth); + int w = scale_(width); + int bd = scale_(brim_width); + Point minCorner = { scale_(pos.x()), scale_(pos.y()) }; + Point maxCorner = { minCorner.x() + w, minCorner.y() + d }; + + std::vector paths; + for (float hh = 0.f; hh < h; hh += lh) { +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + ExtrusionPath path(ExtrusionRole::WipeTower, 0.0, 0.0, lh); +#else + ExtrusionPath path(ExtrusionRole::erWipeTower, 0.0, 0.0, lh); +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + path.polyline = { minCorner, {maxCorner.x(), minCorner.y()}, maxCorner, {minCorner.x(), maxCorner.y()}, minCorner }; + paths.push_back({ path }); + +#if !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + // + // INTEGRATION WHAT TO DO ??? + // we do not define erBrim + // + if (hh == 0.f) { // add brim + ExtrusionPath fakeBrim(ExtrusionRole::erBrim, 0.0, 0.0, lh); + Point wtbminCorner = { minCorner - Point{bd, bd} }; + Point wtbmaxCorner = { maxCorner + Point{bd, bd} }; + fakeBrim.polyline = { wtbminCorner, {wtbmaxCorner.x(), wtbminCorner.y()}, wtbmaxCorner, {wtbminCorner.x(), wtbmaxCorner.y()}, wtbminCorner }; + paths.back().push_back(fakeBrim); + } +#endif // !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + } + return paths; + } +}; +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + struct WipeTowerData { // Following section will be consumed by the GCodeGenerator. @@ -668,6 +740,11 @@ private: friend class GCodeProcessor; // Allow PrintObject to access m_mutex and m_cancel_callback. friend class PrintObject; + +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + ConflictResultOpt m_conflict_result; + FakeWipeTower m_fake_wipe_tower; +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION }; } /* slic3r_Print_hpp_ */ diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 602654633..36b51fe2d 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -62,4 +62,27 @@ #define ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR (1 && ENABLE_2_6_0_ALPHA1) +//==================== +// 2.6.0.beta1 techs +//==================== +#define ENABLE_2_6_0_BETA1 1 + +// Toolpaths conflicts detection +// Succesfully enhanced and integrated into PrusaSlicer from BambuStudio: +// https://github.com/bambulab/BambuStudio/commit/d43c7d5c9293508241ee88cee860ea7ea51c2080 +// https://github.com/bambulab/BambuStudio/commit/d72b4c1bfe3f0c275241250a0b1797944147b3b7 +// https://github.com/bambulab/BambuStudio/commit/87eb0f366560b895cb7219a2eb6820027aaf69d3 +// https://github.com/bambulab/BambuStudio/commit/b5b7264e99ea0872d39455bf61af56209cb4cd39 +// Co-authored-by: manch1n +// Co-authored-by: miaoxin +// Co-authored-by: lane.wei + +#define ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION (1 && ENABLE_2_6_0_BETA1) + +// Modifications to original BambuStudio code: +// * compliance with PS code +// * removed code which has no clear counterpart in PS +#define ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD (1 && ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION) + + #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index a9e016bb9..5261113e0 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -799,6 +799,15 @@ void GCodeViewer::load(const GCodeProcessorResult& gcode_result, const Print& pr short_time(get_time_dhms(time)) == short_time(get_time_dhms(m_print_statistics.modes[static_cast(PrintEstimatedStatistics::ETimeMode::Normal)].time))) m_time_estimate_mode = PrintEstimatedStatistics::ETimeMode::Normal; } + +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + m_conflict_result = gcode_result.conflict_result; +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + if (m_conflict_result.has_value()) { m_conflict_result->layer = m_layers.get_l_at(m_conflict_result->_height); } +#else + if (m_conflict_result) { m_conflict_result.value().layer = m_layers.get_l_at(m_conflict_result.value()._height); } +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION } void GCodeViewer::refresh(const GCodeProcessorResult& gcode_result, const std::vector& str_tool_colors) diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 3eb61cfc4..a8290350d 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -526,6 +526,12 @@ class GCodeViewer std::vector& get_ranges() { return m_ranges; } double get_z_at(unsigned int id) const { return (id < m_zs.size()) ? m_zs[id] : 0.0; } Range get_range_at(unsigned int id) const { return (id < m_ranges.size()) ? m_ranges[id] : Range(); } +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + int get_l_at(double z) const { + auto iter = std::upper_bound(m_zs.begin(), m_zs.end(), z); + return std::distance(m_zs.begin(), iter); + } +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION bool operator != (const Layers& other) const { if (m_zs != other.m_zs) @@ -784,6 +790,10 @@ private: bool m_contained_in_bed{ true }; +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + ConflictResultOpt m_conflict_result; +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + public: GCodeViewer(); ~GCodeViewer() { reset(); } @@ -841,6 +851,10 @@ public: void invalidate_legend() { m_legend_resizer.reset(); } +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + const ConflictResultOpt& get_conflict_result() const { return m_conflict_result; } +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + private: void load_toolpaths(const GCodeProcessorResult& gcode_result); void load_shells(const Print& print); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 3beaa591a..14db2f8df 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2692,6 +2692,9 @@ void GLCanvas3D::load_gcode_preview(const GCodeProcessorResult& gcode_result, co if (wxGetApp().is_editor()) { m_gcode_viewer.update_shells_color_by_extruder(m_config); _set_warning_notification_if_needed(EWarning::ToolpathOutside); +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + _set_warning_notification_if_needed(EWarning::GCodeConflict); +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION } m_gcode_viewer.refresh(gcode_result, str_tool_colors); @@ -7440,8 +7443,21 @@ void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning) } else { if (wxGetApp().is_editor()) { - if (current_printer_technology() != ptSLA) +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + if (current_printer_technology() != ptSLA) { + if (warning == EWarning::ToolpathOutside) + show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed(); + else if (warning == EWarning::GCodeConflict) +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + show = m_gcode_viewer.has_data() && m_gcode_viewer.is_contained_in_bed() && m_gcode_viewer.get_conflict_result().has_value(); +#else + show = m_gcode_viewer.has_data() && m_gcode_viewer.is_contained_in_bed() && m_gcode_viewer.m_conflict_result.has_value(); +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + } +#else + if (current_printer_technology() != ptSLA) show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed(); +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION } } @@ -7467,8 +7483,88 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) "Resolve the current problem to continue slicing."); error = ErrorType::PLATER_ERROR; break; +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + case EWarning::GCodeConflict: { +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + const ConflictResultOpt& conflict_result = m_gcode_viewer.get_conflict_result(); + if (!conflict_result.has_value()) { break; } + std::string objName1 = conflict_result->_objName1; + std::string objName2 = conflict_result->_objName2; + double height = conflict_result->_height; + int layer = conflict_result->layer; + text = (boost::format(_u8L("Conflicts of gcode paths have been found at layer %d, z = %.2lf mm. Please separate the conflicted objects farther (%s <-> %s).")) % layer % + height % objName1 % objName2).str(); +#else + if (!m_gcode_viewer.m_conflict_result) { break; } + std::string objName1 = m_gcode_viewer.m_conflict_result.value()._objName1; + std::string objName2 = m_gcode_viewer.m_conflict_result.value()._objName2; + double height = m_gcode_viewer.m_conflict_result.value()._height; + int layer = m_gcode_viewer.m_conflict_result.value().layer; + text = (boost::format(_u8L("Conflicts of gcode paths have been found at layer %d, z = %.2lf mm. Please separate the conflicted objects farther (%s <-> %s).")) % layer % + height % objName1 % objName2) + .str(); +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + error = ErrorType::SLICING_ERROR; + break; + } +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION } auto& notification_manager = *wxGetApp().plater()->get_notification_manager(); + +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + const ConflictResultOpt& conflict_result = m_gcode_viewer.get_conflict_result(); + if (warning == EWarning::GCodeConflict) { + if (conflict_result.has_value()) { + const PrintObject* obj2 = reinterpret_cast(conflict_result->_obj2); +#else + if (warning == EWarning::GCodeConflict && m_gcode_viewer.m_conflict_result) { + const PrintObject* obj2 = reinterpret_cast(m_gcode_viewer.m_conflict_result.value()._obj2); +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + auto mo = obj2->model_object(); + ObjectID id = mo->id(); +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + auto action_fn = [this, id](wxEvtHandler*) { +#else + auto action_fn = [id](wxEvtHandler*) { +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + auto& objects = wxGetApp().model().objects; + auto iter = id.id ? std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; }) : objects.end(); + if (iter != objects.end()) { +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + const unsigned int obj_idx = std::distance(objects.begin(), iter); + wxGetApp().CallAfter([this, obj_idx]() { + wxGetApp().plater()->select_view_3D("3D"); + wxGetApp().plater()->canvas3D()->get_selection().add_object(obj_idx, true); + wxGetApp().obj_list()->update_selections(); + }); +#else + wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor); + wxGetApp().obj_list()->select_items({ { *iter, nullptr } }); +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + } + return false; + }; + auto hypertext = _u8L("Jump to"); + hypertext += std::string(" [") + mo->name + "]"; +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + notification_manager.push_notification(NotificationType::SlicingError, NotificationManager::NotificationLevel::ErrorNotificationLevel, + _u8L("ERROR:") + "\n" + text, hypertext, action_fn); +#else + notification_manager.push_notification(NotificationType::PlaterError, NotificationManager::NotificationLevel::ErrorNotificationLevel, + _u8L("ERROR:") + "\n" + text, hypertext, action_fn); + return; +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + } +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + else + notification_manager.close_slicing_error_notification(text); + + return; + } +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + switch (error) { case PLATER_WARNING: diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index a58decbcd..613d97698 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -362,7 +362,12 @@ class GLCanvas3D ToolpathOutside, SlaSupportsOutside, SomethingNotShown, +#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + ObjectClashed, + GCodeConflict +#else ObjectClashed +#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION }; class RenderStats From 417c85b83b06022e3776fe479980c9e119c54f4b Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 26 Apr 2023 15:47:55 +0200 Subject: [PATCH 02/17] Tech ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD set as default --- src/libslic3r/GCode/ConflictChecker.cpp | 18 --------- src/libslic3r/GCode/ConflictChecker.hpp | 24 ++---------- src/libslic3r/Print.cpp | 41 +++++--------------- src/libslic3r/Print.hpp | 26 ------------- src/libslic3r/Technologies.hpp | 5 --- src/slic3r/GUI/GCodeViewer.cpp | 4 -- src/slic3r/GUI/GLCanvas3D.cpp | 51 ++++--------------------- 7 files changed, 20 insertions(+), 149 deletions(-) diff --git a/src/libslic3r/GCode/ConflictChecker.cpp b/src/libslic3r/GCode/ConflictChecker.cpp index 7f8ba2d0c..064bb3620 100644 --- a/src/libslic3r/GCode/ConflictChecker.cpp +++ b/src/libslic3r/GCode/ConflictChecker.cpp @@ -163,13 +163,8 @@ ExtrusionPaths getExtrusionPathsFromLayer(LayerRegionPtrs layerRegionPtrs) { ExtrusionPaths paths; for (auto regionPtr : layerRegionPtrs) { -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD getExtrusionPathsFromEntity(®ionPtr->perimeters(), paths); if (!regionPtr->perimeters().empty()) { getExtrusionPathsFromEntity(®ionPtr->fills(), paths); } -#else - getExtrusionPathsFromEntity(®ionPtr->perimeters, paths); - if (regionPtr->perimeters.empty() == false) { getExtrusionPathsFromEntity(®ionPtr->fills, paths); } -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD } return paths; } @@ -218,13 +213,8 @@ ConflictResultOpt ConflictChecker::find_inter_of_lines_in_diff_objs(PrintObjectP if (objs.size() <= 1) { return {}; } LinesBucketQueue conflictQueue; if (wtdptr.has_value()) { // wipe tower at 0 by default -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD auto wtpaths = (*wtdptr)->getFakeExtrusionPathsFromWipeTower(); conflictQueue.emplace_back_bucket(std::move(wtpaths), *wtdptr, { (*wtdptr)->plate_origin.x(), (*wtdptr)->plate_origin.y() }); -#else - auto wtpaths = wtdptr.value()->getFakeExtrusionPathsFromWipeTower(); - conflictQueue.emplace_back_bucket(std::move(wtpaths), wtdptr.value(), {wtdptr.value()->plate_origin.x(),wtdptr.value()->plate_origin.y()}); -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD } for (PrintObject *obj : objs) { auto layers = getAllLayersExtrusionPathsFromObject(obj); @@ -249,11 +239,7 @@ ConflictResultOpt ConflictChecker::find_inter_of_lines_in_diff_objs(PrintObjectP auto interRes = find_inter_of_lines(layersLines[i]); if (interRes.has_value()) { find = true; -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD conflict.emplace_back(*interRes, heights[i]); -#else - conflict.emplace_back(interRes.value(),heights[i]); -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD break; } } @@ -264,11 +250,7 @@ ConflictResultOpt ConflictChecker::find_inter_of_lines_in_diff_objs(PrintObjectP const void *ptr2 = conflictQueue.idToObjsPtr(conflict[0].first._obj2); double conflictHeight = conflict[0].second; if (wtdptr.has_value()) { -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD const FakeWipeTower* wtdp = *wtdptr; -#else - const FakeWipeTower *wtdp = wtdptr.value(); -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD if (ptr1 == wtdp || ptr2 == wtdp) { if (ptr2 == wtdp) { std::swap(ptr1, ptr2); } const PrintObject *obj2 = reinterpret_cast(ptr2); diff --git a/src/libslic3r/GCode/ConflictChecker.hpp b/src/libslic3r/GCode/ConflictChecker.hpp index 00c975c37..39191f059 100644 --- a/src/libslic3r/GCode/ConflictChecker.hpp +++ b/src/libslic3r/GCode/ConflictChecker.hpp @@ -18,15 +18,9 @@ struct LineWithID { Line _line; int _id; -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD ExtrusionRole _role; LineWithID(const Line& line, int id, const ExtrusionRole& role) : _line(line), _id(id), _role(role) {} -#else - int _role; - - LineWithID(const Line& line, int id, int role) : _line(line), _id(id), _role(role) {} -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD }; using LineWithIDs = std::vector; @@ -58,20 +52,10 @@ public: { LineWithIDs lines; for (const ExtrusionPath &path : _piles[_curPileIdx]) { -#if !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD - // - // INTEGRATION WHAT TO DO ??? - // we do not define path.is_force_no_extrusion() - // - if (path.is_force_no_extrusion() == false) { -#endif // !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD - Polyline check_polyline = path.polyline; - check_polyline.translate(_offset); - Lines tmpLines = check_polyline.lines(); - for (const Line &line : tmpLines) { lines.emplace_back(line, _id, path.role()); } -#if !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD - } -#endif // !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + Polyline check_polyline = path.polyline; + check_polyline.translate(_offset); + Lines tmpLines = check_polyline.lines(); + for (const Line &line : tmpLines) { lines.emplace_back(line, _id, path.role()); } } return lines; } diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index b00b8e218..df24f2b11 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -967,39 +967,16 @@ void Print::process() } #if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION -#if !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD - // - // INTEGRATION WHAT TO DO ??? - // we do not define m_no_check - // - if (!m_no_check) { - using Clock = std::chrono::high_resolution_clock; - auto startTime = Clock::now(); -#endif // !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD - std::optional wipe_tower_opt = {}; - if (this->has_wipe_tower()) { -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD - m_fake_wipe_tower.set_pos({ m_config.wipe_tower_x, m_config.wipe_tower_y }); -#else - m_fake_wipe_tower.set_pos({ m_config.wipe_tower_x.get_at(m_plate_index), m_config.wipe_tower_y.get_at(m_plate_index) }); -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD - wipe_tower_opt = std::make_optional(&m_fake_wipe_tower); - } - auto conflictRes = ConflictChecker::find_inter_of_lines_in_diff_objs(m_objects, wipe_tower_opt); -#if !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD - auto endTime = Clock::now(); - volatile double seconds = std::chrono::duration_cast(endTime - startTime).count() / (double)1000; - BOOST_LOG_TRIVIAL(info) << "gcode path conflicts check takes " << seconds << " secs."; -#endif // !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD - - m_conflict_result = conflictRes; - if (conflictRes.has_value()) -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD - BOOST_LOG_TRIVIAL(error) << boost::format("gcode path conflicts found between %1% and %2%") % conflictRes->_objName1 % conflictRes->_objName2; -#else - BOOST_LOG_TRIVIAL(error) << boost::format("gcode path conflicts found between %1% and %2%") % conflictRes.value()._objName1 % conflictRes.value()._objName2; + std::optional wipe_tower_opt = {}; + if (this->has_wipe_tower()) { + m_fake_wipe_tower.set_pos({ m_config.wipe_tower_x, m_config.wipe_tower_y }); + wipe_tower_opt = std::make_optional(&m_fake_wipe_tower); } -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + auto conflictRes = ConflictChecker::find_inter_of_lines_in_diff_objs(m_objects, wipe_tower_opt); + + m_conflict_result = conflictRes; + if (conflictRes.has_value()) + BOOST_LOG_TRIVIAL(error) << boost::format("gcode path conflicts found between %1% and %2%") % conflictRes->_objName1 % conflictRes->_objName2; #endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION BOOST_LOG_TRIVIAL(info) << "Slicing process finished." << log_memory_info(); diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 12058734b..6ecc7abf3 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -430,11 +430,7 @@ struct FakeWipeTower float brim_width; Vec2d plate_origin; -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD void set_fake_extrusion_data(const Vec2f& p, float w, float h, float lh, float d, float bd, const Vec2d& o) -#else - void set_fake_extrusion_data(Vec2f p, float w, float h, float lh, float d, float bd, Vec2d o) -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD { pos = p; width = w; @@ -445,11 +441,7 @@ struct FakeWipeTower plate_origin = o; } -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD void set_pos(const Vec2f& p) { pos = p; } -#else - void set_pos(Vec2f p) { pos = p; } -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD std::vector getFakeExtrusionPathsFromWipeTower() const { @@ -463,27 +455,9 @@ struct FakeWipeTower std::vector paths; for (float hh = 0.f; hh < h; hh += lh) { -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD ExtrusionPath path(ExtrusionRole::WipeTower, 0.0, 0.0, lh); -#else - ExtrusionPath path(ExtrusionRole::erWipeTower, 0.0, 0.0, lh); -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD path.polyline = { minCorner, {maxCorner.x(), minCorner.y()}, maxCorner, {minCorner.x(), maxCorner.y()}, minCorner }; paths.push_back({ path }); - -#if !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD - // - // INTEGRATION WHAT TO DO ??? - // we do not define erBrim - // - if (hh == 0.f) { // add brim - ExtrusionPath fakeBrim(ExtrusionRole::erBrim, 0.0, 0.0, lh); - Point wtbminCorner = { minCorner - Point{bd, bd} }; - Point wtbmaxCorner = { maxCorner + Point{bd, bd} }; - fakeBrim.polyline = { wtbminCorner, {wtbmaxCorner.x(), wtbminCorner.y()}, wtbmaxCorner, {wtbminCorner.x(), wtbmaxCorner.y()}, wtbminCorner }; - paths.back().push_back(fakeBrim); - } -#endif // !ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD } return paths; } diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 36b51fe2d..c54498a98 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -79,10 +79,5 @@ #define ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION (1 && ENABLE_2_6_0_BETA1) -// Modifications to original BambuStudio code: -// * compliance with PS code -// * removed code which has no clear counterpart in PS -#define ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD (1 && ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION) - #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 5261113e0..aec674459 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -802,11 +802,7 @@ void GCodeViewer::load(const GCodeProcessorResult& gcode_result, const Print& pr #if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION m_conflict_result = gcode_result.conflict_result; -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD if (m_conflict_result.has_value()) { m_conflict_result->layer = m_layers.get_l_at(m_conflict_result->_height); } -#else - if (m_conflict_result) { m_conflict_result.value().layer = m_layers.get_l_at(m_conflict_result.value()._height); } -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD #endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 14db2f8df..048449a4c 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -7448,11 +7448,7 @@ void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning) if (warning == EWarning::ToolpathOutside) show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed(); else if (warning == EWarning::GCodeConflict) -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD show = m_gcode_viewer.has_data() && m_gcode_viewer.is_contained_in_bed() && m_gcode_viewer.get_conflict_result().has_value(); -#else - show = m_gcode_viewer.has_data() && m_gcode_viewer.is_contained_in_bed() && m_gcode_viewer.m_conflict_result.has_value(); -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD } #else if (current_printer_technology() != ptSLA) @@ -7485,25 +7481,14 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) break; #if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION case EWarning::GCodeConflict: { -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD - const ConflictResultOpt& conflict_result = m_gcode_viewer.get_conflict_result(); - if (!conflict_result.has_value()) { break; } - std::string objName1 = conflict_result->_objName1; - std::string objName2 = conflict_result->_objName2; - double height = conflict_result->_height; - int layer = conflict_result->layer; - text = (boost::format(_u8L("Conflicts of gcode paths have been found at layer %d, z = %.2lf mm. Please separate the conflicted objects farther (%s <-> %s).")) % layer % - height % objName1 % objName2).str(); -#else - if (!m_gcode_viewer.m_conflict_result) { break; } - std::string objName1 = m_gcode_viewer.m_conflict_result.value()._objName1; - std::string objName2 = m_gcode_viewer.m_conflict_result.value()._objName2; - double height = m_gcode_viewer.m_conflict_result.value()._height; - int layer = m_gcode_viewer.m_conflict_result.value().layer; + const ConflictResultOpt& conflict_result = m_gcode_viewer.get_conflict_result(); + if (!conflict_result.has_value()) { break; } + std::string objName1 = conflict_result->_objName1; + std::string objName2 = conflict_result->_objName2; + double height = conflict_result->_height; + int layer = conflict_result->layer; text = (boost::format(_u8L("Conflicts of gcode paths have been found at layer %d, z = %.2lf mm. Please separate the conflicted objects farther (%s <-> %s).")) % layer % - height % objName1 % objName2) - .str(); -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD + height % objName1 % objName2).str(); error = ErrorType::SLICING_ERROR; break; } @@ -7512,57 +7497,35 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) auto& notification_manager = *wxGetApp().plater()->get_notification_manager(); #if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD const ConflictResultOpt& conflict_result = m_gcode_viewer.get_conflict_result(); if (warning == EWarning::GCodeConflict) { if (conflict_result.has_value()) { const PrintObject* obj2 = reinterpret_cast(conflict_result->_obj2); -#else - if (warning == EWarning::GCodeConflict && m_gcode_viewer.m_conflict_result) { - const PrintObject* obj2 = reinterpret_cast(m_gcode_viewer.m_conflict_result.value()._obj2); -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD auto mo = obj2->model_object(); ObjectID id = mo->id(); -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD auto action_fn = [this, id](wxEvtHandler*) { -#else - auto action_fn = [id](wxEvtHandler*) { -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD auto& objects = wxGetApp().model().objects; auto iter = id.id ? std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; }) : objects.end(); if (iter != objects.end()) { -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD const unsigned int obj_idx = std::distance(objects.begin(), iter); wxGetApp().CallAfter([this, obj_idx]() { wxGetApp().plater()->select_view_3D("3D"); wxGetApp().plater()->canvas3D()->get_selection().add_object(obj_idx, true); wxGetApp().obj_list()->update_selections(); }); -#else - wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor); - wxGetApp().obj_list()->select_items({ { *iter, nullptr } }); -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD } return false; }; auto hypertext = _u8L("Jump to"); hypertext += std::string(" [") + mo->name + "]"; -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD notification_manager.push_notification(NotificationType::SlicingError, NotificationManager::NotificationLevel::ErrorNotificationLevel, _u8L("ERROR:") + "\n" + text, hypertext, action_fn); -#else - notification_manager.push_notification(NotificationType::PlaterError, NotificationManager::NotificationLevel::ErrorNotificationLevel, - _u8L("ERROR:") + "\n" + text, hypertext, action_fn); - return; -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD } -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD else notification_manager.close_slicing_error_notification(text); return; } -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION_MOD #endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION switch (error) From 6944c30f879c92bd3a25db05c3d62f1ac78a7b9e Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 27 Apr 2023 08:49:56 +0200 Subject: [PATCH 03/17] Tech ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION set as default --- src/libslic3r/GCode/ConflictChecker.cpp | 3 --- src/libslic3r/GCode/ConflictChecker.hpp | 4 ---- src/libslic3r/GCode/GCodeProcessor.hpp | 4 ---- src/libslic3r/Print.cpp | 6 ------ src/libslic3r/Print.hpp | 4 ---- src/libslic3r/Technologies.hpp | 18 ------------------ src/slic3r/GUI/GCodeViewer.cpp | 2 -- src/slic3r/GUI/GCodeViewer.hpp | 6 ------ src/slic3r/GUI/GLCanvas3D.cpp | 23 ++++++----------------- src/slic3r/GUI/GLCanvas3D.hpp | 4 ---- 10 files changed, 6 insertions(+), 68 deletions(-) diff --git a/src/libslic3r/GCode/ConflictChecker.cpp b/src/libslic3r/GCode/ConflictChecker.cpp index 064bb3620..cf4fe751a 100644 --- a/src/libslic3r/GCode/ConflictChecker.cpp +++ b/src/libslic3r/GCode/ConflictChecker.cpp @@ -1,8 +1,6 @@ #include "libslic3r.h" #include "ConflictChecker.hpp" -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION - #include #include @@ -280,4 +278,3 @@ ConflictComputeOpt ConflictChecker::line_intersect(const LineWithID &l1, const L } // namespace Slic3r -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION diff --git a/src/libslic3r/GCode/ConflictChecker.hpp b/src/libslic3r/GCode/ConflictChecker.hpp index 39191f059..cc21bc816 100644 --- a/src/libslic3r/GCode/ConflictChecker.hpp +++ b/src/libslic3r/GCode/ConflictChecker.hpp @@ -1,8 +1,6 @@ #ifndef slic3r_ConflictChecker_hpp_ #define slic3r_ConflictChecker_hpp_ -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION - #include "../Utils.hpp" #include "../Model.hpp" #include "../Print.hpp" @@ -122,6 +120,4 @@ struct ConflictChecker } // namespace Slic3r -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION - #endif diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 6a9d5606e..76395f435 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -82,7 +82,6 @@ namespace Slic3r { } }; -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION struct ConflictResult { std::string _objName1; @@ -98,7 +97,6 @@ namespace Slic3r { }; using ConflictResultOpt = std::optional; -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION struct GCodeProcessorResult { @@ -155,9 +153,7 @@ namespace Slic3r { std::vector custom_gcode_per_print_z; std::vector>> spiral_vase_layers; -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION ConflictResultOpt conflict_result; -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION #if ENABLE_GCODE_VIEWER_STATISTICS int64_t time{ 0 }; diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index df24f2b11..57ccc9a82 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -11,9 +11,7 @@ #include "Thread.hpp" #include "GCode.hpp" #include "GCode/WipeTower.hpp" -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION #include "GCode/ConflictChecker.hpp" -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION #include "Utils.hpp" #include "BuildVolume.hpp" #include "format.hpp" @@ -966,7 +964,6 @@ void Print::process() this->set_done(psSkirtBrim); } -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION std::optional wipe_tower_opt = {}; if (this->has_wipe_tower()) { m_fake_wipe_tower.set_pos({ m_config.wipe_tower_x, m_config.wipe_tower_y }); @@ -977,7 +974,6 @@ void Print::process() m_conflict_result = conflictRes; if (conflictRes.has_value()) BOOST_LOG_TRIVIAL(error) << boost::format("gcode path conflicts found between %1% and %2%") % conflictRes->_objName1 % conflictRes->_objName2; -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION BOOST_LOG_TRIVIAL(info) << "Slicing process finished." << log_memory_info(); } @@ -1005,9 +1001,7 @@ std::string Print::export_gcode(const std::string& path_template, GCodeProcessor std::unique_ptr gcode(new GCode); gcode->do_export(this, path.c_str(), result, thumbnail_cb); -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION result->conflict_result = m_conflict_result; -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION return path.c_str(); } diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 6ecc7abf3..5449d4897 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -418,7 +418,6 @@ private: FillLightning::GeneratorPtr m_lightning_generator; }; -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION struct FakeWipeTower { // generate fake extrusion @@ -462,7 +461,6 @@ struct FakeWipeTower return paths; } }; -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION struct WipeTowerData { @@ -715,10 +713,8 @@ private: // Allow PrintObject to access m_mutex and m_cancel_callback. friend class PrintObject; -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION ConflictResultOpt m_conflict_result; FakeWipeTower m_fake_wipe_tower; -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION }; } /* slic3r_Print_hpp_ */ diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index c54498a98..602654633 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -62,22 +62,4 @@ #define ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR (1 && ENABLE_2_6_0_ALPHA1) -//==================== -// 2.6.0.beta1 techs -//==================== -#define ENABLE_2_6_0_BETA1 1 - -// Toolpaths conflicts detection -// Succesfully enhanced and integrated into PrusaSlicer from BambuStudio: -// https://github.com/bambulab/BambuStudio/commit/d43c7d5c9293508241ee88cee860ea7ea51c2080 -// https://github.com/bambulab/BambuStudio/commit/d72b4c1bfe3f0c275241250a0b1797944147b3b7 -// https://github.com/bambulab/BambuStudio/commit/87eb0f366560b895cb7219a2eb6820027aaf69d3 -// https://github.com/bambulab/BambuStudio/commit/b5b7264e99ea0872d39455bf61af56209cb4cd39 -// Co-authored-by: manch1n -// Co-authored-by: miaoxin -// Co-authored-by: lane.wei - -#define ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION (1 && ENABLE_2_6_0_BETA1) - - #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index aec674459..38575c610 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -800,10 +800,8 @@ void GCodeViewer::load(const GCodeProcessorResult& gcode_result, const Print& pr m_time_estimate_mode = PrintEstimatedStatistics::ETimeMode::Normal; } -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION m_conflict_result = gcode_result.conflict_result; if (m_conflict_result.has_value()) { m_conflict_result->layer = m_layers.get_l_at(m_conflict_result->_height); } -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION } void GCodeViewer::refresh(const GCodeProcessorResult& gcode_result, const std::vector& str_tool_colors) diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index a8290350d..32d0a91e3 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -526,12 +526,10 @@ class GCodeViewer std::vector& get_ranges() { return m_ranges; } double get_z_at(unsigned int id) const { return (id < m_zs.size()) ? m_zs[id] : 0.0; } Range get_range_at(unsigned int id) const { return (id < m_ranges.size()) ? m_ranges[id] : Range(); } -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION int get_l_at(double z) const { auto iter = std::upper_bound(m_zs.begin(), m_zs.end(), z); return std::distance(m_zs.begin(), iter); } -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION bool operator != (const Layers& other) const { if (m_zs != other.m_zs) @@ -790,9 +788,7 @@ private: bool m_contained_in_bed{ true }; -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION ConflictResultOpt m_conflict_result; -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION public: GCodeViewer(); @@ -851,9 +847,7 @@ public: void invalidate_legend() { m_legend_resizer.reset(); } -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION const ConflictResultOpt& get_conflict_result() const { return m_conflict_result; } -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION private: void load_toolpaths(const GCodeProcessorResult& gcode_result); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 048449a4c..934cd975d 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2692,9 +2692,7 @@ void GLCanvas3D::load_gcode_preview(const GCodeProcessorResult& gcode_result, co if (wxGetApp().is_editor()) { m_gcode_viewer.update_shells_color_by_extruder(m_config); _set_warning_notification_if_needed(EWarning::ToolpathOutside); -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION _set_warning_notification_if_needed(EWarning::GCodeConflict); -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION } m_gcode_viewer.refresh(gcode_result, str_tool_colors); @@ -7443,17 +7441,12 @@ void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning) } else { if (wxGetApp().is_editor()) { -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION - if (current_printer_technology() != ptSLA) { - if (warning == EWarning::ToolpathOutside) - show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed(); - else if (warning == EWarning::GCodeConflict) - show = m_gcode_viewer.has_data() && m_gcode_viewer.is_contained_in_bed() && m_gcode_viewer.get_conflict_result().has_value(); - } -#else - if (current_printer_technology() != ptSLA) - show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed(); -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION + if (current_printer_technology() != ptSLA) { + if (warning == EWarning::ToolpathOutside) + show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed(); + else if (warning == EWarning::GCodeConflict) + show = m_gcode_viewer.has_data() && m_gcode_viewer.is_contained_in_bed() && m_gcode_viewer.get_conflict_result().has_value(); + } } } @@ -7479,7 +7472,6 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) "Resolve the current problem to continue slicing."); error = ErrorType::PLATER_ERROR; break; -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION case EWarning::GCodeConflict: { const ConflictResultOpt& conflict_result = m_gcode_viewer.get_conflict_result(); if (!conflict_result.has_value()) { break; } @@ -7492,11 +7484,9 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) error = ErrorType::SLICING_ERROR; break; } -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION } auto& notification_manager = *wxGetApp().plater()->get_notification_manager(); -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION const ConflictResultOpt& conflict_result = m_gcode_viewer.get_conflict_result(); if (warning == EWarning::GCodeConflict) { if (conflict_result.has_value()) { @@ -7526,7 +7516,6 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) return; } -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION switch (error) { diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 613d97698..eb674dffe 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -362,12 +362,8 @@ class GLCanvas3D ToolpathOutside, SlaSupportsOutside, SomethingNotShown, -#if ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION ObjectClashed, GCodeConflict -#else - ObjectClashed -#endif // ENABLE_BAMBUSTUDIO_TOOLPATHS_CONFLICTS_DETECTION }; class RenderStats From efe00f310b13d3e84ccf89d1cacf62986c2d95fb Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 27 Apr 2023 08:55:59 +0200 Subject: [PATCH 04/17] Fixed warnings --- src/libslic3r/GCode/ConflictChecker.cpp | 1 - src/slic3r/GUI/GLCanvas3D.cpp | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/GCode/ConflictChecker.cpp b/src/libslic3r/GCode/ConflictChecker.cpp index cf4fe751a..82d4504ae 100644 --- a/src/libslic3r/GCode/ConflictChecker.cpp +++ b/src/libslic3r/GCode/ConflictChecker.cpp @@ -32,7 +32,6 @@ inline Grids line_rasterization(const Line &line, int64_t xdist = RasteXDistance Point rayStart = line.a; Point rayEnd = line.b; IndexPair currentVoxel = point_map_grid_index(rayStart, xdist, ydist); - IndexPair firstVoxel = currentVoxel; IndexPair lastVoxel = point_map_grid_index(rayEnd, xdist, ydist); Point ray = rayEnd - rayStart; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 934cd975d..4a3732fe9 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -7493,12 +7493,12 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) const PrintObject* obj2 = reinterpret_cast(conflict_result->_obj2); auto mo = obj2->model_object(); ObjectID id = mo->id(); - auto action_fn = [this, id](wxEvtHandler*) { + auto action_fn = [id](wxEvtHandler*) { auto& objects = wxGetApp().model().objects; auto iter = id.id ? std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; }) : objects.end(); if (iter != objects.end()) { const unsigned int obj_idx = std::distance(objects.begin(), iter); - wxGetApp().CallAfter([this, obj_idx]() { + wxGetApp().CallAfter([obj_idx]() { wxGetApp().plater()->select_view_3D("3D"); wxGetApp().plater()->canvas3D()->get_selection().add_object(obj_idx, true); wxGetApp().obj_list()->update_selections(); From 681227be7118fde3f1d6b062a457df70f912603d Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 27 Apr 2023 10:42:30 +0200 Subject: [PATCH 05/17] Fixed crash in fff_print_tests --- src/libslic3r/GCode/GCodeProcessor.cpp | 2 ++ src/libslic3r/Print.cpp | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 51e4c88c1..d71dd347a 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -450,6 +450,7 @@ void GCodeProcessorResult::reset() { filament_cost = std::vector(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_COST); custom_gcode_per_print_z = std::vector(); spiral_vase_layers = std::vector>>(); + conflict_result = std::nullopt; time = 0; } #else @@ -468,6 +469,7 @@ void GCodeProcessorResult::reset() { filament_cost = std::vector(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_COST); custom_gcode_per_print_z = std::vector(); spiral_vase_layers = std::vector>>(); + conflict_result = std::nullopt; } #endif // ENABLE_GCODE_VIEWER_STATISTICS diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 57ccc9a82..a184c1ccd 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -1001,7 +1001,8 @@ std::string Print::export_gcode(const std::string& path_template, GCodeProcessor std::unique_ptr gcode(new GCode); gcode->do_export(this, path.c_str(), result, thumbnail_cb); - result->conflict_result = m_conflict_result; + if (m_conflict_result.has_value()) + result->conflict_result = *m_conflict_result; return path.c_str(); } From 3706a2c777e8bcc78cf036dda39ea5919cf82bb2 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 27 Apr 2023 10:58:49 +0200 Subject: [PATCH 06/17] Fixed warning --- src/libslic3r/GCode/ConflictChecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/GCode/ConflictChecker.cpp b/src/libslic3r/GCode/ConflictChecker.cpp index 82d4504ae..f8fed0efa 100644 --- a/src/libslic3r/GCode/ConflictChecker.cpp +++ b/src/libslic3r/GCode/ConflictChecker.cpp @@ -189,7 +189,7 @@ ConflictComputeOpt ConflictChecker::find_inter_of_lines(const LineWithIDs &lines using namespace RasterizationImpl; std::map> indexToLine; - for (int i = 0; i < lines.size(); ++i) { + for (int i = 0; i < (int)lines.size(); ++i) { const LineWithID &l1 = lines[i]; auto indexes = line_rasterization(l1._line); for (auto index : indexes) { From 2aa6d77c1b73cdf624d020b3ca3aec96325e1112 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 27 Apr 2023 11:48:27 +0200 Subject: [PATCH 07/17] Attempt to fix failure in fff_print_tests on MAC Asan --- src/libslic3r/GCode/ConflictChecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/GCode/ConflictChecker.cpp b/src/libslic3r/GCode/ConflictChecker.cpp index f8fed0efa..4f367f175 100644 --- a/src/libslic3r/GCode/ConflictChecker.cpp +++ b/src/libslic3r/GCode/ConflictChecker.cpp @@ -100,7 +100,7 @@ void LinesBucketQueue::emplace_back_bucket(std::vector &&paths, _pq.push(&_buckets.back()); auto newSize = _buckets.capacity(); if (oldSize != newSize) { // pointers change - decltype(_pq) newQueue; + std::priority_queue, LinesBucketPtrComp> newQueue; for (LinesBucket &bucket : _buckets) { newQueue.push(&bucket); } std::swap(_pq, newQueue); } From 0f15eb660046360902cfad4e2e4ec9c074dc26f1 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 27 Apr 2023 13:04:44 +0200 Subject: [PATCH 08/17] Revert of 00e440e3006d43957f3e865d225b340c3be2e1fd --- src/libslic3r/GCode/ConflictChecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/GCode/ConflictChecker.cpp b/src/libslic3r/GCode/ConflictChecker.cpp index 4f367f175..f8fed0efa 100644 --- a/src/libslic3r/GCode/ConflictChecker.cpp +++ b/src/libslic3r/GCode/ConflictChecker.cpp @@ -100,7 +100,7 @@ void LinesBucketQueue::emplace_back_bucket(std::vector &&paths, _pq.push(&_buckets.back()); auto newSize = _buckets.capacity(); if (oldSize != newSize) { // pointers change - std::priority_queue, LinesBucketPtrComp> newQueue; + decltype(_pq) newQueue; for (LinesBucket &bucket : _buckets) { newQueue.push(&bucket); } std::swap(_pq, newQueue); } From 720ddf73daeefe40eccfbda51a4c117d2807d09c Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 27 Apr 2023 14:52:26 +0200 Subject: [PATCH 09/17] Fixed mysterious ASAN crash in conflict detection code --- src/libslic3r/GCode/ConflictChecker.cpp | 16 ++++++++-------- src/libslic3r/GCode/ConflictChecker.hpp | 1 + 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/libslic3r/GCode/ConflictChecker.cpp b/src/libslic3r/GCode/ConflictChecker.cpp index f8fed0efa..f3d3f49fe 100644 --- a/src/libslic3r/GCode/ConflictChecker.cpp +++ b/src/libslic3r/GCode/ConflictChecker.cpp @@ -91,19 +91,18 @@ inline Grids line_rasterization(const Line &line, int64_t xdist = RasteXDistance void LinesBucketQueue::emplace_back_bucket(std::vector &&paths, const void *objPtr, Point offset) { - auto oldSize = _buckets.capacity(); if (_objsPtrToId.find(objPtr) == _objsPtrToId.end()) { _objsPtrToId.insert({objPtr, _objsPtrToId.size()}); _idToObjsPtr.insert({_objsPtrToId.size() - 1, objPtr}); } _buckets.emplace_back(std::move(paths), _objsPtrToId[objPtr], offset); - _pq.push(&_buckets.back()); - auto newSize = _buckets.capacity(); - if (oldSize != newSize) { // pointers change - decltype(_pq) newQueue; - for (LinesBucket &bucket : _buckets) { newQueue.push(&bucket); } - std::swap(_pq, newQueue); - } +} + +void LinesBucketQueue::build_queue() +{ + assert(_pq.empty); + for (LinesBucket &bucket : _buckets) + _pq.push(&bucket); } double LinesBucketQueue::removeLowests() @@ -218,6 +217,7 @@ ConflictResultOpt ConflictChecker::find_inter_of_lines_in_diff_objs(PrintObjectP conflictQueue.emplace_back_bucket(std::move(layers.first), obj, obj->instances().front().shift); conflictQueue.emplace_back_bucket(std::move(layers.second), obj, obj->instances().front().shift); } + conflictQueue.build_queue(); std::vector layersLines; std::vector heights; diff --git a/src/libslic3r/GCode/ConflictChecker.hpp b/src/libslic3r/GCode/ConflictChecker.hpp index cc21bc816..069e553b4 100644 --- a/src/libslic3r/GCode/ConflictChecker.hpp +++ b/src/libslic3r/GCode/ConflictChecker.hpp @@ -78,6 +78,7 @@ private: public: void emplace_back_bucket(std::vector &&paths, const void *objPtr, Point offset); + void build_queue(); bool valid() const { return _pq.empty() == false; } const void *idToObjsPtr(int id) { From b0bef4eeb4e15cc95421a23d8c387cfbb9f46854 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 3 May 2023 15:28:46 +0200 Subject: [PATCH 10/17] Conflict checker: first steps to extend it so it takes instances into account --- src/libslic3r/GCode/ConflictChecker.cpp | 17 +++++++++++------ src/libslic3r/GCode/ConflictChecker.hpp | 17 ++++++++++------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/GCode/ConflictChecker.cpp b/src/libslic3r/GCode/ConflictChecker.cpp index f3d3f49fe..3ac65663b 100644 --- a/src/libslic3r/GCode/ConflictChecker.cpp +++ b/src/libslic3r/GCode/ConflictChecker.cpp @@ -89,18 +89,18 @@ inline Grids line_rasterization(const Line &line, int64_t xdist = RasteXDistance } } // namespace RasterizationImpl -void LinesBucketQueue::emplace_back_bucket(std::vector &&paths, const void *objPtr, Point offset) +void LinesBucketQueue::emplace_back_bucket(std::vector &&paths, const void *objPtr, Points offsets) { if (_objsPtrToId.find(objPtr) == _objsPtrToId.end()) { _objsPtrToId.insert({objPtr, _objsPtrToId.size()}); _idToObjsPtr.insert({_objsPtrToId.size() - 1, objPtr}); } - _buckets.emplace_back(std::move(paths), _objsPtrToId[objPtr], offset); + _buckets.emplace_back(std::move(paths), _objsPtrToId[objPtr], offsets); } void LinesBucketQueue::build_queue() { - assert(_pq.empty); + assert(_pq.empty()); for (LinesBucket &bucket : _buckets) _pq.push(&bucket); } @@ -210,12 +210,17 @@ ConflictResultOpt ConflictChecker::find_inter_of_lines_in_diff_objs(PrintObjectP LinesBucketQueue conflictQueue; if (wtdptr.has_value()) { // wipe tower at 0 by default auto wtpaths = (*wtdptr)->getFakeExtrusionPathsFromWipeTower(); - conflictQueue.emplace_back_bucket(std::move(wtpaths), *wtdptr, { (*wtdptr)->plate_origin.x(), (*wtdptr)->plate_origin.y() }); + conflictQueue.emplace_back_bucket(std::move(wtpaths), *wtdptr, Points{Point((*wtdptr)->plate_origin)}); } for (PrintObject *obj : objs) { auto layers = getAllLayersExtrusionPathsFromObject(obj); - conflictQueue.emplace_back_bucket(std::move(layers.first), obj, obj->instances().front().shift); - conflictQueue.emplace_back_bucket(std::move(layers.second), obj, obj->instances().front().shift); + + Points instances_shifts; + for (const PrintInstance& inst : obj->instances()) + instances_shifts.emplace_back(inst.shift); + + conflictQueue.emplace_back_bucket(std::move(layers.first), obj, instances_shifts); + conflictQueue.emplace_back_bucket(std::move(layers.second), obj, instances_shifts); } conflictQueue.build_queue(); diff --git a/src/libslic3r/GCode/ConflictChecker.hpp b/src/libslic3r/GCode/ConflictChecker.hpp index 069e553b4..ce57fdcfb 100644 --- a/src/libslic3r/GCode/ConflictChecker.hpp +++ b/src/libslic3r/GCode/ConflictChecker.hpp @@ -31,10 +31,10 @@ private: std::vector _piles; int _id; - Point _offset; + Points _offsets; public: - LinesBucket(std::vector &&paths, int id, Point offset) : _piles(paths), _id(id), _offset(offset) {} + LinesBucket(std::vector &&paths, int id, Points offsets) : _piles(paths), _id(id), _offsets(offsets) {} LinesBucket(LinesBucket &&) = default; bool valid() const { return _curPileIdx < _piles.size(); } @@ -50,10 +50,13 @@ public: { LineWithIDs lines; for (const ExtrusionPath &path : _piles[_curPileIdx]) { - Polyline check_polyline = path.polyline; - check_polyline.translate(_offset); - Lines tmpLines = check_polyline.lines(); - for (const Line &line : tmpLines) { lines.emplace_back(line, _id, path.role()); } + Polyline check_polyline; + for (const Point& offset : _offsets) { + check_polyline = path.polyline; + check_polyline.translate(offset); + Lines tmpLines = check_polyline.lines(); + for (const Line &line : tmpLines) { lines.emplace_back(line, _id, path.role()); } + } } return lines; } @@ -77,7 +80,7 @@ private: std::map _objsPtrToId; public: - void emplace_back_bucket(std::vector &&paths, const void *objPtr, Point offset); + void emplace_back_bucket(std::vector &&paths, const void *objPtr, Points offset); void build_queue(); bool valid() const { return _pq.empty() == false; } const void *idToObjsPtr(int id) From a2ed20d5950f3858793a86c0523c72ea90eadf7a Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 4 May 2023 12:20:33 +0200 Subject: [PATCH 11/17] Conflict checker: added detection for instances belonging to the same object --- src/libslic3r/GCode/ConflictChecker.cpp | 8 +++++--- src/libslic3r/GCode/ConflictChecker.hpp | 12 +++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/libslic3r/GCode/ConflictChecker.cpp b/src/libslic3r/GCode/ConflictChecker.cpp index 3ac65663b..2030399f5 100644 --- a/src/libslic3r/GCode/ConflictChecker.cpp +++ b/src/libslic3r/GCode/ConflictChecker.cpp @@ -206,7 +206,8 @@ ConflictComputeOpt ConflictChecker::find_inter_of_lines(const LineWithIDs &lines ConflictResultOpt ConflictChecker::find_inter_of_lines_in_diff_objs(PrintObjectPtrs objs, std::optional wtdptr) // find the first intersection point of lines in different objects { - if (objs.size() <= 1) { return {}; } + if (objs.empty() || (objs.size() == 1 && objs.front()->instances().size() == 1)) { return {}; } + LinesBucketQueue conflictQueue; if (wtdptr.has_value()) { // wipe tower at 0 by default auto wtpaths = (*wtdptr)->getFakeExtrusionPathsFromWipeTower(); @@ -268,14 +269,15 @@ ConflictResultOpt ConflictChecker::find_inter_of_lines_in_diff_objs(PrintObjectP ConflictComputeOpt ConflictChecker::line_intersect(const LineWithID &l1, const LineWithID &l2) { - if (l1._id == l2._id) { return {}; } // return true if lines are from same object + if (l1._obj_id == l2._obj_id && l1._inst_id == l2._inst_id) { return {}; } // lines are from same instance + Point inter; bool intersect = l1._line.intersection(l2._line, &inter); if (intersect) { auto dist1 = std::min(unscale(Point(l1._line.a - inter)).norm(), unscale(Point(l1._line.b - inter)).norm()); auto dist2 = std::min(unscale(Point(l2._line.a - inter)).norm(), unscale(Point(l2._line.b - inter)).norm()); auto dist = std::min(dist1, dist2); - if (dist > 0.01) { return std::make_optional(l1._id, l2._id); } // the two lines intersects if dist>0.01mm + if (dist > 0.01) { return std::make_optional(l1._obj_id, l2._obj_id); } // the two lines intersects if dist>0.01mm } return {}; } diff --git a/src/libslic3r/GCode/ConflictChecker.hpp b/src/libslic3r/GCode/ConflictChecker.hpp index ce57fdcfb..344018f3d 100644 --- a/src/libslic3r/GCode/ConflictChecker.hpp +++ b/src/libslic3r/GCode/ConflictChecker.hpp @@ -15,10 +15,12 @@ namespace Slic3r { struct LineWithID { Line _line; - int _id; + int _obj_id; + int _inst_id; ExtrusionRole _role; - LineWithID(const Line& line, int id, const ExtrusionRole& role) : _line(line), _id(id), _role(role) {} + LineWithID(const Line& line, int obj_id, int inst_id, const ExtrusionRole& role) : + _line(line), _obj_id(obj_id), _inst_id(inst_id), _role(role) {} }; using LineWithIDs = std::vector; @@ -51,11 +53,11 @@ public: LineWithIDs lines; for (const ExtrusionPath &path : _piles[_curPileIdx]) { Polyline check_polyline; - for (const Point& offset : _offsets) { + for (int i = 0; i < (int)_offsets.size(); ++i) { check_polyline = path.polyline; - check_polyline.translate(offset); + check_polyline.translate(_offsets[i]); Lines tmpLines = check_polyline.lines(); - for (const Line &line : tmpLines) { lines.emplace_back(line, _id, path.role()); } + for (const Line& line : tmpLines) { lines.emplace_back(line, _id, i, path.role()); } } } return lines; From 9a1e85c1f4ffcbd0f0e9a54c6ee63c35646e7564 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 4 May 2023 13:29:04 +0200 Subject: [PATCH 12/17] Conflict checker: sort detected conflicts to show the one with lowest z in the notification --- src/libslic3r/GCode/ConflictChecker.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libslic3r/GCode/ConflictChecker.cpp b/src/libslic3r/GCode/ConflictChecker.cpp index 2030399f5..f7841601e 100644 --- a/src/libslic3r/GCode/ConflictChecker.cpp +++ b/src/libslic3r/GCode/ConflictChecker.cpp @@ -249,6 +249,10 @@ ConflictResultOpt ConflictChecker::find_inter_of_lines_in_diff_objs(PrintObjectP }); if (find) { + std::sort(conflict.begin(), conflict.end(), [](const std::pair& i1, const std::pair& i2) { + return i1.second < i2.second; + }); + const void *ptr1 = conflictQueue.idToObjsPtr(conflict[0].first._obj1); const void *ptr2 = conflictQueue.idToObjsPtr(conflict[0].first._obj2); double conflictHeight = conflict[0].second; From cc55bcbf5ef570534c9adc3586ba6fa0c5d9e451 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 5 May 2023 13:22:14 +0200 Subject: [PATCH 13/17] Conflict checker: automatically set the gcode preview at the layer shown in the notification when hitting the action text in it --- src/slic3r/GUI/GLCanvas3D.cpp | 6 ++++-- src/slic3r/GUI/GUI_Preview.cpp | 6 ++++++ src/slic3r/GUI/GUI_Preview.hpp | 2 ++ src/slic3r/GUI/Plater.cpp | 12 ++++++++++++ src/slic3r/GUI/Plater.hpp | 2 ++ 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 4a3732fe9..227df0b41 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -7493,12 +7493,14 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) const PrintObject* obj2 = reinterpret_cast(conflict_result->_obj2); auto mo = obj2->model_object(); ObjectID id = mo->id(); - auto action_fn = [id](wxEvtHandler*) { + int layer_id = conflict_result->layer; + auto action_fn = [id, layer_id](wxEvtHandler*) { auto& objects = wxGetApp().model().objects; auto iter = id.id ? std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; }) : objects.end(); if (iter != objects.end()) { const unsigned int obj_idx = std::distance(objects.begin(), iter); - wxGetApp().CallAfter([obj_idx]() { + wxGetApp().CallAfter([obj_idx, layer_id]() { + wxGetApp().plater()->set_preview_layers_slider_values_range(0, layer_id - 1); wxGetApp().plater()->select_view_3D("3D"); wxGetApp().plater()->canvas3D()->get_selection().add_object(obj_idx, true); wxGetApp().obj_list()->update_selections(); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 656bc0b53..74a8719d8 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -181,6 +181,12 @@ Preview::Preview( load_print(); } +void Preview::set_layers_slider_values_range(int bottom, int top) +{ + m_layers_slider->SetHigherValue(std::min(top, m_layers_slider->GetMaxValue())); + m_layers_slider->SetLowerValue(std::max(bottom, m_layers_slider->GetMinValue())); +} + bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model) { if (!Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 /* disable wxTAB_TRAVERSAL */)) diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index 25d9fe084..c7b7fdc61 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -151,6 +151,8 @@ public: void set_keep_current_preview_type(bool value) { m_keep_current_preview_type = value; } + void set_layers_slider_values_range(int bottom, int top); + private: bool init(wxWindow* parent, Bed3D& bed, Model* model); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index d367f1f19..b598abfaf 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1794,6 +1794,8 @@ struct Plater::priv bool init_view_toolbar(); bool init_collapse_toolbar(); + void set_preview_layers_slider_values_range(int bottom, int top); + void update_preview_moves_slider(); void enable_preview_moves_slider(bool enable); @@ -4632,6 +4634,11 @@ bool Plater::priv::init_collapse_toolbar() return true; } +void Plater::priv::set_preview_layers_slider_values_range(int bottom, int top) +{ + preview->set_layers_slider_values_range(bottom, top); +} + void Plater::priv::update_preview_moves_slider() { preview->update_moves_slider(); @@ -7506,6 +7513,11 @@ GLToolbar& Plater::get_collapse_toolbar() return p->collapse_toolbar; } +void Plater::set_preview_layers_slider_values_range(int bottom, int top) +{ + p->set_preview_layers_slider_values_range(bottom, top); +} + void Plater::update_preview_moves_slider() { p->update_preview_moves_slider(); diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 880448c86..8eeabae42 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -399,6 +399,8 @@ public: const GLToolbar& get_collapse_toolbar() const; GLToolbar& get_collapse_toolbar(); + void set_preview_layers_slider_values_range(int bottom, int top); + void update_preview_moves_slider(); void enable_preview_moves_slider(bool enable); From 985bb54748a2798cd46d6fae07e24570b125c629 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 26 May 2023 12:38:24 +0200 Subject: [PATCH 14/17] Conflict checker: take the wipe tower into account --- src/libslic3r/Print.cpp | 4 ++++ src/libslic3r/Print.hpp | 29 ++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index a184c1ccd..c2a20e034 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -1526,6 +1526,10 @@ void Print::_make_wipe_tower() m_wipe_tower_data.used_filament = wipe_tower.get_used_filament(); m_wipe_tower_data.number_of_toolchanges = wipe_tower.get_number_of_toolchanges(); + const Vec3d origin = Vec3d::Zero(); + m_fake_wipe_tower.set_fake_extrusion_data(wipe_tower.position(), wipe_tower.width(), wipe_tower.get_wipe_tower_height(), config().first_layer_height, m_wipe_tower_data.depth, + m_wipe_tower_data.brim_width, config().wipe_tower_rotation_angle, {scale_(origin.x()), scale_(origin.y())}); + } // Generate a recommended G-code output file name based on the format template, default extension, and template parameters diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 5449d4897..47fc3ebb0 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -427,9 +427,10 @@ struct FakeWipeTower float layer_height; float depth; float brim_width; + float rotation_angle; Vec2d plate_origin; - void set_fake_extrusion_data(const Vec2f& p, float w, float h, float lh, float d, float bd, const Vec2d& o) + void set_fake_extrusion_data(const Vec2f& p, float w, float h, float lh, float d, float bd, float ra, const Vec2d& o) { pos = p; width = w; @@ -437,6 +438,7 @@ struct FakeWipeTower layer_height = lh; depth = d; brim_width = bd; + rotation_angle = ra; plate_origin = o; } @@ -449,15 +451,36 @@ struct FakeWipeTower int d = scale_(depth); int w = scale_(width); int bd = scale_(brim_width); - Point minCorner = { scale_(pos.x()), scale_(pos.y()) }; - Point maxCorner = { minCorner.x() + w, minCorner.y() + d }; + Point minCorner = { -bd, -bd }; + Point maxCorner = { minCorner.x() + w + bd, minCorner.y() + d + bd }; std::vector paths; for (float hh = 0.f; hh < h; hh += lh) { ExtrusionPath path(ExtrusionRole::WipeTower, 0.0, 0.0, lh); path.polyline = { minCorner, {maxCorner.x(), minCorner.y()}, maxCorner, {minCorner.x(), maxCorner.y()}, minCorner }; paths.push_back({ path }); + + // We added the border, now add several parallel lines so we can detect an object that is fully inside the tower. + // For now, simply use fixed spacing of 3mm. + for (coord_t y=minCorner.y()+scale_(3.); y Date: Fri, 26 May 2023 13:15:56 +0200 Subject: [PATCH 15/17] Conflict checker: follow-up to previous commit: the wipe tower may be rotated without being invalidated, in which case the rotation would not be updated in the conflict checker --- src/libslic3r/Print.cpp | 2 +- src/libslic3r/Print.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index c2a20e034..7ef199639 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -966,7 +966,7 @@ void Print::process() std::optional wipe_tower_opt = {}; if (this->has_wipe_tower()) { - m_fake_wipe_tower.set_pos({ m_config.wipe_tower_x, m_config.wipe_tower_y }); + m_fake_wipe_tower.set_pos_and_rotation({ m_config.wipe_tower_x, m_config.wipe_tower_y }, m_config.wipe_tower_rotation_angle); wipe_tower_opt = std::make_optional(&m_fake_wipe_tower); } auto conflictRes = ConflictChecker::find_inter_of_lines_in_diff_objs(m_objects, wipe_tower_opt); diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 47fc3ebb0..25fcc449b 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -442,7 +442,7 @@ struct FakeWipeTower plate_origin = o; } - void set_pos(const Vec2f& p) { pos = p; } + void set_pos_and_rotation(const Vec2f& p, float rotation) { pos = p; rotation_angle = rotation; } std::vector getFakeExtrusionPathsFromWipeTower() const { From 46678c27b50710be3a3936964a278f6d41402ba7 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 29 May 2023 14:26:31 +0200 Subject: [PATCH 16/17] Conflict checker: detection of the wipe tower when it narrows towards the top --- src/libslic3r/GCode/ConflictChecker.cpp | 4 +- src/libslic3r/GCode/WipeTower.cpp | 15 +++++++ src/libslic3r/GCode/WipeTower.hpp | 1 + src/libslic3r/Print.cpp | 57 ++++++++++++++++++++++++- src/libslic3r/Print.hpp | 45 +++---------------- src/slic3r/GUI/3DScene.cpp | 13 ++++-- src/slic3r/GUI/3DScene.hpp | 4 +- src/slic3r/GUI/GCodeViewer.cpp | 3 +- src/slic3r/GUI/GLCanvas3D.cpp | 5 ++- 9 files changed, 94 insertions(+), 53 deletions(-) diff --git a/src/libslic3r/GCode/ConflictChecker.cpp b/src/libslic3r/GCode/ConflictChecker.cpp index f7841601e..09ef1c850 100644 --- a/src/libslic3r/GCode/ConflictChecker.cpp +++ b/src/libslic3r/GCode/ConflictChecker.cpp @@ -210,11 +210,11 @@ ConflictResultOpt ConflictChecker::find_inter_of_lines_in_diff_objs(PrintObjectP LinesBucketQueue conflictQueue; if (wtdptr.has_value()) { // wipe tower at 0 by default - auto wtpaths = (*wtdptr)->getFakeExtrusionPathsFromWipeTower(); + std::vector wtpaths = (*wtdptr)->getFakeExtrusionPathsFromWipeTower(); conflictQueue.emplace_back_bucket(std::move(wtpaths), *wtdptr, Points{Point((*wtdptr)->plate_origin)}); } for (PrintObject *obj : objs) { - auto layers = getAllLayersExtrusionPathsFromObject(obj); + std::pair, std::vector> layers = getAllLayersExtrusionPathsFromObject(obj); Points instances_shifts; for (const PrintInstance& inst : obj->instances()) diff --git a/src/libslic3r/GCode/WipeTower.cpp b/src/libslic3r/GCode/WipeTower.cpp index 5ce5353db..6e868d148 100644 --- a/src/libslic3r/GCode/WipeTower.cpp +++ b/src/libslic3r/GCode/WipeTower.cpp @@ -1563,4 +1563,19 @@ void WipeTower::generate(std::vector> & } } + + +std::vector> WipeTower::get_z_and_depth_pairs() const +{ + std::vector> out = {{0.f, m_wipe_tower_depth}}; + for (const WipeTowerInfo& wti : m_plan) { + assert(wti.depth < wti.depth + WT_EPSILON); + if (wti.depth < out.back().second - WT_EPSILON) + out.emplace_back(wti.z, wti.depth); + } + if (out.back().first < m_wipe_tower_height - WT_EPSILON) + out.emplace_back(m_wipe_tower_height, 0.f); + return out; +} + } // namespace Slic3r diff --git a/src/libslic3r/GCode/WipeTower.hpp b/src/libslic3r/GCode/WipeTower.hpp index 8209d13f4..969da848d 100644 --- a/src/libslic3r/GCode/WipeTower.hpp +++ b/src/libslic3r/GCode/WipeTower.hpp @@ -143,6 +143,7 @@ public: void generate(std::vector> &result); float get_depth() const { return m_wipe_tower_depth; } + std::vector> get_z_and_depth_pairs() const; float get_brim_width() const { return m_wipe_tower_brim_width_real; } float get_wipe_tower_height() const { return m_wipe_tower_height; } diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 7ef199639..d35140263 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -27,7 +27,6 @@ #include #include - namespace Slic3r { template class PrintState; @@ -1502,6 +1501,7 @@ void Print::_make_wipe_tower() m_wipe_tower_data.tool_changes.reserve(m_wipe_tower_data.tool_ordering.layer_tools().size()); wipe_tower.generate(m_wipe_tower_data.tool_changes); m_wipe_tower_data.depth = wipe_tower.get_depth(); + m_wipe_tower_data.z_and_depth_pairs = wipe_tower.get_z_and_depth_pairs(); m_wipe_tower_data.brim_width = wipe_tower.get_brim_width(); m_wipe_tower_data.height = wipe_tower.get_wipe_tower_height(); @@ -1528,7 +1528,7 @@ void Print::_make_wipe_tower() m_wipe_tower_data.number_of_toolchanges = wipe_tower.get_number_of_toolchanges(); const Vec3d origin = Vec3d::Zero(); m_fake_wipe_tower.set_fake_extrusion_data(wipe_tower.position(), wipe_tower.width(), wipe_tower.get_wipe_tower_height(), config().first_layer_height, m_wipe_tower_data.depth, - m_wipe_tower_data.brim_width, config().wipe_tower_rotation_angle, {scale_(origin.x()), scale_(origin.y())}); + m_wipe_tower_data.z_and_depth_pairs, m_wipe_tower_data.brim_width, config().wipe_tower_rotation_angle, {scale_(origin.x()), scale_(origin.y())}); } @@ -1597,4 +1597,57 @@ std::string PrintStatistics::finalize_output_path(const std::string &path_in) co return final_path; } + std::vector FakeWipeTower::getFakeExtrusionPathsFromWipeTower() const + { + float h = height; + float lh = layer_height; + int d = scale_(depth); + int w = scale_(width); + int bd = scale_(brim_width); + Point minCorner = { -bd, -bd }; + Point maxCorner = { minCorner.x() + w + bd, minCorner.y() + d + bd }; + + std::vector paths; + for (float hh = 0.f; hh < h; hh += lh) { + + if (hh != 0.f) { + // The wipe tower may be getting smaller. Find the depth for this layer. + size_t i = 0; + for (i=0; i= z_and_depth_pairs[i].first && hh < z_and_depth_pairs[i+1].first) + break; + d = scale_(z_and_depth_pairs[i].second); + minCorner = {0.f, -d/2 + scale_(z_and_depth_pairs.front().second/2.f)}; + maxCorner = { minCorner.x() + w, minCorner.y() + d }; + } + + + ExtrusionPath path(ExtrusionRole::WipeTower, 0.0, 0.0, lh); + path.polyline = { minCorner, {maxCorner.x(), minCorner.y()}, maxCorner, {minCorner.x(), maxCorner.y()}, minCorner }; + paths.push_back({ path }); + + // We added the border, now add several parallel lines so we can detect an object that is fully inside the tower. + // For now, simply use fixed spacing of 3mm. + for (coord_t y=minCorner.y()+scale_(3.); y> z_and_depth_pairs; float brim_width; float rotation_angle; Vec2d plate_origin; - void set_fake_extrusion_data(const Vec2f& p, float w, float h, float lh, float d, float bd, float ra, const Vec2d& o) + void set_fake_extrusion_data(const Vec2f& p, float w, float h, float lh, float d, const std::vector>& zad, float bd, float ra, const Vec2d& o) { pos = p; width = w; height = h; layer_height = lh; depth = d; + z_and_depth_pairs = zad; brim_width = bd; rotation_angle = ra; plate_origin = o; @@ -444,45 +446,7 @@ struct FakeWipeTower void set_pos_and_rotation(const Vec2f& p, float rotation) { pos = p; rotation_angle = rotation; } - std::vector getFakeExtrusionPathsFromWipeTower() const - { - float h = height; - float lh = layer_height; - int d = scale_(depth); - int w = scale_(width); - int bd = scale_(brim_width); - Point minCorner = { -bd, -bd }; - Point maxCorner = { minCorner.x() + w + bd, minCorner.y() + d + bd }; - - std::vector paths; - for (float hh = 0.f; hh < h; hh += lh) { - ExtrusionPath path(ExtrusionRole::WipeTower, 0.0, 0.0, lh); - path.polyline = { minCorner, {maxCorner.x(), minCorner.y()}, maxCorner, {minCorner.x(), maxCorner.y()}, minCorner }; - paths.push_back({ path }); - - // We added the border, now add several parallel lines so we can detect an object that is fully inside the tower. - // For now, simply use fixed spacing of 3mm. - for (coord_t y=minCorner.y()+scale_(3.); y getFakeExtrusionPathsFromWipeTower() const; }; struct WipeTowerData @@ -500,6 +464,7 @@ struct WipeTowerData // Depth of the wipe tower to pass to GLCanvas3D for exact bounding box: float depth; + std::vector> z_and_depth_pairs; float brim_width; float height; diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 7c5008554..679abb709 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -480,11 +480,11 @@ int GLVolumeCollection::load_object_volume( #if ENABLE_OPENGL_ES int GLVolumeCollection::load_wipe_tower_preview( - float pos_x, float pos_y, float width, float depth, float height, float cone_angle, + float pos_x, float pos_y, float width, float depth, const std::vector>& z_and_depth_pairs, float height, float cone_angle, float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh) #else int GLVolumeCollection::load_wipe_tower_preview( - float pos_x, float pos_y, float width, float depth, float height, float cone_angle, + float pos_x, float pos_y, float width, float depth, const std::vector>& z_and_depth_pairs, float height, float cone_angle, float rotation_angle, bool size_unknown, float brim_width) #endif // ENABLE_OPENGL_ES { @@ -534,8 +534,13 @@ int GLVolumeCollection::load_wipe_tower_preview( mesh.scale(Vec3f(width / (n * min_width), 1.f, height)); // Scaling to proper width } - else - mesh = make_cube(width, depth, height); + else { + for (size_t i=1; i>& z_and_depth_pairs, float height, float cone_angle, float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh = nullptr); #else int load_wipe_tower_preview( - float pos_x, float pos_y, float width, float depth, float height, float cone_angle, float rotation_angle, bool size_unknown, float brim_width); + float pos_x, float pos_y, float width, float depth, const std::vector>& z_and_depth_pairs, float height, float cone_angle, float rotation_angle, bool size_unknown, float brim_width); #endif // ENABLE_OPENGL_ES // Load SLA auxiliary GLVolumes (for support trees or pad). diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 38575c610..5b4681b9c 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2260,9 +2260,10 @@ void GCodeViewer::load_shells(const Print& print) if (extruders_count > 1 && config.wipe_tower && !config.complete_objects) { const WipeTowerData& wipe_tower_data = print.wipe_tower_data(extruders_count); const float depth = wipe_tower_data.depth; + const std::vector> z_and_depth_pairs = print.wipe_tower_data(extruders_count).z_and_depth_pairs; const float brim_width = wipe_tower_data.brim_width; if (depth != 0.) - m_shells.volumes.load_wipe_tower_preview(config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_cone_angle, config.wipe_tower_rotation_angle, + m_shells.volumes.load_wipe_tower_preview(config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, z_and_depth_pairs, max_z, config.wipe_tower_cone_angle, config.wipe_tower_rotation_angle, !print.is_step_done(psWipeTower), brim_width); } } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 227df0b41..1ca749e4e 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2554,6 +2554,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re const Print *print = m_process->fff_print(); const float depth = print->wipe_tower_data(extruders_count).depth; + const std::vector> z_and_depth_pairs = print->wipe_tower_data(extruders_count).z_and_depth_pairs; const float height_real = print->wipe_tower_data(extruders_count).height; // -1.f = unknown // Height of a print (Show at least a slab). @@ -2562,11 +2563,11 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re if (depth != 0.) { #if ENABLE_OPENGL_ES int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview( - x, y, w, depth, (float)height, ca, a, !print->is_step_done(psWipeTower), + x, y, w, depth, z_and_depth_pairs, (float)height, ca, a, !print->is_step_done(psWipeTower), bw, &m_wipe_tower_mesh); #else int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview( - x, y, w, depth, (float)height, ca, a, !print->is_step_done(psWipeTower), + x, y, w, depth, z_and_depth_pairs, (float)height, ca, a, !print->is_step_done(psWipeTower), bw); #endif // ENABLE_OPENGL_ES if (volume_idx_wipe_tower_old != -1) From 5f7c5f452be899a2310eebd2b8ced98f3271f711 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 30 May 2023 16:37:38 +0200 Subject: [PATCH 17/17] Conflict checker: account for the stabilization cone of the wipe tower and its brim --- src/libslic3r/Print.cpp | 27 +++++++++++++++++++++++++-- src/libslic3r/Print.hpp | 4 +++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index d35140263..c62e27400 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -1528,7 +1528,7 @@ void Print::_make_wipe_tower() m_wipe_tower_data.number_of_toolchanges = wipe_tower.get_number_of_toolchanges(); const Vec3d origin = Vec3d::Zero(); m_fake_wipe_tower.set_fake_extrusion_data(wipe_tower.position(), wipe_tower.width(), wipe_tower.get_wipe_tower_height(), config().first_layer_height, m_wipe_tower_data.depth, - m_wipe_tower_data.z_and_depth_pairs, m_wipe_tower_data.brim_width, config().wipe_tower_rotation_angle, {scale_(origin.x()), scale_(origin.y())}); + m_wipe_tower_data.z_and_depth_pairs, m_wipe_tower_data.brim_width, config().wipe_tower_rotation_angle, config().wipe_tower_cone_angle, {scale_(origin.x()), scale_(origin.y())}); } @@ -1607,6 +1607,8 @@ std::string PrintStatistics::finalize_output_path(const std::string &path_in) co Point minCorner = { -bd, -bd }; Point maxCorner = { minCorner.x() + w + bd, minCorner.y() + d + bd }; + const auto [cone_base_R, cone_scale_x] = WipeTower::get_wipe_tower_cone_base(width, height, depth, cone_angle); + std::vector paths; for (float hh = 0.f; hh < h; hh += lh) { @@ -1630,9 +1632,30 @@ std::string PrintStatistics::finalize_output_path(const std::string &path_in) co // For now, simply use fixed spacing of 3mm. for (coord_t y=minCorner.y()+scale_(3.); y 0.) { + path.polyline.clear(); + double r = cone_base_R * (1 - hh/height); + for (double alpha=0; alpha<2.01*M_PI; alpha+=2*M_PI/20.) + path.polyline.points.emplace_back(Point::new_scale(width/2. + r * std::cos(alpha)/cone_scale_x, depth/2. + r * std::sin(alpha))); + paths.back().emplace_back(path); + if (hh == 0.f) { // Cone brim. + for (float bw=brim_width; bw>0.f; bw-=3.f) { + path.polyline.clear(); + for (double alpha=0; alpha<2.01*M_PI; alpha+=2*M_PI/20.) // see load_wipe_tower_preview, where the same is a bit clearer + path.polyline.points.emplace_back(Point::new_scale( + width/2. + cone_base_R * std::cos(alpha)/cone_scale_x * (1. + cone_scale_x*bw/cone_base_R), + depth/2. + cone_base_R * std::sin(alpha) * (1. + bw/cone_base_R)) + ); + paths.back().emplace_back(path); + } + } + } + + // Only the first layer has brim. if (hh == 0.f) { minCorner = minCorner + Point(bd, bd); maxCorner = maxCorner - Point(bd, bd); diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index feeebd20f..059491951 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -429,9 +429,10 @@ struct FakeWipeTower std::vector> z_and_depth_pairs; float brim_width; float rotation_angle; + float cone_angle; Vec2d plate_origin; - void set_fake_extrusion_data(const Vec2f& p, float w, float h, float lh, float d, const std::vector>& zad, float bd, float ra, const Vec2d& o) + void set_fake_extrusion_data(const Vec2f& p, float w, float h, float lh, float d, const std::vector>& zad, float bd, float ra, float ca, const Vec2d& o) { pos = p; width = w; @@ -441,6 +442,7 @@ struct FakeWipeTower z_and_depth_pairs = zad; brim_width = bd; rotation_angle = ra; + cone_angle = ca; plate_origin = o; }