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
// 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();

View File

@ -19,6 +19,7 @@
#include <boost/pool/object_pool.hpp>
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<std::array<int, 8>, 3> child_traversal_order {
std::array<int, 8>{ 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<Cube*, 8> children {}; // initialized to nullptrs
Cube(const Vec3d &center) : center(center) {}
};
std::array<Cube*, 8> children {}; // initialized to nullptrs
Cube(const Vec3d &center) : 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<Cube> pool;
Cube* root_cube { nullptr };
Vec3d origin;
std::vector<CubeProperties> 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<Cube> pool;
Cube* root_cube { nullptr };
Vec3d origin;
std::vector<CubeProperties> cubes_properties;
Octree(const Vec3d &origin, const std::vector<CubeProperties> &cubes_properties)
: root_cube(pool.construct(origin)), origin(origin), cubes_properties(cubes_properties) {}
Octree(const Vec3d &origin, const std::vector<CubeProperties> &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 &current_bbox, int depth);
};
void insert_triangle(const Vec3d &a, const Vec3d &b, const Vec3d &c, Cube *current_cube, const BoundingBoxf3 &current_bbox, int depth);
};
void OctreeDeleter::operator()(Octree *p) {
delete p;
}
}; // namespace FillAdaptive_Internal
void OctreeDeleter::operator()(Octree *p) {
delete p;
}
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
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<FillAdaptive_Internal::CubeProperties> &cubes_properties;
const Vec3d origin_world;
const std::vector<CubeProperties> &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<int, 8> traversal_order;
const std::array<int, 8> 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<Line> temp_lines;
std::vector<Line> temp_lines;
// Final output
std::vector<Line> output_lines;
std::vector<Line> 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<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) {
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<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_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<float, Point> &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 &center)
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;
std::vector<FillAdaptive_Internal::CubeProperties> cubes_properties;
std::vector<CubeProperties> 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<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.
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 &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(depth > 0);
@ -673,4 +672,5 @@ void FillAdaptive_Internal::Octree::insert_triangle(const Vec3d &a, const Vec3d
}
}
} // namespace FillAdaptive
} // namespace Slic3r

View File

@ -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<Octree, OctreeDeleter>;
// 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<double, double> 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<Octree, OctreeDeleter>;
// 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<double, double> 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 &params,
unsigned int thickness_layers,
const std::pair<float, Point> &direction,
ExPolygon &expolygon,
Polylines &polylines_out);
virtual bool no_sort() const { return true; }
};
}; // namespace FillAdaptive
} // namespace Slic3r
#endif // slic3r_FillAdaptive_hpp_

View File

@ -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");
}
}

View File

@ -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() {}

View File

@ -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;

View File

@ -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<Octree, OctreeDeleter>;
@ -241,7 +241,7 @@ private:
void discover_horizontal_shells();
void combine_infill();
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
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);
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<float>(m_center_offset.x()), - unscale<float>(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<float>(m_center_offset.x()), - unscale<float>(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()