forked from SoftFever/OrcaSlicer
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Port of Cura's multi-material interlocking (SoftFever#5775)
* Init port of Cura's MM interlocking * Refactor a bit * Fix crash when bottom surface is multi-color * Fix crash when boundary avoidance is 0 * Add config --------- Co-authored-by: SoftFever <softfeverever@gmail.com>
- Loading branch information
Showing
15 changed files
with
1,029 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
// Copyright (c) 2022 Ultimaker B.V. | ||
// CuraEngine is released under the terms of the AGPLv3 or higher. | ||
|
||
#ifndef INTERLOCKING_GENERATOR_HPP | ||
#define INTERLOCKING_GENERATOR_HPP | ||
|
||
#include "../Print.hpp" | ||
#include "VoxelUtils.hpp" | ||
|
||
namespace Slic3r { | ||
|
||
/*! | ||
* Class for generating an interlocking structure between two adjacent models of a different extruder. | ||
* | ||
* The structure consists of horizontal beams of the two materials interlaced. | ||
* In the z direction the direction of these beams is alternated with 90*. | ||
* | ||
* Example with two materials # and O | ||
* Even beams: Odd beams: | ||
* ###### ##OO##OO | ||
* OOOOOO ##OO##OO | ||
* ###### ##OO##OO | ||
* OOOOOO ##OO##OO | ||
* | ||
* One material of a single cell of the structure looks like this: | ||
* .-*-. | ||
* .-* *-. | ||
* |*-. *-. | ||
* | *-. *-. | ||
* .-* *-. *-. *-. | ||
* .-* *-. *-. .-*| | ||
* .-* .-* *-. *-.-* | | ||
* |*-. .-* .-* *-. | .-* | ||
* | *-.-* .-* *-|-* | ||
* *-. | .-* | ||
* *-|-* | ||
* | ||
* We set up a voxel grid of (2*beam_w,2*beam_w,2*beam_h) and mark all the voxels which contain both meshes. | ||
* We then remove all voxels which also contain air, so that the interlocking pattern will not be visible from the outside. | ||
* We then generate and combine the polygons for each voxel and apply those areas to the outlines ofthe meshes. | ||
*/ | ||
class InterlockingGenerator | ||
{ | ||
public: | ||
/*! | ||
* Generate an interlocking structure between each two adjacent meshes. | ||
*/ | ||
static void generate_interlocking_structure(PrintObject* print_object); | ||
|
||
private: | ||
/*! | ||
* Generate an interlocking structure between two meshes | ||
*/ | ||
void generateInterlockingStructure() const; | ||
|
||
/*! | ||
* Private class for storing some variables used in the computation of the interlocking structure between two meshes. | ||
* \param region_a_index The first region | ||
* \param region_b_index The second region | ||
* \param rotation The angle by which to rotate the interlocking pattern | ||
* \param cell_size The size of a voxel cell in (coord_t, coord_t, layer_count) | ||
* \param beam_layer_count The number of layers for the height of the beams | ||
* \param interface_dilation The thicknening kernel for the interface | ||
* \param air_dilation The thickening kernel applied to air so that cells near the outside of the model won't be generated | ||
* \param air_filtering Whether to fully remove all of the interlocking cells which would be visible on the outside (i.e. touching air). | ||
* If no air filtering then those cells will be cut off in the middle of a beam. | ||
*/ | ||
InterlockingGenerator(PrintObject& print_object, | ||
const size_t region_a_index, | ||
const size_t region_b_index, | ||
const coord_t beam_width, | ||
const coord_t boundary_avoidance, | ||
const float rotation, | ||
const Vec3crd& cell_size, | ||
const coord_t beam_layer_count, | ||
const DilationKernel& interface_dilation, | ||
const DilationKernel& air_dilation, | ||
const bool air_filtering) | ||
: print_object(print_object) | ||
, region_a_index(region_a_index) | ||
, region_b_index(region_b_index) | ||
, beam_width(beam_width) | ||
, boundary_avoidance(boundary_avoidance) | ||
, vu(cell_size) | ||
, rotation(rotation) | ||
, cell_size(cell_size) | ||
, beam_layer_count(beam_layer_count) | ||
, interface_dilation(interface_dilation) | ||
, air_dilation(air_dilation) | ||
, air_filtering(air_filtering) | ||
{} | ||
|
||
/*! Given two polygons, return the parts that border on air, and grow 'perpendicular' up to 'detect' distance. | ||
* | ||
* \param a The first polygon. | ||
* \param b The second polygon. | ||
* \param detec The expand distance. (Not equal to offset, but a series of small offsets and differences). | ||
* \return A pair of polygons that repressent the 'borders' of a and b, but expanded 'perpendicularly'. | ||
*/ | ||
std::pair<ExPolygons, ExPolygons> growBorderAreasPerpendicular(const ExPolygons& a, const ExPolygons& b, const coord_t& detect) const; | ||
|
||
/*! Special handling for thin strips of material. | ||
* | ||
* Expand the meshes into each other where they need it, namely when a thin strip of material needs to be attached. | ||
* \param has_all_meshes Only do this special handling if there's actually microstructure nearby that needs to be adhered to. | ||
*/ | ||
void handleThinAreas(const std::unordered_set<GridPoint3>& has_all_meshes) const; | ||
|
||
/*! | ||
* Compute the voxels overlapping with the shell of both models. | ||
* This includes the walls, but also top/bottom skin. | ||
* | ||
* \param kernel The dilation kernel to give the returned voxel shell more thickness | ||
* \return The shell voxels for mesh a and those for mesh b | ||
*/ | ||
std::vector<std::unordered_set<GridPoint3>> getShellVoxels(const DilationKernel& kernel) const; | ||
|
||
/*! | ||
* Compute the voxels overlapping with the shell of some layers. | ||
* This includes the walls, but also top/bottom skin. | ||
* | ||
* \param layers The layer outlines for which to compute the shell voxels | ||
* \param kernel The dilation kernel to give the returned voxel shell more thickness | ||
* \param[out] cells The output cells which elong to the shell | ||
*/ | ||
void addBoundaryCells(const std::vector<ExPolygons>& layers, const DilationKernel& kernel, std::unordered_set<GridPoint3>& cells) const; | ||
|
||
/*! | ||
* Compute the regions occupied by both models. | ||
* | ||
* A morphological close is performed so that we don't register small gaps between the two models as being separate. | ||
* \return layer_regions The computed layer regions | ||
*/ | ||
std::vector<ExPolygons> computeUnionedVolumeRegions() const; | ||
|
||
/*! | ||
* Generate the polygons for the beams of a single cell | ||
* \return cell_area_per_mesh_per_layer The output polygons for each beam | ||
*/ | ||
std::vector<std::vector<ExPolygons>> generateMicrostructure() const; | ||
|
||
/*! | ||
* Change the outlines of the meshes with the computed interlocking structure. | ||
* | ||
* \param cells The cells where we want to apply the interlocking structure. | ||
* \param layer_regions The total volume of the two meshes combined (and small gaps closed) | ||
*/ | ||
void applyMicrostructureToOutlines(const std::unordered_set<GridPoint3>& cells, const std::vector<ExPolygons>& layer_regions) const; | ||
|
||
static const coord_t ignored_gap_ = 100u; //!< Distance between models to be considered next to each other so that an interlocking structure will be generated there | ||
|
||
PrintObject& print_object; | ||
const size_t region_a_index; | ||
const size_t region_b_index; | ||
const coord_t beam_width; | ||
const coord_t boundary_avoidance; | ||
|
||
const VoxelUtils vu; | ||
|
||
const float rotation; | ||
const Vec3crd cell_size; | ||
const coord_t beam_layer_count; | ||
const DilationKernel interface_dilation; | ||
const DilationKernel air_dilation; | ||
// Whether to fully remove all of the interlocking cells which would be visible on the outside. If no air filtering then those cells | ||
// will be cut off midway in a beam. | ||
const bool air_filtering; | ||
}; | ||
|
||
} // namespace Slic3r | ||
|
||
#endif // INTERLOCKING_GENERATOR_HPP |
Oops, something went wrong.