Adaptive infill: Reshuffled the namespaces.

This commit is contained in:
Vojtech Bubnik 2020-09-18 10:53:50 +02:00
parent 7c7f5ebdda
commit 7e756b20e6
8 changed files with 108 additions and 118 deletions

View file

@ -318,7 +318,7 @@ void export_group_fills_to_svg(const char *path, const std::vector<SurfaceFill>
#endif #endif
// friend to Layer // 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) for (LayerRegion *layerm : m_regions)
layerm->fills.clear(); layerm->fills.clear();

View file

@ -19,6 +19,7 @@
#include <boost/pool/object_pool.hpp> #include <boost/pool/object_pool.hpp>
namespace Slic3r { namespace Slic3r {
namespace FillAdaptive {
// Derived from https://github.com/juj/MathGeoLib/blob/master/src/Geometry/Triangle.cpp // 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 // The AABB-Triangle test implementation is based on the pseudo-code in
@ -165,8 +166,6 @@ static constexpr std::array<std::array<int, 8>, 3> child_traversal_order {
std::array<int, 8>{ 1, 5, 0, 4, 3, 7, 2, 6 }, std::array<int, 8>{ 1, 5, 0, 4, 3, 7, 2, 6 },
}; };
namespace FillAdaptive_Internal
{
struct Cube struct Cube
{ {
Vec3d center; Vec3d center;
@ -204,9 +203,8 @@ namespace FillAdaptive_Internal
void OctreeDeleter::operator()(Octree *p) { void OctreeDeleter::operator()(Octree *p) {
delete p; delete p;
} }
}; // namespace FillAdaptive_Internal
std::pair<double, double> FillAdaptive_Internal::adaptive_fill_line_spacing(const PrintObject &print_object) std::pair<double, double> FillAdaptive::adaptive_fill_line_spacing(const PrintObject &print_object)
{ {
// Output, spacing for icAdaptiveCubic and icSupportCubic // Output, spacing for icAdaptiveCubic and icSupportCubic
double adaptive_line_spacing = 0.; double adaptive_line_spacing = 0.;
@ -296,7 +294,7 @@ struct FillContext
-(2.0 * M_PI) / 3.0 -(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), origin_world(octree.origin),
cubes_properties(octree.cubes_properties), cubes_properties(octree.cubes_properties),
z_position(z_position), z_position(z_position),
@ -313,7 +311,7 @@ struct FillContext
// Center of the root cube in the Octree coordinate system. // Center of the root cube in the Octree coordinate system.
const Vec3d origin_world; const Vec3d origin_world;
const std::vector<FillAdaptive_Internal::CubeProperties> &cubes_properties; const std::vector<CubeProperties> &cubes_properties;
// Top of the current layer. // Top of the current layer.
const double z_position; const double z_position;
// Order of traversal for this line direction. // Order of traversal for this line direction.
@ -331,12 +329,12 @@ struct FillContext
static constexpr double octree_rot[3] = { 5.0 * M_PI / 4.0, Geometry::deg2rad(215.264), M_PI / 6.0 }; 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()); 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()); return Eigen::AngleAxisd(- octree_rot[0], Vec3d::UnitX()) * Eigen::AngleAxisd(- octree_rot[1], Vec3d::UnitY()) * Eigen::AngleAxisd(- octree_rot[2], Vec3d::UnitZ());
} }
@ -346,13 +344,13 @@ Eigen::Quaterniond FillAdaptive_Internal::adaptive_fill_octree_transform_to_octr
// therefore the infill line may get extended with O(1) time & space complexity. // therefore the infill line may get extended with O(1) time & space complexity.
static bool verify_traversal_order( static bool verify_traversal_order(
FillContext &context, FillContext &context,
const FillAdaptive_Internal::Cube *cube, const Cube *cube,
int depth, int depth,
const Vec2d &line_from, const Vec2d &line_from,
const Vec2d &line_to) const Vec2d &line_to)
{ {
std::array<Vec3d, 8> c; std::array<Vec3d, 8> 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) { for (int i = 0; i < 8; ++i) {
int j = context.traversal_order[i]; int j = context.traversal_order[i];
Vec3d cntr = to_world * (cube->center_octree + (child_centers[j] * (context.cubes_properties[depth].edge_length / 4.))); Vec3d cntr = to_world * (cube->center_octree + (child_centers[j] * (context.cubes_properties[depth].edge_length / 4.)));
@ -380,14 +378,14 @@ static bool verify_traversal_order(
static void generate_infill_lines_recursive( static void generate_infill_lines_recursive(
FillContext &context, FillContext &context,
const FillAdaptive_Internal::Cube *cube, const Cube *cube,
// Address of this wall in the octree, used to address context.temp_lines. // Address of this wall in the octree, used to address context.temp_lines.
int address, int address,
int depth) int depth)
{ {
assert(cube != nullptr); assert(cube != nullptr);
const std::vector<FillAdaptive_Internal::CubeProperties> &cubes_properties = context.cubes_properties; const std::vector<CubeProperties> &cubes_properties = context.cubes_properties;
const double z_diff = context.z_position - cube->center.z(); const double z_diff = context.z_position - cube->center.z();
const double z_diff_abs = std::abs(z_diff); const double z_diff_abs = std::abs(z_diff);
@ -427,7 +425,7 @@ static void generate_infill_lines_recursive(
-- depth; -- depth;
size_t i = 0; size_t i = 0;
for (const int child_idx : context.traversal_order) { 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) if (child != nullptr)
generate_infill_lines_recursive(context, child, address, depth); generate_infill_lines_recursive(context, child, address, depth);
if (++ i == 4) 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 */ #endif /* ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT */
void FillAdaptive::_fill_surface_single( void Filler::_fill_surface_single(
const FillParams & params, const FillParams & params,
unsigned int thickness_layers, unsigned int thickness_layers,
const std::pair<float, Point> &direction, const std::pair<float, Point> &direction,
@ -547,7 +545,7 @@ void FillAdaptive::_fill_surface_single(
if (!boundary_polylines.empty()) { if (!boundary_polylines.empty()) {
boundary_polylines = chain_polylines(boundary_polylines); 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)); append(polylines_out, std::move(non_boundary_polylines));
@ -571,14 +569,14 @@ static double bbox_max_radius(const BoundingBoxf3 &bbox, const Vec3d &center)
return sqrt(r2max); return sqrt(r2max);
} }
static std::vector<FillAdaptive_Internal::CubeProperties> make_cubes_properties(double max_cube_edge_length, double line_spacing) static std::vector<CubeProperties> make_cubes_properties(double max_cube_edge_length, double line_spacing)
{ {
max_cube_edge_length += EPSILON; max_cube_edge_length += EPSILON;
std::vector<FillAdaptive_Internal::CubeProperties> cubes_properties; std::vector<CubeProperties> cubes_properties;
for (double edge_length = line_spacing * 2.;; edge_length *= 2.) for (double edge_length = line_spacing * 2.;; edge_length *= 2.)
{ {
FillAdaptive_Internal::CubeProperties props{}; CubeProperties props{};
props.edge_length = edge_length; props.edge_length = edge_length;
props.height = edge_length * sqrt(3); props.height = edge_length * sqrt(3);
props.diagonal_length = edge_length * sqrt(2); 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(); 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 #ifndef NDEBUG
current_cube->center_octree = current_cube->center; 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); 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(line_spacing > 0);
assert(! std::isnan(line_spacing)); 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)); auto octree = OctreePtr(new Octree(cube_center, cubes_properties));
if (cubes_properties.size() > 1) { 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) { for (auto &tri : triangle_mesh.indices) {
auto a = triangle_mesh.vertices[tri[0]].cast<double>(); auto a = triangle_mesh.vertices[tri[0]].cast<double>();
auto b = triangle_mesh.vertices[tri[1]].cast<double>(); auto b = triangle_mesh.vertices[tri[1]].cast<double>();
@ -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. // 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); transform_center(octree->root_cube, rot);
octree->origin = rot * octree->origin; octree->origin = rot * octree->origin;
} }
@ -645,7 +644,7 @@ FillAdaptive_Internal::OctreePtr FillAdaptive_Internal::build_octree(const index
return octree; return octree;
} }
void FillAdaptive_Internal::Octree::insert_triangle(const Vec3d &a, const Vec3d &b, const Vec3d &c, Cube *current_cube, const BoundingBoxf3 &current_bbox, int depth) void Octree::insert_triangle(const Vec3d &a, const Vec3d &b, const Vec3d &c, Cube *current_cube, const BoundingBoxf3 &current_bbox, int depth)
{ {
assert(current_cube); assert(current_cube);
assert(depth > 0); assert(depth > 0);
@ -673,4 +672,5 @@ void FillAdaptive_Internal::Octree::insert_triangle(const Vec3d &a, const Vec3d
} }
} }
} // namespace FillAdaptive
} // namespace Slic3r } // namespace Slic3r

View file

@ -11,8 +11,6 @@
#ifndef slic3r_FillAdaptive_hpp_ #ifndef slic3r_FillAdaptive_hpp_
#define slic3r_FillAdaptive_hpp_ #define slic3r_FillAdaptive_hpp_
#include "../AABBTreeIndirect.hpp"
#include "FillBase.hpp" #include "FillBase.hpp"
struct indexed_triangle_set; struct indexed_triangle_set;
@ -20,13 +18,13 @@ struct indexed_triangle_set;
namespace Slic3r { namespace Slic3r {
class PrintObject; class PrintObject;
namespace FillAdaptive_Internal
namespace FillAdaptive
{ {
struct Octree; struct Octree;
// To keep the definition of Octree opaque, we have to define a custom deleter. // To keep the definition of Octree opaque, we have to define a custom deleter.
struct OctreeDeleter { struct OctreeDeleter { void operator()(Octree *p); };
void operator()(Octree *p);
};
using OctreePtr = std::unique_ptr<Octree, OctreeDeleter>; using OctreePtr = std::unique_ptr<Octree, OctreeDeleter>;
// Calculate line spacing for // Calculate line spacing for
@ -36,42 +34,39 @@ namespace FillAdaptive_Internal
std::pair<double, double> adaptive_fill_line_spacing(const PrintObject &print_object); std::pair<double, double> adaptive_fill_line_spacing(const PrintObject &print_object);
// Rotation of the octree to stand on one of its corners. // Rotation of the octree to stand on one of its corners.
Eigen::Quaterniond adaptive_fill_octree_transform_to_world(); Eigen::Quaterniond transform_to_world();
// Inverse roation of the above. // Inverse roation of the above.
Eigen::Quaterniond adaptive_fill_octree_transform_to_octree(); Eigen::Quaterniond transform_to_octree();
FillAdaptive_Internal::OctreePtr build_octree( FillAdaptive::OctreePtr build_octree(
// Mesh is rotated to the coordinate system of the octree. // Mesh is rotated to the coordinate system of the octree.
const indexed_triangle_set &triangle_mesh, 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, coordf_t line_spacing,
// If true, octree is densified below internal overhangs only. // If true, octree is densified below internal overhangs only.
bool support_overhangs_only); bool support_overhangs_only);
}; // namespace FillAdaptive_Internal
// //
// Some of the algorithms used by class FillAdaptive were inspired by // Some of the algorithms used by class FillAdaptive were inspired by
// Cura Engine's class SubDivCube // Cura Engine's class SubDivCube
// https://github.com/Ultimaker/CuraEngine/blob/master/src/infill/SubDivCube.h // https://github.com/Ultimaker/CuraEngine/blob/master/src/infill/SubDivCube.h
// //
class FillAdaptive : public Fill class Filler : public Slic3r::Fill
{ {
public: public:
virtual ~FillAdaptive() {} virtual ~Filler() {}
protected: protected:
virtual Fill* clone() const { return new FillAdaptive(*this); }; virtual Fill* clone() const { return new Filler(*this); };
virtual void _fill_surface_single( virtual void _fill_surface_single(
const FillParams &params, const FillParams &params,
unsigned int thickness_layers, unsigned int thickness_layers,
const std::pair<float, Point> &direction, const std::pair<float, Point> &direction,
ExPolygon &expolygon, ExPolygon &expolygon,
Polylines &polylines_out); Polylines &polylines_out);
virtual bool no_sort() const { return true; } virtual bool no_sort() const { return true; }
}; };
}; // namespace FillAdaptive
} // namespace Slic3r } // namespace Slic3r
#endif // slic3r_FillAdaptive_hpp_ #endif // slic3r_FillAdaptive_hpp_

View file

@ -38,8 +38,8 @@ Fill* Fill::new_from_type(const InfillPattern type)
case ipArchimedeanChords: return new FillArchimedeanChords(); case ipArchimedeanChords: return new FillArchimedeanChords();
case ipHilbertCurve: return new FillHilbertCurve(); case ipHilbertCurve: return new FillHilbertCurve();
case ipOctagramSpiral: return new FillOctagramSpiral(); case ipOctagramSpiral: return new FillOctagramSpiral();
case ipAdaptiveCubic: return new FillAdaptive(); case ipAdaptiveCubic: return new FillAdaptive::Filler();
case ipSupportCubic: return new FillAdaptive(); case ipSupportCubic: return new FillAdaptive::Filler();
default: throw Slic3r::InvalidArgument("unknown type"); default: throw Slic3r::InvalidArgument("unknown type");
} }
} }

View file

@ -20,7 +20,7 @@ class ExPolygon;
class Surface; class Surface;
enum InfillPattern : int; enum InfillPattern : int;
namespace FillAdaptive_Internal { namespace FillAdaptive {
struct Octree; struct Octree;
}; };
@ -76,7 +76,7 @@ public:
BoundingBox bounding_box; BoundingBox bounding_box;
// Octree builds on mesh for usage in the adaptive cubic infill // 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: public:
virtual ~Fill() {} virtual ~Fill() {}

View file

@ -13,7 +13,7 @@ class Layer;
class PrintRegion; class PrintRegion;
class PrintObject; class PrintObject;
namespace FillAdaptive_Internal { namespace FillAdaptive {
struct Octree; struct Octree;
}; };
@ -139,7 +139,7 @@ public:
} }
void make_perimeters(); void make_perimeters();
void make_fills() { this->make_fills(nullptr, nullptr); }; 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 make_ironing();
void export_region_slices_to_svg(const char *path) const; void export_region_slices_to_svg(const char *path) const;

View file

@ -30,7 +30,7 @@ enum class SlicingMode : uint32_t;
class Layer; class Layer;
class SupportLayer; class SupportLayer;
namespace FillAdaptive_Internal { namespace FillAdaptive {
struct Octree; struct Octree;
struct OctreeDeleter; struct OctreeDeleter;
using OctreePtr = std::unique_ptr<Octree, OctreeDeleter>; using OctreePtr = std::unique_ptr<Octree, OctreeDeleter>;
@ -241,7 +241,7 @@ private:
void discover_horizontal_shells(); void discover_horizontal_shells();
void combine_infill(); void combine_infill();
void _generate_support_material(); void _generate_support_material();
std::pair<FillAdaptive_Internal::OctreePtr, FillAdaptive_Internal::OctreePtr> prepare_adaptive_infill_data(); std::pair<FillAdaptive::OctreePtr, FillAdaptive::OctreePtr> prepare_adaptive_infill_data();
// XYZ in scaled coordinates // XYZ in scaled coordinates
Vec3crd m_size; Vec3crd m_size;

View file

@ -434,27 +434,22 @@ void PrintObject::generate_support_material()
} }
} }
std::pair<FillAdaptive_Internal::OctreePtr, FillAdaptive_Internal::OctreePtr> PrintObject::prepare_adaptive_infill_data() std::pair<FillAdaptive::OctreePtr, FillAdaptive::OctreePtr> PrintObject::prepare_adaptive_infill_data()
{ {
using namespace FillAdaptive_Internal; using namespace FillAdaptive;
auto [adaptive_line_spacing, support_line_spacing] = adaptive_fill_line_spacing(*this); auto [adaptive_line_spacing, support_line_spacing] = adaptive_fill_line_spacing(*this);
if (adaptive_line_spacing == 0. && support_line_spacing == 0.) if (adaptive_line_spacing == 0. && support_line_spacing == 0.)
return std::make_pair(OctreePtr(), OctreePtr()); return std::make_pair(OctreePtr(), OctreePtr());
indexed_triangle_set mesh = this->model_object()->raw_indexed_triangle_set(); indexed_triangle_set mesh = this->model_object()->raw_indexed_triangle_set();
Vec3d up; // Rotate mesh and build octree on it with axis-aligned (standart base) cubes.
{ Transform3d m = m_trafo;
auto m = adaptive_fill_octree_transform_to_octree().toRotationMatrix(); m.translate(Vec3d(- unscale<float>(m_center_offset.x()), - unscale<float>(m_center_offset.y()), 0));
up = m * Vec3d(0., 0., 1.); its_transform(mesh, transform_to_octree().toRotationMatrix() * m, true);
// Rotate mesh and build octree on it with axis-aligned (standart base) cubes
Transform3d m2 = m_trafo;
m2.translate(Vec3d(- unscale<float>(m_center_offset.x()), - unscale<float>(m_center_offset.y()), 0));
its_transform(mesh, m * m2, true);
}
return std::make_pair( return std::make_pair(
adaptive_line_spacing ? build_octree(mesh, up, adaptive_line_spacing, false) : OctreePtr(), adaptive_line_spacing ? build_octree(mesh, adaptive_line_spacing, false) : OctreePtr(),
support_line_spacing ? build_octree(mesh, up, support_line_spacing, true) : OctreePtr()); support_line_spacing ? build_octree(mesh, support_line_spacing, true) : OctreePtr());
} }
void PrintObject::clear_layers() void PrintObject::clear_layers()