From 7e756b20e61609659864e135ff3780304fd1a4ff Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 18 Sep 2020 10:53:50 +0200 Subject: [PATCH] Adaptive infill: Reshuffled the namespaces. --- src/libslic3r/Fill/Fill.cpp | 2 +- src/libslic3r/Fill/FillAdaptive.cpp | 130 ++++++++++++++-------------- src/libslic3r/Fill/FillAdaptive.hpp | 57 ++++++------ src/libslic3r/Fill/FillBase.cpp | 4 +- src/libslic3r/Fill/FillBase.hpp | 4 +- src/libslic3r/Layer.hpp | 4 +- src/libslic3r/Print.hpp | 4 +- src/libslic3r/PrintObject.cpp | 21 ++--- 8 files changed, 108 insertions(+), 118 deletions(-) diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 70792b823..03aa798dc 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -318,7 +318,7 @@ void export_group_fills_to_svg(const char *path, const std::vector #endif // friend to Layer -void Layer::make_fills(FillAdaptive_Internal::Octree* adaptive_fill_octree, FillAdaptive_Internal::Octree* support_fill_octree) +void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree) { for (LayerRegion *layerm : m_regions) layerm->fills.clear(); diff --git a/src/libslic3r/Fill/FillAdaptive.cpp b/src/libslic3r/Fill/FillAdaptive.cpp index 6c5d7c0c4..b016242f4 100644 --- a/src/libslic3r/Fill/FillAdaptive.cpp +++ b/src/libslic3r/Fill/FillAdaptive.cpp @@ -19,6 +19,7 @@ #include namespace Slic3r { +namespace FillAdaptive { // Derived from https://github.com/juj/MathGeoLib/blob/master/src/Geometry/Triangle.cpp // The AABB-Triangle test implementation is based on the pseudo-code in @@ -165,48 +166,45 @@ static constexpr std::array, 3> child_traversal_order { std::array{ 1, 5, 0, 4, 3, 7, 2, 6 }, }; -namespace FillAdaptive_Internal +struct Cube { - struct Cube - { - Vec3d center; + Vec3d center; #ifndef NDEBUG - Vec3d center_octree; + Vec3d center_octree; #endif // NDEBUG - std::array children {}; // initialized to nullptrs - Cube(const Vec3d ¢er) : center(center) {} - }; + std::array children {}; // initialized to nullptrs + Cube(const Vec3d ¢er) : center(center) {} +}; - struct CubeProperties - { - double edge_length; // Lenght of edge of a cube - double height; // Height of rotated cube (standing on the corner) - double diagonal_length; // Length of diagonal of a cube a face - double line_z_distance; // Defines maximal distance from a center of a cube on Z axis on which lines will be created - double line_xy_distance;// Defines maximal distance from a center of a cube on X and Y axis on which lines will be created - }; +struct CubeProperties +{ + double edge_length; // Lenght of edge of a cube + double height; // Height of rotated cube (standing on the corner) + double diagonal_length; // Length of diagonal of a cube a face + double line_z_distance; // Defines maximal distance from a center of a cube on Z axis on which lines will be created + double line_xy_distance;// Defines maximal distance from a center of a cube on X and Y axis on which lines will be created +}; - struct Octree - { - // Octree will allocate its Cubes from the pool. The pool only supports deletion of the complete pool, - // perfect for building up our octree. - boost::object_pool pool; - Cube* root_cube { nullptr }; - Vec3d origin; - std::vector cubes_properties; +struct Octree +{ + // Octree will allocate its Cubes from the pool. The pool only supports deletion of the complete pool, + // perfect for building up our octree. + boost::object_pool pool; + Cube* root_cube { nullptr }; + Vec3d origin; + std::vector cubes_properties; - Octree(const Vec3d &origin, const std::vector &cubes_properties) - : root_cube(pool.construct(origin)), origin(origin), cubes_properties(cubes_properties) {} + Octree(const Vec3d &origin, const std::vector &cubes_properties) + : root_cube(pool.construct(origin)), origin(origin), cubes_properties(cubes_properties) {} - void insert_triangle(const Vec3d &a, const Vec3d &b, const Vec3d &c, Cube *current_cube, const BoundingBoxf3 ¤t_bbox, int depth); - }; + void insert_triangle(const Vec3d &a, const Vec3d &b, const Vec3d &c, Cube *current_cube, const BoundingBoxf3 ¤t_bbox, int depth); +}; - void OctreeDeleter::operator()(Octree *p) { - delete p; - } -}; // namespace FillAdaptive_Internal +void OctreeDeleter::operator()(Octree *p) { + delete p; +} -std::pair FillAdaptive_Internal::adaptive_fill_line_spacing(const PrintObject &print_object) +std::pair FillAdaptive::adaptive_fill_line_spacing(const PrintObject &print_object) { // Output, spacing for icAdaptiveCubic and icSupportCubic double adaptive_line_spacing = 0.; @@ -296,7 +294,7 @@ struct FillContext -(2.0 * M_PI) / 3.0 }; - FillContext(const FillAdaptive_Internal::Octree &octree, double z_position, int direction_idx) : + FillContext(const Octree &octree, double z_position, int direction_idx) : origin_world(octree.origin), cubes_properties(octree.cubes_properties), z_position(z_position), @@ -312,31 +310,31 @@ struct FillContext Vec2d rotate(const Vec2d& v) { return Vec2d(this->cos_a * v.x() - this->sin_a * v.y(), this->sin_a * v.x() + this->cos_a * v.y()); } // Center of the root cube in the Octree coordinate system. - const Vec3d origin_world; - const std::vector &cubes_properties; + const Vec3d origin_world; + const std::vector &cubes_properties; // Top of the current layer. - const double z_position; + const double z_position; // Order of traversal for this line direction. - const std::array traversal_order; + const std::array traversal_order; // Rotation of the generated line for this line direction. - const double cos_a; - const double sin_a; + const double cos_a; + const double sin_a; // Linearized tree spanning a single Octree wall, used to connect lines spanning // neighboring Octree cells. Unused lines have the Line::a::x set to infinity. - std::vector temp_lines; + std::vector temp_lines; // Final output - std::vector output_lines; + std::vector output_lines; }; static constexpr double octree_rot[3] = { 5.0 * M_PI / 4.0, Geometry::deg2rad(215.264), M_PI / 6.0 }; -Eigen::Quaterniond FillAdaptive_Internal::adaptive_fill_octree_transform_to_world() +Eigen::Quaterniond transform_to_world() { return Eigen::AngleAxisd(octree_rot[2], Vec3d::UnitZ()) * Eigen::AngleAxisd(octree_rot[1], Vec3d::UnitY()) * Eigen::AngleAxisd(octree_rot[0], Vec3d::UnitX()); } -Eigen::Quaterniond FillAdaptive_Internal::adaptive_fill_octree_transform_to_octree() +Eigen::Quaterniond transform_to_octree() { return Eigen::AngleAxisd(- octree_rot[0], Vec3d::UnitX()) * Eigen::AngleAxisd(- octree_rot[1], Vec3d::UnitY()) * Eigen::AngleAxisd(- octree_rot[2], Vec3d::UnitZ()); } @@ -345,14 +343,14 @@ Eigen::Quaterniond FillAdaptive_Internal::adaptive_fill_octree_transform_to_octr // Verify that the traversal order of the octree children matches the line direction, // therefore the infill line may get extended with O(1) time & space complexity. static bool verify_traversal_order( - FillContext &context, - const FillAdaptive_Internal::Cube *cube, - int depth, - const Vec2d &line_from, - const Vec2d &line_to) + FillContext &context, + const Cube *cube, + int depth, + const Vec2d &line_from, + const Vec2d &line_to) { std::array c; - Eigen::Quaterniond to_world = FillAdaptive_Internal::adaptive_fill_octree_transform_to_world(); + Eigen::Quaterniond to_world = transform_to_world(); for (int i = 0; i < 8; ++i) { int j = context.traversal_order[i]; Vec3d cntr = to_world * (cube->center_octree + (child_centers[j] * (context.cubes_properties[depth].edge_length / 4.))); @@ -379,15 +377,15 @@ static bool verify_traversal_order( #endif // NDEBUG static void generate_infill_lines_recursive( - FillContext &context, - const FillAdaptive_Internal::Cube *cube, + FillContext &context, + const Cube *cube, // Address of this wall in the octree, used to address context.temp_lines. - int address, - int depth) + int address, + int depth) { assert(cube != nullptr); - const std::vector &cubes_properties = context.cubes_properties; + const std::vector &cubes_properties = context.cubes_properties; const double z_diff = context.z_position - cube->center.z(); const double z_diff_abs = std::abs(z_diff); @@ -427,7 +425,7 @@ static void generate_infill_lines_recursive( -- depth; size_t i = 0; for (const int child_idx : context.traversal_order) { - const FillAdaptive_Internal::Cube *child = cube->children[child_idx]; + const Cube *child = cube->children[child_idx]; if (child != nullptr) generate_infill_lines_recursive(context, child, address, depth); if (++ i == 4) @@ -486,7 +484,7 @@ static void export_infill_lines_to_svg(const ExPolygon &expoly, const Polylines } #endif /* ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT */ -void FillAdaptive::_fill_surface_single( +void Filler::_fill_surface_single( const FillParams & params, unsigned int thickness_layers, const std::pair &direction, @@ -547,7 +545,7 @@ void FillAdaptive::_fill_surface_single( if (!boundary_polylines.empty()) { boundary_polylines = chain_polylines(boundary_polylines); - FillAdaptive::connect_infill(std::move(boundary_polylines), expolygon, polylines_out, this->spacing, params); + connect_infill(std::move(boundary_polylines), expolygon, polylines_out, this->spacing, params); } append(polylines_out, std::move(non_boundary_polylines)); @@ -571,14 +569,14 @@ static double bbox_max_radius(const BoundingBoxf3 &bbox, const Vec3d ¢er) return sqrt(r2max); } -static std::vector make_cubes_properties(double max_cube_edge_length, double line_spacing) +static std::vector make_cubes_properties(double max_cube_edge_length, double line_spacing) { max_cube_edge_length += EPSILON; - std::vector cubes_properties; + std::vector cubes_properties; for (double edge_length = line_spacing * 2.;; edge_length *= 2.) { - FillAdaptive_Internal::CubeProperties props{}; + CubeProperties props{}; props.edge_length = edge_length; props.height = edge_length * sqrt(3); props.diagonal_length = edge_length * sqrt(2); @@ -598,7 +596,7 @@ static inline bool is_overhang_triangle(const Vec3d &a, const Vec3d &b, const Ve return n.dot(up) > 0.707 * n.norm(); } -static void transform_center(FillAdaptive_Internal::Cube *current_cube, const Eigen::Matrix3d &rot) +static void transform_center(Cube *current_cube, const Eigen::Matrix3d &rot) { #ifndef NDEBUG current_cube->center_octree = current_cube->center; @@ -609,7 +607,7 @@ static void transform_center(FillAdaptive_Internal::Cube *current_cube, const Ei transform_center(child, rot); } -FillAdaptive_Internal::OctreePtr FillAdaptive_Internal::build_octree(const indexed_triangle_set &triangle_mesh, const Vec3d &up_vector, coordf_t line_spacing, bool support_overhangs_only) +OctreePtr build_octree(const indexed_triangle_set &triangle_mesh, coordf_t line_spacing, bool support_overhangs_only) { assert(line_spacing > 0); assert(! std::isnan(line_spacing)); @@ -620,6 +618,7 @@ FillAdaptive_Internal::OctreePtr FillAdaptive_Internal::build_octree(const index auto octree = OctreePtr(new Octree(cube_center, cubes_properties)); if (cubes_properties.size() > 1) { + auto up_vector = support_overhangs_only ? transform_to_octree() * Vec3d(0., 0., 1.) : Vec3d(); for (auto &tri : triangle_mesh.indices) { auto a = triangle_mesh.vertices[tri[0]].cast(); auto b = triangle_mesh.vertices[tri[1]].cast(); @@ -636,7 +635,7 @@ FillAdaptive_Internal::OctreePtr FillAdaptive_Internal::build_octree(const index } { // Transform the octree to world coordinates to reduce computation when extracting infill lines. - auto rot = adaptive_fill_octree_transform_to_world().toRotationMatrix(); + auto rot = transform_to_world().toRotationMatrix(); transform_center(octree->root_cube, rot); octree->origin = rot * octree->origin; } @@ -645,7 +644,7 @@ FillAdaptive_Internal::OctreePtr FillAdaptive_Internal::build_octree(const index return octree; } -void FillAdaptive_Internal::Octree::insert_triangle(const Vec3d &a, const Vec3d &b, const Vec3d &c, Cube *current_cube, const BoundingBoxf3 ¤t_bbox, int depth) +void Octree::insert_triangle(const Vec3d &a, const Vec3d &b, const Vec3d &c, Cube *current_cube, const BoundingBoxf3 ¤t_bbox, int depth) { assert(current_cube); assert(depth > 0); @@ -673,4 +672,5 @@ void FillAdaptive_Internal::Octree::insert_triangle(const Vec3d &a, const Vec3d } } +} // namespace FillAdaptive } // namespace Slic3r diff --git a/src/libslic3r/Fill/FillAdaptive.hpp b/src/libslic3r/Fill/FillAdaptive.hpp index 906414747..aca8d1d7b 100644 --- a/src/libslic3r/Fill/FillAdaptive.hpp +++ b/src/libslic3r/Fill/FillAdaptive.hpp @@ -11,8 +11,6 @@ #ifndef slic3r_FillAdaptive_hpp_ #define slic3r_FillAdaptive_hpp_ -#include "../AABBTreeIndirect.hpp" - #include "FillBase.hpp" struct indexed_triangle_set; @@ -20,58 +18,55 @@ struct indexed_triangle_set; namespace Slic3r { class PrintObject; -namespace FillAdaptive_Internal + +namespace FillAdaptive { - struct Octree; - // To keep the definition of Octree opaque, we have to define a custom deleter. - struct OctreeDeleter { - void operator()(Octree *p); - }; - using OctreePtr = std::unique_ptr; - // Calculate line spacing for - // 1) adaptive cubic infill - // 2) adaptive internal support cubic infill - // Returns zero for a particular infill type if no such infill is to be generated. - std::pair adaptive_fill_line_spacing(const PrintObject &print_object); +struct Octree; +// To keep the definition of Octree opaque, we have to define a custom deleter. +struct OctreeDeleter { void operator()(Octree *p); }; +using OctreePtr = std::unique_ptr; - // Rotation of the octree to stand on one of its corners. - Eigen::Quaterniond adaptive_fill_octree_transform_to_world(); - // Inverse roation of the above. - Eigen::Quaterniond adaptive_fill_octree_transform_to_octree(); +// Calculate line spacing for +// 1) adaptive cubic infill +// 2) adaptive internal support cubic infill +// Returns zero for a particular infill type if no such infill is to be generated. +std::pair adaptive_fill_line_spacing(const PrintObject &print_object); - FillAdaptive_Internal::OctreePtr build_octree( - // Mesh is rotated to the coordinate system of the octree. - const indexed_triangle_set &triangle_mesh, - // Up vector of the mesh rotated to the coordinate system of the octree. - const Vec3d &up_vector, - coordf_t line_spacing, - // If true, octree is densified below internal overhangs only. - bool support_overhangs_only); -}; // namespace FillAdaptive_Internal +// Rotation of the octree to stand on one of its corners. +Eigen::Quaterniond transform_to_world(); +// Inverse roation of the above. +Eigen::Quaterniond transform_to_octree(); + +FillAdaptive::OctreePtr build_octree( + // Mesh is rotated to the coordinate system of the octree. + const indexed_triangle_set &triangle_mesh, + coordf_t line_spacing, + // If true, octree is densified below internal overhangs only. + bool support_overhangs_only); // // Some of the algorithms used by class FillAdaptive were inspired by // Cura Engine's class SubDivCube // https://github.com/Ultimaker/CuraEngine/blob/master/src/infill/SubDivCube.h // -class FillAdaptive : public Fill +class Filler : public Slic3r::Fill { public: - virtual ~FillAdaptive() {} + virtual ~Filler() {} protected: - virtual Fill* clone() const { return new FillAdaptive(*this); }; + virtual Fill* clone() const { return new Filler(*this); }; virtual void _fill_surface_single( const FillParams ¶ms, unsigned int thickness_layers, const std::pair &direction, ExPolygon &expolygon, Polylines &polylines_out); - virtual bool no_sort() const { return true; } }; +}; // namespace FillAdaptive } // namespace Slic3r #endif // slic3r_FillAdaptive_hpp_ diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index 5866330b9..43b5d464a 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -38,8 +38,8 @@ Fill* Fill::new_from_type(const InfillPattern type) case ipArchimedeanChords: return new FillArchimedeanChords(); case ipHilbertCurve: return new FillHilbertCurve(); case ipOctagramSpiral: return new FillOctagramSpiral(); - case ipAdaptiveCubic: return new FillAdaptive(); - case ipSupportCubic: return new FillAdaptive(); + case ipAdaptiveCubic: return new FillAdaptive::Filler(); + case ipSupportCubic: return new FillAdaptive::Filler(); default: throw Slic3r::InvalidArgument("unknown type"); } } diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp index 4d822ddea..0779117eb 100644 --- a/src/libslic3r/Fill/FillBase.hpp +++ b/src/libslic3r/Fill/FillBase.hpp @@ -20,7 +20,7 @@ class ExPolygon; class Surface; enum InfillPattern : int; -namespace FillAdaptive_Internal { +namespace FillAdaptive { struct Octree; }; @@ -76,7 +76,7 @@ public: BoundingBox bounding_box; // Octree builds on mesh for usage in the adaptive cubic infill - FillAdaptive_Internal::Octree* adapt_fill_octree = nullptr; + FillAdaptive::Octree* adapt_fill_octree = nullptr; public: virtual ~Fill() {} diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index 8d5db42fc..8285b5493 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -13,7 +13,7 @@ class Layer; class PrintRegion; class PrintObject; -namespace FillAdaptive_Internal { +namespace FillAdaptive { struct Octree; }; @@ -139,7 +139,7 @@ public: } void make_perimeters(); void make_fills() { this->make_fills(nullptr, nullptr); }; - void make_fills(FillAdaptive_Internal::Octree* adaptive_fill_octree, FillAdaptive_Internal::Octree* support_fill_octree); + void make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree); void make_ironing(); void export_region_slices_to_svg(const char *path) const; diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 471484005..a389ef00d 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -30,7 +30,7 @@ enum class SlicingMode : uint32_t; class Layer; class SupportLayer; -namespace FillAdaptive_Internal { +namespace FillAdaptive { struct Octree; struct OctreeDeleter; using OctreePtr = std::unique_ptr; @@ -241,7 +241,7 @@ private: void discover_horizontal_shells(); void combine_infill(); void _generate_support_material(); - std::pair prepare_adaptive_infill_data(); + std::pair prepare_adaptive_infill_data(); // XYZ in scaled coordinates Vec3crd m_size; diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 0968f6cfc..ac47e1d10 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -434,27 +434,22 @@ void PrintObject::generate_support_material() } } -std::pair PrintObject::prepare_adaptive_infill_data() +std::pair PrintObject::prepare_adaptive_infill_data() { - using namespace FillAdaptive_Internal; + using namespace FillAdaptive; auto [adaptive_line_spacing, support_line_spacing] = adaptive_fill_line_spacing(*this); if (adaptive_line_spacing == 0. && support_line_spacing == 0.) return std::make_pair(OctreePtr(), OctreePtr()); indexed_triangle_set mesh = this->model_object()->raw_indexed_triangle_set(); - Vec3d up; - { - auto m = adaptive_fill_octree_transform_to_octree().toRotationMatrix(); - up = m * Vec3d(0., 0., 1.); - // Rotate mesh and build octree on it with axis-aligned (standart base) cubes - Transform3d m2 = m_trafo; - m2.translate(Vec3d(- unscale(m_center_offset.x()), - unscale(m_center_offset.y()), 0)); - its_transform(mesh, m * m2, true); - } + // Rotate mesh and build octree on it with axis-aligned (standart base) cubes. + Transform3d m = m_trafo; + m.translate(Vec3d(- unscale(m_center_offset.x()), - unscale(m_center_offset.y()), 0)); + its_transform(mesh, transform_to_octree().toRotationMatrix() * m, true); return std::make_pair( - adaptive_line_spacing ? build_octree(mesh, up, adaptive_line_spacing, false) : OctreePtr(), - support_line_spacing ? build_octree(mesh, up, support_line_spacing, true) : OctreePtr()); + adaptive_line_spacing ? build_octree(mesh, adaptive_line_spacing, false) : OctreePtr(), + support_line_spacing ? build_octree(mesh, support_line_spacing, true) : OctreePtr()); } void PrintObject::clear_layers()