mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 01:15:53 +08:00
simple example of a function which generates extrusions on overhangs
This commit is contained in:
parent
ec2f533e3a
commit
78f8fa5556
@ -2,7 +2,10 @@
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "ExtrusionEntityCollection.hpp"
|
||||
#include "ShortestPath.hpp"
|
||||
#include "Surface.hpp"
|
||||
#include "clipper/clipper_z.hpp"
|
||||
#include "SVG.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include "Arachne/WallToolPaths.hpp"
|
||||
#include "Arachne/utils/ExtrusionLine.hpp"
|
||||
@ -10,6 +13,7 @@
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
//#define ARACHNE_DEBUG
|
||||
@ -567,6 +571,75 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator &p
|
||||
return extrusion_coll;
|
||||
}
|
||||
|
||||
// Return new generated extrusions and polygons filled by those extrusions
|
||||
std::tuple<std::vector<ExtrusionPaths>, Polygons> generate_structure_on_overhangs(ExPolygons infill_area,
|
||||
const Polygons &lower_slices_polygons,
|
||||
const Flow &overhang_flow,
|
||||
double scaled_resolution,
|
||||
const PrintObjectConfig &object_config,
|
||||
const PrintConfig &print_config)
|
||||
{
|
||||
//This function will generate perimeters over overhangs. It is a simple demo to get you started
|
||||
|
||||
// infill area is already without the perimeters.
|
||||
// The diff operation below produces polygons of overhangs ( we take the area to be filled, and remove the parts supported by lower level.)
|
||||
ExPolygons overhangs = diff_ex(infill_area, lower_slices_polygons);
|
||||
|
||||
//ExPolygon is a contour polygon that also stores its holes. We need it here so that we can later iterate over all connected overhang areas and fill them
|
||||
// while respecting the holes of the object.
|
||||
// Note that you can also use Polygon structure, holes are still recognized by clockwise orientation - but you will loose the information about which
|
||||
// contour contains which hole
|
||||
|
||||
//NOTE that all points have scaled values - which means they are in nanometers. If you debug print them, you will get quite big numbers.
|
||||
// I advise to use doubles when computing something so that you avoid overflow issues.
|
||||
// There are conversion functions scaled() and unscaled() to convert between millimters and nanometers
|
||||
|
||||
//example of debug export file. The svg image will be written into the "out" folder of your workspace directory (from where you run the program),
|
||||
// you have to create the "out" directory first to actually get the images
|
||||
#if 1
|
||||
{
|
||||
BoundingBox bbox = get_extents(union_(to_polygons(infill_area), lower_slices_polygons));
|
||||
bbox.offset(scale_(1.));
|
||||
::Slic3r::SVG svg(debug_out_path(("debug_svg"+ std::to_string(std::rand())).c_str()).c_str(), bbox);
|
||||
for (const Line &line : to_lines(infill_area)) svg.draw(line, "red", scale_(0.2));
|
||||
for (const Line &line : to_lines(lower_slices_polygons)) svg.draw(line, "green", scale_(0.2));
|
||||
svg.Close();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<ExtrusionPaths> perims; // overhang region -> perimeter shells ( so that each overhang region is finished first before moving to next)
|
||||
for (const ExPolygon &overhang_area : overhangs) {
|
||||
|
||||
perims.emplace_back(); // new overhang area
|
||||
ExtrusionPaths &overhang_region = perims.back(); // perimeters in the new overhang area
|
||||
|
||||
Polygons perimeter_polygon = offset(overhang_area, -overhang_flow.scaled_spacing() * 0.5); // the central axis of the generated extrusion should be
|
||||
// one half away from the boundary of the polygon to fill, otherwise we would not fit the model properly
|
||||
|
||||
// fill the overhang with perimeters until it is full
|
||||
// We are generating the perimeters from outside to inside
|
||||
while (!perimeter_polygon.empty()) {
|
||||
|
||||
// prepare next perimeter lines
|
||||
Polylines perimeter_polyline = to_polylines(perimeter_polygon); //convert the polygon to polylines
|
||||
|
||||
// make extrusions from polylines (by adding flow params) and append them to this overhang region
|
||||
extrusion_paths_append(overhang_region, perimeter_polyline,
|
||||
erOverhangPerimeter,
|
||||
overhang_flow.mm3_per_mm(),
|
||||
overhang_flow.width(),
|
||||
overhang_flow.height());
|
||||
|
||||
perimeter_polygon = shrink(perimeter_polygon, overhang_flow.scaled_spacing()); // Shrink the perimeter polygon by full width, to get the central axis
|
||||
// of the next perimeter extrusion
|
||||
}
|
||||
}
|
||||
|
||||
// return the generated perimeters and overhang polygons filled by those perimeters.
|
||||
return {perims, to_polygons(overhangs)};
|
||||
}
|
||||
|
||||
|
||||
#ifdef ARACHNE_DEBUG
|
||||
static void export_perimeters_to_svg(const std::string &path, const Polygons &contours, const std::vector<Arachne::VariableWidthLines> &perimeters, const ExPolygons &infill_area)
|
||||
{
|
||||
@ -802,13 +875,31 @@ void PerimeterGenerator::process_arachne()
|
||||
ex.simplify_p(m_scaled_resolution, &pp);
|
||||
// collapse too narrow infill areas
|
||||
const auto min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
||||
// append infill areas to fill_surfaces
|
||||
this->fill_surfaces->append(
|
||||
offset2_ex(
|
||||
union_ex(pp),
|
||||
float(- min_perimeter_infill_spacing / 2.),
|
||||
float(inset + min_perimeter_infill_spacing / 2.)),
|
||||
stInternal);
|
||||
// append infill areas to fill_surfaces
|
||||
ExPolygons infill_areas =
|
||||
offset2_ex(
|
||||
union_ex(pp),
|
||||
float(- min_perimeter_infill_spacing / 2.),
|
||||
float(inset + min_perimeter_infill_spacing / 2.));
|
||||
|
||||
if (lower_slices != nullptr && config->overhangs &&
|
||||
config->perimeters > 0 && layer_id > object_config->raft_layers) {
|
||||
// Generate extra perimeters on overhang areas, and cut them to these parts only, to save print time and material
|
||||
auto [extra_perimeters, filled_area] = generate_structure_on_overhangs(infill_areas,
|
||||
this->lower_slices_polygons(),
|
||||
this->overhang_flow, this->m_scaled_resolution,
|
||||
*this->object_config, *this->print_config);
|
||||
if (!extra_perimeters.empty()) {
|
||||
ExtrusionEntityCollection &this_islands_perimeters = static_cast<ExtrusionEntityCollection&>(*loops->entities.back());
|
||||
ExtrusionEntitiesPtr old_entities;
|
||||
old_entities.swap(this_islands_perimeters.entities);
|
||||
for (ExtrusionPaths &paths : extra_perimeters)
|
||||
this_islands_perimeters.append(std::move(paths));
|
||||
append(this_islands_perimeters.entities, old_entities);
|
||||
infill_areas = diff_ex(infill_areas, filled_area);
|
||||
}
|
||||
}
|
||||
fill_surfaces->append(infill_areas, stInternal);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1073,13 +1164,31 @@ void PerimeterGenerator::process_classic()
|
||||
ex.simplify_p(m_scaled_resolution, &pp);
|
||||
// collapse too narrow infill areas
|
||||
coord_t min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
||||
// append infill areas to fill_surfaces
|
||||
this->fill_surfaces->append(
|
||||
// append infill areas to fill_surfaces
|
||||
ExPolygons infill_areas =
|
||||
offset2_ex(
|
||||
union_ex(pp),
|
||||
float(- inset - min_perimeter_infill_spacing / 2.),
|
||||
float(min_perimeter_infill_spacing / 2.)),
|
||||
stInternal);
|
||||
float(min_perimeter_infill_spacing / 2.));
|
||||
|
||||
if (lower_slices != nullptr && config->overhangs &&
|
||||
config->perimeters > 0 && layer_id > object_config->raft_layers) {
|
||||
// Generate extra perimeters on overhang areas, and cut them to these parts only, to save print time and material
|
||||
auto [extra_perimeters, filled_area] = generate_structure_on_overhangs(infill_areas,
|
||||
this->lower_slices_polygons(),
|
||||
this->overhang_flow, this->m_scaled_resolution,
|
||||
*this->object_config, *this->print_config);
|
||||
if (!extra_perimeters.empty()) {
|
||||
ExtrusionEntityCollection &this_islands_perimeters = static_cast<ExtrusionEntityCollection&>(*loops->entities.back());
|
||||
ExtrusionEntitiesPtr old_entities;
|
||||
old_entities.swap(this_islands_perimeters.entities);
|
||||
for (ExtrusionPaths &paths : extra_perimeters)
|
||||
this_islands_perimeters.append(std::move(paths));
|
||||
append(this_islands_perimeters.entities, old_entities);
|
||||
infill_areas = diff_ex(infill_areas, filled_area);
|
||||
}
|
||||
}
|
||||
fill_surfaces->append(infill_areas, stInternal);
|
||||
} // for each island
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user