Merge branch 'lh_adaptive_support_infill'
This commit is contained in:
commit
cf838a47c4
11 changed files with 314 additions and 38 deletions
|
@ -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)
|
||||
void Layer::make_fills(FillAdaptive_Internal::Octree* adaptive_fill_octree, FillAdaptive_Internal::Octree* support_fill_octree)
|
||||
{
|
||||
for (LayerRegion *layerm : m_regions)
|
||||
layerm->fills.clear();
|
||||
|
@ -346,6 +346,7 @@ void Layer::make_fills(FillAdaptive_Internal::Octree* adaptive_fill_octree)
|
|||
f->z = this->print_z;
|
||||
f->angle = surface_fill.params.angle;
|
||||
f->adapt_fill_octree = adaptive_fill_octree;
|
||||
f->support_fill_octree = support_fill_octree;
|
||||
|
||||
// calculate flow spacing for infill pattern generation
|
||||
bool using_internal_flow = ! surface_fill.surface.is_solid() && ! surface_fill.params.flow.bridge;
|
||||
|
|
|
@ -35,7 +35,7 @@ std::pair<double, double> adaptive_fill_line_spacing(const PrintObject &print_ob
|
|||
const PrintRegionConfig &config = region->config();
|
||||
bool nonempty = config.fill_density > 0;
|
||||
bool has_adaptive_infill = nonempty && config.fill_pattern == ipAdaptiveCubic;
|
||||
bool has_support_infill = nonempty && false; // config.fill_pattern == icSupportCubic;
|
||||
bool has_support_infill = nonempty && config.fill_pattern == ipSupportCubic;
|
||||
region_fill_data.push_back(RegionFillData({
|
||||
has_adaptive_infill ? Tristate::Maybe : Tristate::No,
|
||||
has_support_infill ? Tristate::Maybe : Tristate::No,
|
||||
|
@ -90,19 +90,32 @@ std::pair<double, double> adaptive_fill_line_spacing(const PrintObject &print_ob
|
|||
return std::make_pair(adaptive_line_spacing, support_line_spacing);
|
||||
}
|
||||
|
||||
void FillAdaptive::_fill_surface_single(
|
||||
const FillParams ¶ms,
|
||||
unsigned int thickness_layers,
|
||||
const std::pair<float, Point> &direction,
|
||||
ExPolygon &expolygon,
|
||||
Polylines &polylines_out)
|
||||
void FillAdaptive::_fill_surface_single(const FillParams & params,
|
||||
unsigned int thickness_layers,
|
||||
const std::pair<float, Point> &direction,
|
||||
ExPolygon & expolygon,
|
||||
Polylines & polylines_out)
|
||||
{
|
||||
if(this->adapt_fill_octree != nullptr)
|
||||
this->generate_infill(params, thickness_layers, direction, expolygon, polylines_out, this->adapt_fill_octree);
|
||||
}
|
||||
|
||||
void FillAdaptive::generate_infill(const FillParams & params,
|
||||
unsigned int thickness_layers,
|
||||
const std::pair<float, Point> &direction,
|
||||
ExPolygon & expolygon,
|
||||
Polylines & polylines_out,
|
||||
FillAdaptive_Internal::Octree *octree)
|
||||
{
|
||||
Vec3d rotation = Vec3d((5.0 * M_PI) / 4.0, Geometry::deg2rad(215.264), M_PI / 6.0);
|
||||
Transform3d rotation_matrix = Geometry::assemble_transform(Vec3d::Zero(), rotation, Vec3d::Ones(), Vec3d::Ones());
|
||||
|
||||
// Store grouped lines by its direction (multiple of 120°)
|
||||
std::vector<Lines> infill_lines_dir(3);
|
||||
this->generate_infill_lines(this->adapt_fill_octree->root_cube.get(),
|
||||
this->z, this->adapt_fill_octree->origin,infill_lines_dir,
|
||||
this->adapt_fill_octree->cubes_properties,
|
||||
int(this->adapt_fill_octree->cubes_properties.size()) - 1);
|
||||
this->generate_infill_lines(octree->root_cube.get(),
|
||||
this->z, octree->origin, rotation_matrix,
|
||||
infill_lines_dir, octree->cubes_properties,
|
||||
int(octree->cubes_properties.size()) - 1);
|
||||
|
||||
Polylines all_polylines;
|
||||
all_polylines.reserve(infill_lines_dir[0].size() * 3);
|
||||
|
@ -186,6 +199,7 @@ void FillAdaptive::generate_infill_lines(
|
|||
FillAdaptive_Internal::Cube *cube,
|
||||
double z_position,
|
||||
const Vec3d &origin,
|
||||
const Transform3d &rotation_matrix,
|
||||
std::vector<Lines> &dir_lines_out,
|
||||
const std::vector<FillAdaptive_Internal::CubeProperties> &cubes_properties,
|
||||
int depth)
|
||||
|
@ -197,7 +211,8 @@ void FillAdaptive::generate_infill_lines(
|
|||
return;
|
||||
}
|
||||
|
||||
double z_diff = std::abs(z_position - cube->center.z());
|
||||
Vec3d cube_center_tranformed = rotation_matrix * cube->center;
|
||||
double z_diff = std::abs(z_position - cube_center_tranformed.z());
|
||||
|
||||
if (z_diff > cubes_properties[depth].height / 2)
|
||||
{
|
||||
|
@ -208,14 +223,14 @@ void FillAdaptive::generate_infill_lines(
|
|||
{
|
||||
Point from(
|
||||
scale_((cubes_properties[depth].diagonal_length / 2) * (cubes_properties[depth].line_z_distance - z_diff) / cubes_properties[depth].line_z_distance),
|
||||
scale_(cubes_properties[depth].line_xy_distance - ((z_position - (cube->center.z() - cubes_properties[depth].line_z_distance)) / sqrt(2))));
|
||||
scale_(cubes_properties[depth].line_xy_distance - ((z_position - (cube_center_tranformed.z() - cubes_properties[depth].line_z_distance)) / sqrt(2))));
|
||||
Point to(-from.x(), from.y());
|
||||
// Relative to cube center
|
||||
|
||||
double rotation_angle = (2.0 * M_PI) / 3.0;
|
||||
for (Lines &lines : dir_lines_out)
|
||||
{
|
||||
Vec3d offset = cube->center - origin;
|
||||
Vec3d offset = cube_center_tranformed - (rotation_matrix * origin);
|
||||
Point from_abs(from), to_abs(to);
|
||||
|
||||
from_abs.x() += int(scale_(offset.x()));
|
||||
|
@ -235,7 +250,7 @@ void FillAdaptive::generate_infill_lines(
|
|||
{
|
||||
if(child != nullptr)
|
||||
{
|
||||
generate_infill_lines(child.get(), z_position, origin, dir_lines_out, cubes_properties, depth - 1);
|
||||
generate_infill_lines(child.get(), z_position, origin, rotation_matrix, dir_lines_out, cubes_properties, depth - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -301,14 +316,11 @@ std::unique_ptr<FillAdaptive_Internal::Octree> FillAdaptive::build_octree(
|
|||
triangle_mesh.require_shared_vertices();
|
||||
}
|
||||
|
||||
Vec3d rotation = Vec3d((5.0 * M_PI) / 4.0, Geometry::deg2rad(215.264), M_PI / 6.0);
|
||||
Transform3d rotation_matrix = Geometry::assemble_transform(Vec3d::Zero(), rotation, Vec3d::Ones(), Vec3d::Ones());
|
||||
|
||||
AABBTreeIndirect::Tree3f aabbTree = AABBTreeIndirect::build_aabb_tree_over_indexed_triangle_set(
|
||||
triangle_mesh.its.vertices, triangle_mesh.its.indices);
|
||||
auto octree = std::make_unique<Octree>(std::make_unique<Cube>(cube_center), cube_center, cubes_properties);
|
||||
|
||||
FillAdaptive::expand_cube(octree->root_cube.get(), cubes_properties, rotation_matrix, aabbTree, triangle_mesh, int(cubes_properties.size()) - 1);
|
||||
FillAdaptive::expand_cube(octree->root_cube.get(), cubes_properties, aabbTree, triangle_mesh, int(cubes_properties.size()) - 1);
|
||||
|
||||
return octree;
|
||||
}
|
||||
|
@ -316,7 +328,6 @@ std::unique_ptr<FillAdaptive_Internal::Octree> FillAdaptive::build_octree(
|
|||
void FillAdaptive::expand_cube(
|
||||
FillAdaptive_Internal::Cube *cube,
|
||||
const std::vector<FillAdaptive_Internal::CubeProperties> &cubes_properties,
|
||||
const Transform3d &rotation_matrix,
|
||||
const AABBTreeIndirect::Tree3f &distance_tree,
|
||||
const TriangleMesh &triangle_mesh, int depth)
|
||||
{
|
||||
|
@ -328,8 +339,8 @@ void FillAdaptive::expand_cube(
|
|||
}
|
||||
|
||||
std::vector<Vec3d> child_centers = {
|
||||
Vec3d(-1, -1, -1), Vec3d( 1, -1, -1), Vec3d(-1, 1, -1), Vec3d(-1, -1, 1),
|
||||
Vec3d( 1, 1, 1), Vec3d(-1, 1, 1), Vec3d( 1, -1, 1), Vec3d( 1, 1, -1)
|
||||
Vec3d(-1, -1, -1), Vec3d( 1, -1, -1), Vec3d(-1, 1, -1), Vec3d( 1, 1, -1),
|
||||
Vec3d(-1, -1, 1), Vec3d( 1, -1, 1), Vec3d(-1, 1, 1), Vec3d( 1, 1, 1)
|
||||
};
|
||||
|
||||
double cube_radius_squared = (cubes_properties[depth].height * cubes_properties[depth].height) / 16;
|
||||
|
@ -337,15 +348,173 @@ void FillAdaptive::expand_cube(
|
|||
for (size_t i = 0; i < 8; ++i)
|
||||
{
|
||||
const Vec3d &child_center = child_centers[i];
|
||||
Vec3d child_center_transformed = cube->center + rotation_matrix * (child_center * (cubes_properties[depth].edge_length / 4));
|
||||
Vec3d child_center_transformed = cube->center + (child_center * (cubes_properties[depth].edge_length / 4));
|
||||
|
||||
if(AABBTreeIndirect::is_any_triangle_in_radius(triangle_mesh.its.vertices, triangle_mesh.its.indices,
|
||||
distance_tree, child_center_transformed, cube_radius_squared))
|
||||
{
|
||||
cube->children[i] = std::make_unique<Cube>(child_center_transformed);
|
||||
FillAdaptive::expand_cube(cube->children[i].get(), cubes_properties, rotation_matrix, distance_tree, triangle_mesh, depth - 1);
|
||||
FillAdaptive::expand_cube(cube->children[i].get(), cubes_properties, distance_tree, triangle_mesh, depth - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FillAdaptive_Internal::Octree::propagate_point(
|
||||
Vec3d point,
|
||||
FillAdaptive_Internal::Cube * current,
|
||||
int depth,
|
||||
const std::vector<FillAdaptive_Internal::CubeProperties> &cubes_properties)
|
||||
{
|
||||
using namespace FillAdaptive_Internal;
|
||||
|
||||
if(depth <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
size_t octant_idx = Octree::find_octant(point, current->center);
|
||||
Cube * child = current->children[octant_idx].get();
|
||||
|
||||
// Octant not exists, then create it
|
||||
if(child == nullptr) {
|
||||
std::vector<Vec3d> child_centers = {
|
||||
Vec3d(-1, -1, -1), Vec3d( 1, -1, -1), Vec3d(-1, 1, -1), Vec3d( 1, 1, -1),
|
||||
Vec3d(-1, -1, 1), Vec3d( 1, -1, 1), Vec3d(-1, 1, 1), Vec3d( 1, 1, 1)
|
||||
};
|
||||
|
||||
const Vec3d &child_center = child_centers[octant_idx];
|
||||
Vec3d child_center_transformed = current->center + (child_center * (cubes_properties[depth].edge_length / 4));
|
||||
|
||||
current->children[octant_idx] = std::make_unique<Cube>(child_center_transformed);
|
||||
child = current->children[octant_idx].get();
|
||||
}
|
||||
|
||||
Octree::propagate_point(point, child, (depth - 1), cubes_properties);
|
||||
}
|
||||
|
||||
std::unique_ptr<FillAdaptive_Internal::Octree> FillSupportCubic::build_octree_for_adaptive_support(
|
||||
TriangleMesh & triangle_mesh,
|
||||
coordf_t line_spacing,
|
||||
const Vec3d & cube_center,
|
||||
const Transform3d &rotation_matrix)
|
||||
{
|
||||
using namespace FillAdaptive_Internal;
|
||||
|
||||
if(line_spacing <= 0 || std::isnan(line_spacing))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Vec3d bb_size = triangle_mesh.bounding_box().size();
|
||||
// The furthest point from the center of the bottom of the mesh bounding box.
|
||||
double furthest_point = std::sqrt(((bb_size.x() * bb_size.x()) / 4.0) +
|
||||
((bb_size.y() * bb_size.y()) / 4.0) +
|
||||
(bb_size.z() * bb_size.z()));
|
||||
double max_cube_edge_length = furthest_point * 2;
|
||||
|
||||
std::vector<CubeProperties> cubes_properties;
|
||||
for (double edge_length = (line_spacing * 2); edge_length < (max_cube_edge_length * 2); edge_length *= 2)
|
||||
{
|
||||
CubeProperties props{};
|
||||
props.edge_length = edge_length;
|
||||
props.height = edge_length * sqrt(3);
|
||||
props.diagonal_length = edge_length * sqrt(2);
|
||||
props.line_z_distance = edge_length / sqrt(3);
|
||||
props.line_xy_distance = edge_length / sqrt(6);
|
||||
cubes_properties.push_back(props);
|
||||
}
|
||||
|
||||
if (triangle_mesh.its.vertices.empty())
|
||||
{
|
||||
triangle_mesh.require_shared_vertices();
|
||||
}
|
||||
|
||||
AABBTreeIndirect::Tree3f aabbTree = AABBTreeIndirect::build_aabb_tree_over_indexed_triangle_set(
|
||||
triangle_mesh.its.vertices, triangle_mesh.its.indices);
|
||||
|
||||
auto octree = std::make_unique<Octree>(std::make_unique<Cube>(cube_center), cube_center, cubes_properties);
|
||||
|
||||
double cube_edge_length = line_spacing;
|
||||
size_t max_depth = octree->cubes_properties.size() - 1;
|
||||
BoundingBoxf3 mesh_bb = triangle_mesh.bounding_box();
|
||||
Vec3f vertical(0, 0, 1);
|
||||
|
||||
for (size_t facet_idx = 0; facet_idx < triangle_mesh.stl.facet_start.size(); ++facet_idx)
|
||||
{
|
||||
if(triangle_mesh.stl.facet_start[facet_idx].normal.dot(vertical) <= 0.707)
|
||||
{
|
||||
// The angle is smaller than PI/4, than infill don't to be there
|
||||
continue;
|
||||
}
|
||||
|
||||
stl_vertex v_1 = triangle_mesh.stl.facet_start[facet_idx].vertex[0];
|
||||
stl_vertex v_2 = triangle_mesh.stl.facet_start[facet_idx].vertex[1];
|
||||
stl_vertex v_3 = triangle_mesh.stl.facet_start[facet_idx].vertex[2];
|
||||
|
||||
std::vector<Vec3d> triangle_vertices =
|
||||
{Vec3d(v_1.x(), v_1.y(), v_1.z()),
|
||||
Vec3d(v_2.x(), v_2.y(), v_2.z()),
|
||||
Vec3d(v_3.x(), v_3.y(), v_3.z())};
|
||||
|
||||
BoundingBoxf3 triangle_bb(triangle_vertices);
|
||||
|
||||
Vec3d triangle_start_relative = triangle_bb.min - mesh_bb.min;
|
||||
Vec3d triangle_end_relative = triangle_bb.max - mesh_bb.min;
|
||||
|
||||
Vec3crd triangle_start_idx = Vec3crd(
|
||||
std::floor(triangle_start_relative.x() / cube_edge_length),
|
||||
std::floor(triangle_start_relative.y() / cube_edge_length),
|
||||
std::floor(triangle_start_relative.z() / cube_edge_length));
|
||||
Vec3crd triangle_end_idx = Vec3crd(
|
||||
std::floor(triangle_end_relative.x() / cube_edge_length),
|
||||
std::floor(triangle_end_relative.y() / cube_edge_length),
|
||||
std::floor(triangle_end_relative.z() / cube_edge_length));
|
||||
|
||||
for (int z = triangle_start_idx.z(); z <= triangle_end_idx.z(); ++z)
|
||||
{
|
||||
for (int y = triangle_start_idx.y(); y <= triangle_end_idx.y(); ++y)
|
||||
{
|
||||
for (int x = triangle_start_idx.x(); x <= triangle_end_idx.x(); ++x)
|
||||
{
|
||||
Vec3d cube_center_relative(x * cube_edge_length + (cube_edge_length / 2.0), y * cube_edge_length + (cube_edge_length / 2.0), z * cube_edge_length);
|
||||
Vec3d cube_center_absolute = cube_center_relative + mesh_bb.min;
|
||||
|
||||
double cube_center_absolute_arr[3] = {cube_center_absolute.x(), cube_center_absolute.y(), cube_center_absolute.z()};
|
||||
double distance = 0, cord_u = 0, cord_v = 0;
|
||||
|
||||
double dir[3] = {0.0, 0.0, 1.0};
|
||||
|
||||
double vert_0[3] = {triangle_vertices[0].x(),
|
||||
triangle_vertices[0].y(),
|
||||
triangle_vertices[0].z()};
|
||||
double vert_1[3] = {triangle_vertices[1].x(),
|
||||
triangle_vertices[1].y(),
|
||||
triangle_vertices[1].z()};
|
||||
double vert_2[3] = {triangle_vertices[2].x(),
|
||||
triangle_vertices[2].y(),
|
||||
triangle_vertices[2].z()};
|
||||
|
||||
if(intersect_triangle(cube_center_absolute_arr, dir, vert_0, vert_1, vert_2, &distance, &cord_u, &cord_v) && distance > 0 && distance <= cube_edge_length)
|
||||
{
|
||||
Vec3d cube_center_transformed(cube_center_absolute.x(), cube_center_absolute.y(), cube_center_absolute.z() + (cube_edge_length / 2.0));
|
||||
Octree::propagate_point(cube_center_transformed, octree->root_cube.get(), max_depth, octree->cubes_properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return octree;
|
||||
}
|
||||
|
||||
void FillSupportCubic::_fill_surface_single(const FillParams & params,
|
||||
unsigned int thickness_layers,
|
||||
const std::pair<float, Point> &direction,
|
||||
ExPolygon & expolygon,
|
||||
Polylines & polylines_out)
|
||||
{
|
||||
if (this->support_fill_octree != nullptr)
|
||||
this->generate_infill(params, thickness_layers, direction, expolygon, polylines_out, this->support_fill_octree);
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -35,6 +35,17 @@ namespace FillAdaptive_Internal
|
|||
|
||||
Octree(std::unique_ptr<Cube> rootCube, const Vec3d &origin, const std::vector<CubeProperties> &cubes_properties)
|
||||
: root_cube(std::move(rootCube)), origin(origin), cubes_properties(cubes_properties) {}
|
||||
|
||||
inline static int find_octant(const Vec3d &i_cube, const Vec3d ¤t)
|
||||
{
|
||||
return (i_cube.z() > current.z()) * 4 + (i_cube.y() > current.y()) * 2 + (i_cube.x() > current.x());
|
||||
}
|
||||
|
||||
static void propagate_point(
|
||||
Vec3d point,
|
||||
FillAdaptive_Internal::Cube *current_cube,
|
||||
int depth,
|
||||
const std::vector<FillAdaptive_Internal::CubeProperties> &cubes_properties);
|
||||
};
|
||||
}; // namespace FillAdaptive_Internal
|
||||
|
||||
|
@ -63,12 +74,20 @@ protected:
|
|||
FillAdaptive_Internal::Cube *cube,
|
||||
double z_position,
|
||||
const Vec3d & origin,
|
||||
const Transform3d & rotation_matrix,
|
||||
std::vector<Lines> & dir_lines_out,
|
||||
const std::vector<FillAdaptive_Internal::CubeProperties> &cubes_properties,
|
||||
int depth);
|
||||
|
||||
static void connect_lines(Lines &lines, Line new_line);
|
||||
|
||||
void generate_infill(const FillParams & params,
|
||||
unsigned int thickness_layers,
|
||||
const std::pair<float, Point> &direction,
|
||||
ExPolygon & expolygon,
|
||||
Polylines & polylines_out,
|
||||
FillAdaptive_Internal::Octree *octree);
|
||||
|
||||
public:
|
||||
static std::unique_ptr<FillAdaptive_Internal::Octree> build_octree(
|
||||
TriangleMesh &triangle_mesh,
|
||||
|
@ -78,12 +97,36 @@ public:
|
|||
static void expand_cube(
|
||||
FillAdaptive_Internal::Cube *cube,
|
||||
const std::vector<FillAdaptive_Internal::CubeProperties> &cubes_properties,
|
||||
const Transform3d & rotation_matrix,
|
||||
const AABBTreeIndirect::Tree3f &distance_tree,
|
||||
const TriangleMesh & triangle_mesh,
|
||||
int depth);
|
||||
};
|
||||
|
||||
class FillSupportCubic : public FillAdaptive
|
||||
{
|
||||
public:
|
||||
virtual ~FillSupportCubic() = default;
|
||||
|
||||
protected:
|
||||
virtual Fill* clone() const { return new FillSupportCubic(*this); };
|
||||
|
||||
virtual bool no_sort() const { return true; }
|
||||
|
||||
virtual void _fill_surface_single(
|
||||
const FillParams ¶ms,
|
||||
unsigned int thickness_layers,
|
||||
const std::pair<float, Point> &direction,
|
||||
ExPolygon &expolygon,
|
||||
Polylines &polylines_out);
|
||||
|
||||
public:
|
||||
static std::unique_ptr<FillAdaptive_Internal::Octree> build_octree_for_adaptive_support(
|
||||
TriangleMesh & triangle_mesh,
|
||||
coordf_t line_spacing,
|
||||
const Vec3d & cube_center,
|
||||
const Transform3d &rotation_matrix);
|
||||
};
|
||||
|
||||
// Calculate line spacing for
|
||||
// 1) adaptive cubic infill
|
||||
// 2) adaptive internal support cubic infill
|
||||
|
|
|
@ -39,6 +39,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
|
|||
case ipHilbertCurve: return new FillHilbertCurve();
|
||||
case ipOctagramSpiral: return new FillOctagramSpiral();
|
||||
case ipAdaptiveCubic: return new FillAdaptive();
|
||||
case ipSupportCubic: return new FillSupportCubic();
|
||||
default: throw std::invalid_argument("unknown type");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,10 @@ public:
|
|||
// In scaled coordinates. Bounding box of the 2D projection of the object.
|
||||
BoundingBox bounding_box;
|
||||
|
||||
// Octree builds on mesh for usage in the adaptive cubic infill
|
||||
FillAdaptive_Internal::Octree* adapt_fill_octree = nullptr;
|
||||
// Octree builds on mesh for usage in the support cubic infill
|
||||
FillAdaptive_Internal::Octree* support_fill_octree = nullptr;
|
||||
|
||||
public:
|
||||
virtual ~Fill() {}
|
||||
|
|
|
@ -138,8 +138,8 @@ public:
|
|||
return false;
|
||||
}
|
||||
void make_perimeters();
|
||||
void make_fills() { this->make_fills(nullptr); };
|
||||
void make_fills(FillAdaptive_Internal::Octree* adaptive_fill_octree);
|
||||
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_ironing();
|
||||
|
||||
void export_region_slices_to_svg(const char *path) const;
|
||||
|
|
|
@ -239,7 +239,7 @@ private:
|
|||
void discover_horizontal_shells();
|
||||
void combine_infill();
|
||||
void _generate_support_material();
|
||||
std::unique_ptr<FillAdaptive_Internal::Octree> prepare_adaptive_infill_data();
|
||||
std::pair<std::unique_ptr<FillAdaptive_Internal::Octree>, std::unique_ptr<FillAdaptive_Internal::Octree>> prepare_adaptive_infill_data();
|
||||
|
||||
// XYZ in scaled coordinates
|
||||
Vec3crd m_size;
|
||||
|
|
|
@ -882,6 +882,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->enum_values.push_back("archimedeanchords");
|
||||
def->enum_values.push_back("octagramspiral");
|
||||
def->enum_values.push_back("adaptivecubic");
|
||||
def->enum_values.push_back("supportcubic");
|
||||
def->enum_labels.push_back(L("Rectilinear"));
|
||||
def->enum_labels.push_back(L("Grid"));
|
||||
def->enum_labels.push_back(L("Triangles"));
|
||||
|
@ -896,6 +897,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->enum_labels.push_back(L("Archimedean Chords"));
|
||||
def->enum_labels.push_back(L("Octagram Spiral"));
|
||||
def->enum_labels.push_back(L("Adaptive Cubic"));
|
||||
def->enum_labels.push_back(L("Support Cubic"));
|
||||
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipStars));
|
||||
|
||||
def = this->add("first_layer_acceleration", coFloat);
|
||||
|
|
|
@ -39,7 +39,7 @@ enum AuthorizationType {
|
|||
|
||||
enum InfillPattern : int {
|
||||
ipRectilinear, ipMonotonous, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb,
|
||||
ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipAdaptiveCubic, ipCount,
|
||||
ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipAdaptiveCubic, ipSupportCubic, ipCount,
|
||||
};
|
||||
|
||||
enum class IroningType {
|
||||
|
@ -140,6 +140,7 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<InfillPattern>::g
|
|||
keys_map["archimedeanchords"] = ipArchimedeanChords;
|
||||
keys_map["octagramspiral"] = ipOctagramSpiral;
|
||||
keys_map["adaptivecubic"] = ipAdaptiveCubic;
|
||||
keys_map["supportcubic"] = ipSupportCubic;
|
||||
}
|
||||
return keys_map;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "Utils.hpp"
|
||||
#include "AABBTreeIndirect.hpp"
|
||||
#include "Fill/FillAdaptive.hpp"
|
||||
#include "Format/STL.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
@ -371,15 +372,15 @@ void PrintObject::infill()
|
|||
this->prepare_infill();
|
||||
|
||||
if (this->set_started(posInfill)) {
|
||||
std::unique_ptr<FillAdaptive_Internal::Octree> octree = this->prepare_adaptive_infill_data();
|
||||
auto [adaptive_fill_octree, support_fill_octree] = this->prepare_adaptive_infill_data();
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - start";
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||
[this, &octree](const tbb::blocked_range<size_t>& range) {
|
||||
[this, &adaptive_fill_octree, &support_fill_octree](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||
m_print->throw_if_canceled();
|
||||
m_layers[layer_idx]->make_fills(octree.get());
|
||||
m_layers[layer_idx]->make_fills(adaptive_fill_octree.get(), support_fill_octree.get());
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -432,11 +433,18 @@ void PrintObject::generate_support_material()
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<FillAdaptive_Internal::Octree> PrintObject::prepare_adaptive_infill_data()
|
||||
//#define ADAPTIVE_SUPPORT_SIMPLE
|
||||
|
||||
std::pair<std::unique_ptr<FillAdaptive_Internal::Octree>, std::unique_ptr<FillAdaptive_Internal::Octree>> PrintObject::prepare_adaptive_infill_data()
|
||||
{
|
||||
using namespace FillAdaptive_Internal;
|
||||
|
||||
auto [adaptive_line_spacing, support_line_spacing] = adaptive_fill_line_spacing(*this);
|
||||
if (adaptive_line_spacing == 0.)
|
||||
return std::unique_ptr<FillAdaptive_Internal::Octree>{};
|
||||
|
||||
std::unique_ptr<Octree> adaptive_fill_octree = {}, support_fill_octree = {};
|
||||
|
||||
if (adaptive_line_spacing == 0. && support_line_spacing == 0.)
|
||||
return std::make_pair(std::move(adaptive_fill_octree), std::move(support_fill_octree));
|
||||
|
||||
TriangleMesh mesh = this->model_object()->raw_mesh();
|
||||
mesh.transform(m_trafo, true);
|
||||
|
@ -444,7 +452,55 @@ std::unique_ptr<FillAdaptive_Internal::Octree> PrintObject::prepare_adaptive_inf
|
|||
mesh.translate(- unscale<float>(m_center_offset.x()), - unscale<float>(m_center_offset.y()), 0);
|
||||
// Center of the first cube in octree
|
||||
Vec3d mesh_origin = mesh.bounding_box().center();
|
||||
return FillAdaptive::build_octree(mesh, adaptive_line_spacing, mesh_origin);
|
||||
|
||||
#ifdef ADAPTIVE_SUPPORT_SIMPLE
|
||||
if (mesh.its.vertices.empty())
|
||||
{
|
||||
mesh.require_shared_vertices();
|
||||
}
|
||||
|
||||
Vec3f vertical(0, 0, 1);
|
||||
|
||||
indexed_triangle_set its_set;
|
||||
its_set.vertices = mesh.its.vertices;
|
||||
|
||||
// Filter out non overhanging faces
|
||||
for (size_t i = 0; i < mesh.its.indices.size(); ++i) {
|
||||
stl_triangle_vertex_indices vertex_idx = mesh.its.indices[i];
|
||||
|
||||
auto its_calculate_normal = [](const stl_triangle_vertex_indices &index, const std::vector<stl_vertex> &vertices) {
|
||||
stl_normal normal = (vertices[index.y()] - vertices[index.x()]).cross(vertices[index.z()] - vertices[index.x()]);
|
||||
return normal;
|
||||
};
|
||||
|
||||
stl_normal normal = its_calculate_normal(vertex_idx, mesh.its.vertices);
|
||||
stl_normalize_vector(normal);
|
||||
|
||||
if(normal.dot(vertical) >= 0.707) {
|
||||
its_set.indices.push_back(vertex_idx);
|
||||
}
|
||||
}
|
||||
|
||||
mesh = TriangleMesh(its_set);
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
Slic3r::store_stl(debug_out_path("overhangs.stl").c_str(), &mesh, false);
|
||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
#endif /* ADAPTIVE_SUPPORT_SIMPLE */
|
||||
|
||||
Vec3d rotation = Vec3d((5.0 * M_PI) / 4.0, Geometry::deg2rad(215.264), M_PI / 6.0);
|
||||
Transform3d rotation_matrix = Geometry::assemble_transform(Vec3d::Zero(), rotation, Vec3d::Ones(), Vec3d::Ones()).inverse();
|
||||
|
||||
// Rotate mesh and build octree on it with axis-aligned (standart base) cubes
|
||||
mesh.transform(rotation_matrix);
|
||||
|
||||
if (adaptive_line_spacing != 0.)
|
||||
adaptive_fill_octree = FillAdaptive::build_octree(mesh, adaptive_line_spacing, rotation_matrix * mesh_origin);
|
||||
|
||||
if (support_line_spacing != 0.)
|
||||
support_fill_octree = FillSupportCubic::build_octree_for_adaptive_support(mesh, support_line_spacing, rotation_matrix * mesh_origin, rotation_matrix);
|
||||
|
||||
return std::make_pair(std::move(adaptive_fill_octree), std::move(support_fill_octree));
|
||||
}
|
||||
|
||||
void PrintObject::clear_layers()
|
||||
|
|
|
@ -70,7 +70,7 @@ TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector<Vec3i> &fac
|
|||
stl_get_size(&stl);
|
||||
}
|
||||
|
||||
TriangleMesh::TriangleMesh(const indexed_triangle_set &M)
|
||||
TriangleMesh::TriangleMesh(const indexed_triangle_set &M) : repaired(false)
|
||||
{
|
||||
stl.stats.type = inmemory;
|
||||
|
||||
|
|
Loading…
Reference in a new issue