mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer
This commit is contained in:
		
						commit
						3527cd48e8
					
				
					 12 changed files with 466 additions and 5 deletions
				
			
		|  | @ -692,6 +692,40 @@ inline typename VectorType::Scalar squared_distance_to_indexed_triangle_set( | |||
|     	detail::squared_distance_to_indexed_triangle_set_recursive(distancer, size_t(0), Scalar(0), std::numeric_limits<Scalar>::infinity(), hit_idx_out, hit_point_out); | ||||
| } | ||||
| 
 | ||||
| // Decides if exists some triangle in defined radius on a 3D indexed triangle set using a pre-built AABBTreeIndirect::Tree.
 | ||||
| // Closest point to triangle test will be performed with the accuracy of VectorType::Scalar
 | ||||
| // even if the triangle mesh and the AABB Tree are built with floats.
 | ||||
| // Returns true if exists some triangle in defined radius, false otherwise.
 | ||||
| template<typename VertexType, typename IndexedFaceType, typename TreeType, typename VectorType> | ||||
| inline bool is_any_triangle_in_radius( | ||||
|         // Indexed triangle set - 3D vertices.
 | ||||
|         const std::vector<VertexType> 		&vertices, | ||||
|         // Indexed triangle set - triangular faces, references to vertices.
 | ||||
|         const std::vector<IndexedFaceType> 	&faces, | ||||
|         // AABBTreeIndirect::Tree over vertices & faces, bounding boxes built with the accuracy of vertices.
 | ||||
|         const TreeType 						&tree, | ||||
|         // Point to which the closest point on the indexed triangle set is searched for.
 | ||||
|         const VectorType					&point, | ||||
|         // Maximum distance in which triangle is search for
 | ||||
|         typename VectorType::Scalar &max_distance) | ||||
| { | ||||
|     using Scalar = typename VectorType::Scalar; | ||||
|     auto distancer = detail::IndexedTriangleSetDistancer<VertexType, IndexedFaceType, TreeType, VectorType> | ||||
|             { vertices, faces, tree, point }; | ||||
| 
 | ||||
| 	size_t hit_idx; | ||||
| 	VectorType hit_point = VectorType::Ones() * (std::nan("")); | ||||
| 
 | ||||
| 	if(tree.empty()) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	detail::squared_distance_to_indexed_triangle_set_recursive(distancer, size_t(0), Scalar(0), max_distance, hit_idx, hit_point); | ||||
| 
 | ||||
|     return hit_point.allFinite(); | ||||
| } | ||||
| 
 | ||||
| } // namespace AABBTreeIndirect
 | ||||
| } // namespace Slic3r
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -46,6 +46,8 @@ add_library(libslic3r STATIC | |||
|     Fill/Fill.hpp | ||||
|     Fill/Fill3DHoneycomb.cpp | ||||
|     Fill/Fill3DHoneycomb.hpp | ||||
|     Fill/FillAdaptive.cpp | ||||
|     Fill/FillAdaptive.hpp | ||||
|     Fill/FillBase.cpp | ||||
|     Fill/FillBase.hpp | ||||
|     Fill/FillConcentric.cpp | ||||
|  |  | |||
|  | @ -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() | ||||
| void Layer::make_fills(FillAdaptive_Internal::Octree* adaptive_fill_octree) | ||||
| { | ||||
| 	for (LayerRegion *layerm : m_regions) | ||||
| 		layerm->fills.clear(); | ||||
|  | @ -345,6 +345,7 @@ void Layer::make_fills() | |||
|         f->layer_id = this->id(); | ||||
|         f->z 		= this->print_z; | ||||
|         f->angle 	= surface_fill.params.angle; | ||||
|         f->adapt_fill_octree = adaptive_fill_octree; | ||||
| 
 | ||||
|         // calculate flow spacing for infill pattern generation
 | ||||
|         bool using_internal_flow = ! surface_fill.surface.is_solid() && ! surface_fill.params.flow.bridge; | ||||
|  |  | |||
							
								
								
									
										270
									
								
								src/libslic3r/Fill/FillAdaptive.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										270
									
								
								src/libslic3r/Fill/FillAdaptive.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,270 @@ | |||
| #include "../ClipperUtils.hpp" | ||||
| #include "../ExPolygon.hpp" | ||||
| #include "../Surface.hpp" | ||||
| #include "../Geometry.hpp" | ||||
| #include "../AABBTreeIndirect.hpp" | ||||
| #include "../ShortestPath.hpp" | ||||
| 
 | ||||
| #include "FillAdaptive.hpp" | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
| void FillAdaptive::_fill_surface_single( | ||||
|     const FillParams                ¶ms,  | ||||
|     unsigned int                     thickness_layers, | ||||
|     const std::pair<float, Point>   &direction,  | ||||
|     ExPolygon                       &expolygon,  | ||||
|     Polylines                       &polylines_out) | ||||
| { | ||||
|     // 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, | ||||
|                                 this->adapt_fill_octree->cubes_properties.size() - 1); | ||||
| 
 | ||||
|     Polylines all_polylines; | ||||
|     all_polylines.reserve(infill_lines_dir[0].size() * 3); | ||||
|     for (Lines &infill_lines : infill_lines_dir) | ||||
|     { | ||||
|         for (const Line &line : infill_lines) | ||||
|         { | ||||
|             all_polylines.emplace_back(line.a, line.b); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (params.dont_connect) | ||||
|     { | ||||
|         // Crop all polylines
 | ||||
|         polylines_out = intersection_pl(all_polylines, to_polygons(expolygon)); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         // Crop all polylines
 | ||||
|         all_polylines = intersection_pl(all_polylines, to_polygons(expolygon)); | ||||
| 
 | ||||
|         Polylines boundary_polylines; | ||||
|         Polylines non_boundary_polylines; | ||||
|         for (const Polyline &polyline : all_polylines) | ||||
|         { | ||||
|             // connect_infill required all polylines to touch the boundary.
 | ||||
|             if(polyline.lines().size() == 1 && expolygon.has_boundary_point(polyline.lines().front().a) && expolygon.has_boundary_point(polyline.lines().front().b)) | ||||
|             { | ||||
|                 boundary_polylines.push_back(polyline); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 non_boundary_polylines.push_back(polyline); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if(!boundary_polylines.empty()) | ||||
|         { | ||||
|             boundary_polylines = chain_polylines(boundary_polylines); | ||||
|             FillAdaptive::connect_infill(std::move(boundary_polylines), expolygon, polylines_out, this->spacing, params); | ||||
|         } | ||||
| 
 | ||||
|         polylines_out.insert(polylines_out.end(), non_boundary_polylines.begin(), non_boundary_polylines.end()); | ||||
|     } | ||||
| 
 | ||||
| #ifdef SLIC3R_DEBUG_SLICE_PROCESSING | ||||
|     { | ||||
|         static int iRuna = 0; | ||||
|         BoundingBox bbox_svg = this->bounding_box; | ||||
|         { | ||||
|             ::Slic3r::SVG svg(debug_out_path("FillAdaptive-%d.svg", iRuna), bbox_svg); | ||||
|             for (const Polyline &polyline : polylines_out) | ||||
|             { | ||||
|                 for (const Line &line : polyline.lines()) | ||||
|                 { | ||||
|                     Point from = line.a; | ||||
|                     Point to = line.b; | ||||
|                     Point diff = to - from; | ||||
| 
 | ||||
|                     float shrink_length = scale_(0.4); | ||||
|                     float line_slope = (float)diff.y() / diff.x(); | ||||
|                     float shrink_x = shrink_length / (float)std::sqrt(1.0 + (line_slope * line_slope)); | ||||
|                     float shrink_y = line_slope * shrink_x; | ||||
| 
 | ||||
|                     to.x() -= shrink_x; | ||||
|                     to.y() -= shrink_y; | ||||
|                     from.x() += shrink_x; | ||||
|                     from.y() += shrink_y; | ||||
| 
 | ||||
|                     svg.draw(Line(from, to)); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         iRuna++; | ||||
|     } | ||||
| #endif /* SLIC3R_DEBUG */ | ||||
| } | ||||
| 
 | ||||
| void FillAdaptive::generate_infill_lines( | ||||
|         FillAdaptive_Internal::Cube *cube, | ||||
|         double z_position, | ||||
|         const Vec3d &origin, | ||||
|         std::vector<Lines> &dir_lines_out, | ||||
|         const std::vector<FillAdaptive_Internal::CubeProperties> &cubes_properties, | ||||
|         int depth) | ||||
| { | ||||
|     using namespace FillAdaptive_Internal; | ||||
| 
 | ||||
|     if(cube == nullptr) | ||||
|     { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     double z_diff = std::abs(z_position - cube->center.z()); | ||||
| 
 | ||||
|     if (z_diff > cubes_properties[depth].height / 2) | ||||
|     { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (z_diff < cubes_properties[depth].line_z_distance) | ||||
|     { | ||||
|         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)))); | ||||
|         Point to(-from.x(), from.y()); | ||||
|         // Relative to cube center
 | ||||
| 
 | ||||
|         float rotation_angle = (2.0 * M_PI) / 3.0; | ||||
|         for (Lines &lines : dir_lines_out) | ||||
|         { | ||||
|             Vec3d offset = cube->center - origin; | ||||
|             Point from_abs(from), to_abs(to); | ||||
| 
 | ||||
|             from_abs.x() += scale_(offset.x()); | ||||
|             from_abs.y() += scale_(offset.y()); | ||||
|             to_abs.x() += scale_(offset.x()); | ||||
|             to_abs.y() += scale_(offset.y()); | ||||
| 
 | ||||
| //            lines.emplace_back(from_abs, to_abs);
 | ||||
|             this->connect_lines(lines, Line(from_abs, to_abs)); | ||||
| 
 | ||||
|             from.rotate(rotation_angle); | ||||
|             to.rotate(rotation_angle); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     for(const std::unique_ptr<Cube> &child : cube->children) | ||||
|     { | ||||
|         if(child != nullptr) | ||||
|         { | ||||
|             generate_infill_lines(child.get(), z_position, origin, dir_lines_out, cubes_properties, depth - 1); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void FillAdaptive::connect_lines(Lines &lines, Line new_line) | ||||
| { | ||||
|     int eps = scale_(0.10); | ||||
|     for (size_t i = 0; i < lines.size(); ++i) | ||||
|     { | ||||
|         if (std::abs(new_line.a.x() - lines[i].b.x()) < eps && std::abs(new_line.a.y() - lines[i].b.y()) < eps) | ||||
|         { | ||||
|             new_line.a = lines[i].a; | ||||
|             lines.erase(lines.begin() + i); | ||||
|             --i; | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         if (std::abs(new_line.b.x() - lines[i].a.x()) < eps && std::abs(new_line.b.y() - lines[i].a.y()) < eps) | ||||
|         { | ||||
|             new_line.b = lines[i].b; | ||||
|             lines.erase(lines.begin() + i); | ||||
|             --i; | ||||
|             continue; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     lines.emplace_back(new_line.a, new_line.b); | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<FillAdaptive_Internal::Octree> FillAdaptive::build_octree( | ||||
|     TriangleMesh &triangle_mesh, | ||||
|     coordf_t line_spacing, | ||||
|     const Vec3d &cube_center) | ||||
| { | ||||
|     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(); | ||||
|     } | ||||
| 
 | ||||
|     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, cubes_properties.size() - 1); | ||||
| 
 | ||||
|     return 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) | ||||
| { | ||||
|     using namespace FillAdaptive_Internal; | ||||
| 
 | ||||
|     if (cube == nullptr || depth == 0) | ||||
|     { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     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) | ||||
|     }; | ||||
| 
 | ||||
|     double cube_radius_squared = (cubes_properties[depth].height * cubes_properties[depth].height) / 16; | ||||
| 
 | ||||
|     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)); | ||||
| 
 | ||||
|         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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| } // namespace Slic3r
 | ||||
							
								
								
									
										87
									
								
								src/libslic3r/Fill/FillAdaptive.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/libslic3r/Fill/FillAdaptive.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,87 @@ | |||
| #ifndef slic3r_FillAdaptive_hpp_ | ||||
| #define slic3r_FillAdaptive_hpp_ | ||||
| 
 | ||||
| #include "../AABBTreeIndirect.hpp" | ||||
| 
 | ||||
| #include "FillBase.hpp" | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
| namespace FillAdaptive_Internal | ||||
| { | ||||
|     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 Cube | ||||
|     { | ||||
|         Vec3d center; | ||||
|         std::unique_ptr<Cube> children[8] = {}; | ||||
|         Cube(const Vec3d ¢er) : center(center) {} | ||||
|     }; | ||||
| 
 | ||||
|     struct Octree | ||||
|     { | ||||
|         std::unique_ptr<Cube> root_cube; | ||||
|         Vec3d origin; | ||||
|         std::vector<CubeProperties> cubes_properties; | ||||
| 
 | ||||
|         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) {} | ||||
|     }; | ||||
| }; // namespace FillAdaptive_Internal
 | ||||
| 
 | ||||
| //
 | ||||
| // 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 | ||||
| { | ||||
| public: | ||||
|     virtual ~FillAdaptive() {} | ||||
| 
 | ||||
| protected: | ||||
|     virtual Fill* clone() const { return new FillAdaptive(*this); }; | ||||
| 	virtual void _fill_surface_single( | ||||
| 	    const FillParams                ¶ms, | ||||
| 	    unsigned int                     thickness_layers, | ||||
| 	    const std::pair<float, Point>   &direction, | ||||
| 	    ExPolygon                       &expolygon, | ||||
| 	    Polylines                       &polylines_out); | ||||
| 
 | ||||
| 	virtual bool no_sort() const { return true; } | ||||
| 
 | ||||
|     void generate_infill_lines( | ||||
|         FillAdaptive_Internal::Cube *cube, | ||||
|         double                       z_position, | ||||
|         const Vec3d &                origin, | ||||
|         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); | ||||
| 
 | ||||
| public: | ||||
|     static std::unique_ptr<FillAdaptive_Internal::Octree> build_octree( | ||||
|         TriangleMesh &triangle_mesh, | ||||
|         coordf_t      line_spacing, | ||||
|         const Vec3d & cube_center); | ||||
| 
 | ||||
|     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); | ||||
| }; | ||||
| 
 | ||||
| } // namespace Slic3r
 | ||||
| 
 | ||||
| #endif // slic3r_FillAdaptive_hpp_
 | ||||
|  | @ -16,6 +16,7 @@ | |||
| #include "FillRectilinear.hpp" | ||||
| #include "FillRectilinear2.hpp" | ||||
| #include "FillRectilinear3.hpp" | ||||
| #include "FillAdaptive.hpp" | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
|  | @ -37,6 +38,7 @@ 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(); | ||||
|     default: throw std::invalid_argument("unknown type"); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -19,6 +19,10 @@ class ExPolygon; | |||
| class Surface; | ||||
| enum InfillPattern : int; | ||||
| 
 | ||||
| namespace FillAdaptive_Internal { | ||||
|     struct Octree; | ||||
| }; | ||||
| 
 | ||||
| class InfillFailedException : public std::runtime_error { | ||||
| public: | ||||
|     InfillFailedException() : std::runtime_error("Infill failed") {} | ||||
|  | @ -69,6 +73,8 @@ public: | |||
|     // In scaled coordinates. Bounding box of the 2D projection of the object.
 | ||||
|     BoundingBox bounding_box; | ||||
| 
 | ||||
|     FillAdaptive_Internal::Octree* adapt_fill_octree = nullptr; | ||||
| 
 | ||||
| public: | ||||
|     virtual ~Fill() {} | ||||
| 
 | ||||
|  |  | |||
|  | @ -13,6 +13,10 @@ class Layer; | |||
| class PrintRegion; | ||||
| class PrintObject; | ||||
| 
 | ||||
| namespace FillAdaptive_Internal { | ||||
|     struct Octree; | ||||
| }; | ||||
| 
 | ||||
| class LayerRegion | ||||
| { | ||||
| public: | ||||
|  | @ -134,7 +138,8 @@ public: | |||
|         return false; | ||||
|     } | ||||
|     void                    make_perimeters(); | ||||
|     void                    make_fills(); | ||||
|     void                    make_fills() { this->make_fills(nullptr); }; | ||||
|     void                    make_fills(FillAdaptive_Internal::Octree* adaptive_fill_octree); | ||||
|     void 					make_ironing(); | ||||
| 
 | ||||
|     void                    export_region_slices_to_svg(const char *path) const; | ||||
|  |  | |||
|  | @ -30,6 +30,10 @@ enum class SlicingMode : uint32_t; | |||
| class Layer; | ||||
| class SupportLayer; | ||||
| 
 | ||||
| namespace FillAdaptive_Internal { | ||||
|     struct Octree; | ||||
| }; | ||||
| 
 | ||||
| // Print step IDs for keeping track of the print state.
 | ||||
| enum PrintStep { | ||||
|     psSkirt,  | ||||
|  | @ -235,6 +239,7 @@ private: | |||
|     void discover_horizontal_shells(); | ||||
|     void combine_infill(); | ||||
|     void _generate_support_material(); | ||||
|     std::unique_ptr<FillAdaptive_Internal::Octree> prepare_adaptive_infill_data(); | ||||
| 
 | ||||
|     // XYZ in scaled coordinates
 | ||||
|     Vec3crd									m_size; | ||||
|  |  | |||
|  | @ -881,6 +881,7 @@ void PrintConfigDef::init_fff_params() | |||
|     def->enum_values.push_back("hilbertcurve"); | ||||
|     def->enum_values.push_back("archimedeanchords"); | ||||
|     def->enum_values.push_back("octagramspiral"); | ||||
|     def->enum_values.push_back("adaptivecubic"); | ||||
|     def->enum_labels.push_back(L("Rectilinear")); | ||||
|     def->enum_labels.push_back(L("Grid")); | ||||
|     def->enum_labels.push_back(L("Triangles")); | ||||
|  | @ -894,6 +895,7 @@ void PrintConfigDef::init_fff_params() | |||
|     def->enum_labels.push_back(L("Hilbert Curve")); | ||||
|     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->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, ipCount, | ||||
|     ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipAdaptiveCubic, ipCount, | ||||
| }; | ||||
| 
 | ||||
| enum class IroningType { | ||||
|  | @ -139,6 +139,7 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<InfillPattern>::g | |||
|         keys_map["hilbertcurve"]        = ipHilbertCurve; | ||||
|         keys_map["archimedeanchords"]   = ipArchimedeanChords; | ||||
|         keys_map["octagramspiral"]      = ipOctagramSpiral; | ||||
|         keys_map["adaptivecubic"]       = ipAdaptiveCubic; | ||||
|     } | ||||
|     return keys_map; | ||||
| } | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ | |||
| #include "Surface.hpp" | ||||
| #include "Slicing.hpp" | ||||
| #include "Utils.hpp" | ||||
| #include "AABBTreeIndirect.hpp" | ||||
| #include "Fill/FillAdaptive.hpp" | ||||
| 
 | ||||
| #include <utility> | ||||
| #include <boost/log/trivial.hpp> | ||||
|  | @ -369,13 +371,15 @@ void PrintObject::infill() | |||
|     this->prepare_infill(); | ||||
| 
 | ||||
|     if (this->set_started(posInfill)) { | ||||
|         std::unique_ptr<FillAdaptive_Internal::Octree> 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](const tbb::blocked_range<size_t>& range) { | ||||
|             [this, &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(); | ||||
|                     m_layers[layer_idx]->make_fills(octree.get()); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | @ -428,6 +432,48 @@ void PrintObject::generate_support_material() | |||
|     } | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<FillAdaptive_Internal::Octree> PrintObject::prepare_adaptive_infill_data() | ||||
| { | ||||
|     float fill_density = 0; | ||||
|     float infill_extrusion_width = 0; | ||||
| 
 | ||||
|     // Compute the average of above parameters over all layers
 | ||||
|     for (size_t layer_idx = 0; layer_idx < this->m_layers.size(); ++layer_idx) | ||||
|     { | ||||
|         for (size_t region_id = 0; region_id < this->m_layers[layer_idx]->m_regions.size(); ++region_id) | ||||
|         { | ||||
|             LayerRegion *layerm = this->m_layers[layer_idx]->m_regions[region_id]; | ||||
| 
 | ||||
|             // Check if region_id is used for this layer
 | ||||
|             if(!layerm->fill_surfaces.surfaces.empty()) { | ||||
|                 const PrintRegionConfig ®ion_config = layerm->region()->config(); | ||||
| 
 | ||||
|                 fill_density += region_config.fill_density; | ||||
|                 infill_extrusion_width += region_config.infill_extrusion_width; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fill_density /= this->m_layers.size(); | ||||
|     infill_extrusion_width /= this->m_layers.size(); | ||||
| 
 | ||||
|     if(fill_density <= 0 || infill_extrusion_width <= 0) | ||||
|     { | ||||
|         return std::unique_ptr<FillAdaptive_Internal::Octree>{}; | ||||
|     } | ||||
| 
 | ||||
|     coordf_t line_spacing = infill_extrusion_width / ((fill_density / 100.0f) * 0.333333333f); | ||||
| 
 | ||||
|     TriangleMesh mesh = this->model_object()->raw_mesh(); | ||||
|     mesh.transform(m_trafo, true); | ||||
|     // Apply XY shift
 | ||||
|     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, line_spacing, mesh_origin); | ||||
| } | ||||
| 
 | ||||
| void PrintObject::clear_layers() | ||||
| { | ||||
|     for (Layer *l : m_layers) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 enricoturri1966
						enricoturri1966