mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 05:26:02 +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 "ClipperUtils.hpp"
|
||||||
#include "ExtrusionEntityCollection.hpp"
|
#include "ExtrusionEntityCollection.hpp"
|
||||||
#include "ShortestPath.hpp"
|
#include "ShortestPath.hpp"
|
||||||
|
#include "Surface.hpp"
|
||||||
#include "clipper/clipper_z.hpp"
|
#include "clipper/clipper_z.hpp"
|
||||||
|
#include "SVG.hpp"
|
||||||
|
#include "Utils.hpp"
|
||||||
|
|
||||||
#include "Arachne/WallToolPaths.hpp"
|
#include "Arachne/WallToolPaths.hpp"
|
||||||
#include "Arachne/utils/ExtrusionLine.hpp"
|
#include "Arachne/utils/ExtrusionLine.hpp"
|
||||||
@ -10,6 +13,7 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
//#define ARACHNE_DEBUG
|
//#define ARACHNE_DEBUG
|
||||||
@ -567,6 +571,75 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator &p
|
|||||||
return extrusion_coll;
|
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
|
#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)
|
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);
|
ex.simplify_p(m_scaled_resolution, &pp);
|
||||||
// collapse too narrow infill areas
|
// collapse too narrow infill areas
|
||||||
const auto min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
const auto min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
||||||
// append infill areas to fill_surfaces
|
// append infill areas to fill_surfaces
|
||||||
this->fill_surfaces->append(
|
ExPolygons infill_areas =
|
||||||
offset2_ex(
|
offset2_ex(
|
||||||
union_ex(pp),
|
union_ex(pp),
|
||||||
float(- min_perimeter_infill_spacing / 2.),
|
float(- min_perimeter_infill_spacing / 2.),
|
||||||
float(inset + min_perimeter_infill_spacing / 2.)),
|
float(inset + min_perimeter_infill_spacing / 2.));
|
||||||
stInternal);
|
|
||||||
|
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);
|
ex.simplify_p(m_scaled_resolution, &pp);
|
||||||
// collapse too narrow infill areas
|
// collapse too narrow infill areas
|
||||||
coord_t min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
coord_t min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
||||||
// append infill areas to fill_surfaces
|
// append infill areas to fill_surfaces
|
||||||
this->fill_surfaces->append(
|
ExPolygons infill_areas =
|
||||||
offset2_ex(
|
offset2_ex(
|
||||||
union_ex(pp),
|
union_ex(pp),
|
||||||
float(- inset - min_perimeter_infill_spacing / 2.),
|
float(- inset - min_perimeter_infill_spacing / 2.),
|
||||||
float(min_perimeter_infill_spacing / 2.)),
|
float(min_perimeter_infill_spacing / 2.));
|
||||||
stInternal);
|
|
||||||
|
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
|
} // for each island
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user