diff --git a/src/libslic3r/BuildVolume.cpp b/src/libslic3r/BuildVolume.cpp index f8fcef76f..c580e6f87 100644 --- a/src/libslic3r/BuildVolume.cpp +++ b/src/libslic3r/BuildVolume.cpp @@ -269,15 +269,17 @@ BuildVolume::ObjectState object_state_templ(const indexed_triangle_set &its, con return inside ? (outside ? BuildVolume::ObjectState::Colliding : BuildVolume::ObjectState::Inside) : BuildVolume::ObjectState::Outside; } -BuildVolume::ObjectState BuildVolume::object_state(const indexed_triangle_set &its, const Transform3f &trafo, bool may_be_below_bed) const +BuildVolume::ObjectState BuildVolume::object_state(const indexed_triangle_set& its, const Transform3f& trafo, bool may_be_below_bed, bool ignore_bottom) const { switch (m_type) { case Type::Rectangle: { BoundingBox3Base build_volume = this->bounding_volume().inflated(SceneEpsilon); - BoundingBox3Base build_volumef(build_volume.min.cast(), build_volume.max.cast()); - if (m_max_print_height == 0) + if (m_max_print_height == 0.0) build_volume.max.z() = std::numeric_limits::max(); + if (ignore_bottom) + build_volume.min.z() = -std::numeric_limits::max(); + BoundingBox3Base build_volumef(build_volume.min.cast(), build_volume.max.cast()); // The following test correctly interprets intersection of a non-convex object with a rectangular build volume. //return rectangle_test(its, trafo, to_2d(build_volume.min), to_2d(build_volume.max), build_volume.max.z()); //FIXME This test does NOT correctly interprets intersection of a non-convex object with a rectangular build volume. @@ -286,14 +288,14 @@ BuildVolume::ObjectState BuildVolume::object_state(const indexed_triangle_set &i case Type::Circle: { Geometry::Circlef circle { unscaled(m_circle.center), unscaled(m_circle.radius + SceneEpsilon) }; - return m_max_print_height == 0 ? + return m_max_print_height == 0.0 ? object_state_templ(its, trafo, may_be_below_bed, [circle](const Vec3f &pt) { return circle.contains(to_2d(pt)); }) : object_state_templ(its, trafo, may_be_below_bed, [circle, z = m_max_print_height + SceneEpsilon](const Vec3f &pt) { return pt.z() < z && circle.contains(to_2d(pt)); }); } case Type::Convex: //FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently. case Type::Custom: - return m_max_print_height == 0 ? + return m_max_print_height == 0.0 ? object_state_templ(its, trafo, may_be_below_bed, [this](const Vec3f &pt) { return Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_scene, to_2d(pt).cast()); }) : object_state_templ(its, trafo, may_be_below_bed, [this, z = m_max_print_height + SceneEpsilon](const Vec3f &pt) { return pt.z() < z && Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_scene, to_2d(pt).cast()); }); case Type::Invalid: @@ -302,18 +304,20 @@ BuildVolume::ObjectState BuildVolume::object_state(const indexed_triangle_set &i } } -BuildVolume::ObjectState BuildVolume::volume_state_bbox(const BoundingBoxf3 &volume_bbox) const +BuildVolume::ObjectState BuildVolume::volume_state_bbox(const BoundingBoxf3& volume_bbox, bool ignore_bottom) const { assert(m_type == Type::Rectangle); BoundingBox3Base build_volume = this->bounding_volume().inflated(SceneEpsilon); - if (m_max_print_height == 0) + if (m_max_print_height == 0.0) build_volume.max.z() = std::numeric_limits::max(); + if (ignore_bottom) + build_volume.min.z() = -std::numeric_limits::max(); return build_volume.max.z() <= - SceneEpsilon ? ObjectState::Below : build_volume.contains(volume_bbox) ? ObjectState::Inside : build_volume.intersects(volume_bbox) ? ObjectState::Colliding : ObjectState::Outside; } -bool BuildVolume::all_paths_inside(const GCodeProcessorResult &paths, const BoundingBoxf3 &paths_bbox) const +bool BuildVolume::all_paths_inside(const GCodeProcessorResult& paths, const BoundingBoxf3& paths_bbox, bool ignore_bottom) const { auto move_valid = [](const GCodeProcessorResult::MoveVertex &move) { return move.type == EMoveType::Extrude && move.extrusion_role != erCustom && move.width != 0.f && move.height != 0.f; @@ -324,8 +328,10 @@ bool BuildVolume::all_paths_inside(const GCodeProcessorResult &paths, const Boun case Type::Rectangle: { BoundingBox3Base build_volume = this->bounding_volume().inflated(epsilon); - if (m_max_print_height == 0) + if (m_max_print_height == 0.0) build_volume.max.z() = std::numeric_limits::max(); + if (ignore_bottom) + build_volume.min.z() = -std::numeric_limits::max(); return build_volume.contains(paths_bbox); } case Type::Circle: @@ -333,7 +339,7 @@ bool BuildVolume::all_paths_inside(const GCodeProcessorResult &paths, const Boun const Vec2f c = unscaled(m_circle.center); const float r = unscaled(m_circle.radius) + epsilon; const float r2 = sqr(r); - return m_max_print_height == 0 ? + return m_max_print_height == 0.0 ? std::all_of(paths.moves.begin(), paths.moves.end(), [move_valid, c, r2](const GCodeProcessorResult::MoveVertex &move) { return ! move_valid(move) || (to_2d(move.position) - c).squaredNorm() <= r2; }) : std::all_of(paths.moves.begin(), paths.moves.end(), [move_valid, c, r2, z = m_max_print_height + epsilon](const GCodeProcessorResult::MoveVertex& move) @@ -342,7 +348,7 @@ bool BuildVolume::all_paths_inside(const GCodeProcessorResult &paths, const Boun case Type::Convex: //FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently. case Type::Custom: - return m_max_print_height == 0 ? + return m_max_print_height == 0.0 ? std::all_of(paths.moves.begin(), paths.moves.end(), [move_valid, this](const GCodeProcessorResult::MoveVertex &move) { return ! move_valid(move) || Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_bed, to_2d(move.position).cast()); }) : std::all_of(paths.moves.begin(), paths.moves.end(), [move_valid, this, z = m_max_print_height + epsilon](const GCodeProcessorResult::MoveVertex &move) @@ -364,7 +370,7 @@ inline bool all_inside_vertices_normals_interleaved(const std::vector &pa return true; } -bool BuildVolume::all_paths_inside_vertices_and_normals_interleaved(const std::vector &paths, const Eigen::AlignedBox &paths_bbox) const +bool BuildVolume::all_paths_inside_vertices_and_normals_interleaved(const std::vector& paths, const Eigen::AlignedBox& paths_bbox, bool ignore_bottom) const { assert(paths.size() % 6 == 0); static constexpr const double epsilon = BedEpsilon; @@ -372,8 +378,10 @@ bool BuildVolume::all_paths_inside_vertices_and_normals_interleaved(const std::v case Type::Rectangle: { BoundingBox3Base build_volume = this->bounding_volume().inflated(epsilon); - if (m_max_print_height == 0) + if (m_max_print_height == 0.0) build_volume.max.z() = std::numeric_limits::max(); + if (ignore_bottom) + build_volume.min.z() = -std::numeric_limits::max(); return build_volume.contains(paths_bbox.min().cast()) && build_volume.contains(paths_bbox.max().cast()); } case Type::Circle: @@ -381,14 +389,14 @@ bool BuildVolume::all_paths_inside_vertices_and_normals_interleaved(const std::v const Vec2f c = unscaled(m_circle.center); const float r = unscaled(m_circle.radius) + float(epsilon); const float r2 = sqr(r); - return m_max_print_height == 0 ? + return m_max_print_height == 0.0 ? all_inside_vertices_normals_interleaved(paths, [c, r2](Vec3f p) { return (to_2d(p) - c).squaredNorm() <= r2; }) : all_inside_vertices_normals_interleaved(paths, [c, r2, z = m_max_print_height + epsilon](Vec3f p) { return (to_2d(p) - c).squaredNorm() <= r2 && p.z() <= z; }); } case Type::Convex: //FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently. case Type::Custom: - return m_max_print_height == 0 ? + return m_max_print_height == 0.0 ? all_inside_vertices_normals_interleaved(paths, [this](Vec3f p) { return Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_bed, to_2d(p).cast()); }) : all_inside_vertices_normals_interleaved(paths, [this, z = m_max_print_height + epsilon](Vec3f p) { return Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_bed, to_2d(p).cast()) && p.z() <= z; }); default: diff --git a/src/libslic3r/BuildVolume.hpp b/src/libslic3r/BuildVolume.hpp index e75710882..6b928d48b 100644 --- a/src/libslic3r/BuildVolume.hpp +++ b/src/libslic3r/BuildVolume.hpp @@ -80,19 +80,19 @@ public: // Called by Plater to update Inside / Colliding / Outside state of ModelObjects before slicing. // Called from Model::update_print_volume_state() -> ModelObject::update_instances_print_volume_state() // Using SceneEpsilon - ObjectState object_state(const indexed_triangle_set &its, const Transform3f &trafo, bool may_be_below_bed) const; + ObjectState object_state(const indexed_triangle_set &its, const Transform3f &trafo, bool may_be_below_bed, bool ignore_bottom = true) const; // Called by GLVolumeCollection::check_outside_state() after an object is manipulated with gizmos for example. // Called for a rectangular bed: - ObjectState volume_state_bbox(const BoundingBoxf3 &volume_bbox) const; + ObjectState volume_state_bbox(const BoundingBoxf3& volume_bbox, bool ignore_bottom = true) const; // 2) Test called on G-code paths. // Using BedEpsilon for all tests. static constexpr const double BedEpsilon = 3. * EPSILON; // Called on final G-code paths. //FIXME The test does not take the thickness of the extrudates into account! - bool all_paths_inside(const GCodeProcessorResult &paths, const BoundingBoxf3 &paths_bbox) const; + bool all_paths_inside(const GCodeProcessorResult& paths, const BoundingBoxf3& paths_bbox, bool ignore_bottom = true) const; // Called on initial G-code preview on OpenGL vertex buffer interleaved normals and vertices. - bool all_paths_inside_vertices_and_normals_interleaved(const std::vector &paths, const Eigen::AlignedBox &bbox) const; + bool all_paths_inside_vertices_and_normals_interleaved(const std::vector& paths, const Eigen::AlignedBox& bbox, bool ignore_bottom = true) const; private: // Source definition of the print bed geometry (PrintConfig::bed_shape) diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index f0283f1cc..96d31bf3f 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -288,7 +288,7 @@ set(CGAL_DO_NOT_WARN_ABOUT_CMAKE_BUILD_TYPE ON CACHE BOOL "" FORCE) cmake_policy(PUSH) cmake_policy(SET CMP0011 NEW) -find_package(CGAL 4.13.2 REQUIRED) +find_package(CGAL 4.13 REQUIRED) cmake_policy(POP) add_library(libslic3r_cgal STATIC MeshBoolean.cpp MeshBoolean.hpp TryCatchSignal.hpp diff --git a/src/libslic3r/PrintApply.cpp b/src/libslic3r/PrintApply.cpp index 84ff55598..1467aaea0 100644 --- a/src/libslic3r/PrintApply.cpp +++ b/src/libslic3r/PrintApply.cpp @@ -662,11 +662,10 @@ bool verify_update_print_object_regions( // if the visited modifier did not modify their properties. Now the visited modifier's configuration may have changed, // which may require new regions to be created. it_model_volume_modifier_last = it_model_volume; - int this_region_id = int(®ion - layer_range.volume_regions.data()); - int next_region_id = this_region_id + 1; + int next_region_id = int(®ion - layer_range.volume_regions.data()); const PrintObjectRegions::BoundingBox *bbox = find_volume_extents(layer_range, *region.model_volume); assert(bbox); - for (int parent_region_id = this_region_id - 1; parent_region_id >= 0; -- parent_region_id) { + for (int parent_region_id = next_region_id - 1; parent_region_id >= 0; -- parent_region_id) { const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[parent_region_id]; assert(parent_region.model_volume != region.model_volume); if (parent_region.model_volume->is_model_part() || parent_region.model_volume->is_modifier()) {