1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
#ifndef slic3r_Geometry_MedialAxis_hpp_
#define slic3r_Geometry_MedialAxis_hpp_
#include "../libslic3r.h"
#include "Voronoi.hpp"
#include "../ExPolygon.hpp"
#include "../Geometry.hpp"
#include "../ExtrusionEntityCollection.hpp"
#include "../Flow.hpp"
#include <vector>
using boost::polygon::voronoi_builder;
using boost::polygon::voronoi_diagram;
namespace Slic3r { namespace Geometry {
#if 0 //PS
class MedialAxis {
public:
Lines lines;
const ExPolygon* expolygon;
double max_width;
double min_width;
MedialAxis(double _max_width, double _min_width, const ExPolygon* _expolygon = NULL)
: expolygon(_expolygon), max_width(_max_width), min_width(_min_width) {};
void build(ThickPolylines* polylines);
void build(Polylines* polylines);
private:
using VD = VoronoiDiagram;
VD vd;
std::set<const VD::edge_type*> edges, valid_edges;
std::map<const VD::edge_type*, std::pair<coordf_t,coordf_t> > thickness;
void process_edge_neighbors(const VD::edge_type* edge, ThickPolyline* polyline);
bool validate_edge(const VD::edge_type* edge);
const Line& retrieve_segment(const VD::cell_type* cell) const;
const Point& retrieve_endpoint(const VD::cell_type* cell) const;
};
#endif
//SuSi
/// This class is used to create single-line extrusion pattern with variable width to cover a ExPolygon.
/// The ends can enter a boundary area if neded, and can have a taper at each end.
/// The constructor initialize the mandatory variable.
/// you must use the setter to add the opptional settings before calling build().
///
class MedialAxis {
public:
//static int staticid;
//int id;
/// _expolygon: the polygon to fill
/// _max_width : maximum width of the extrusion. _expolygon shouldn't have a spot where a circle diameter is higher than that (or almost).
/// _min_width : minimum width of the extrusion, every spot where a circle diameter is lower than that will be ignored (unless it's the tip of the extrusion)
/// _height: height of the extrusion, used to compute the difference between width and spacing.
MedialAxis(const ExPolygon& _expolygon, const coord_t _max_width, const coord_t _min_width, const coord_t _height)
: surface(_expolygon), max_width(_max_width), min_width(_min_width), height(_height),
bounds(&_expolygon), nozzle_diameter(_min_width), taper_size(0), stop_at_min_width(true), resolution(12500), min_length(_max_width) {/*id= staticid;staticid++;*/
};
/// create the polylines_out collection of variable-width polyline to extrude.
void build(ThickPolylines& polylines_out);
/// You shouldn't use this method as it doesn't give you the variable width. Can be useful for debugging.
void build(Polylines& polylines);
/// optional parameter: anchor area in which the extrusion should extends into. Default : expolygon (no bound)
MedialAxis& use_bounds(const ExPolygon& _bounds) { this->bounds = &_bounds; return *this; }
/// optional parameter: the real minimum width : it will grow the width of every extrusion that has a width lower than that. Default : min_width (same min)
MedialAxis& use_min_real_width(const coord_t nozzle_diameter) { this->nozzle_diameter = nozzle_diameter; return *this; }
/// optional parameter: create a taper of this length at each end (inside a bound or not). Default : 0 (no taper)
MedialAxis& use_tapers(const coord_t taper_size) { this->taper_size = taper_size; return *this; }
/// optional parameter: if true, the extension inside the bounds can be cut if the width is too small. Default : true
MedialAxis& set_stop_at_min_width(const bool stop_at_min_width) { this->stop_at_min_width = stop_at_min_width; return *this; }
MedialAxis& set_min_length(const coord_t min_length) { this->min_length = min_length; return *this; }
private:
/// input polygon to fill
const ExPolygon& surface;
/// the copied expolygon from surface, it's modified in build() to simplify it. It's then used to create the voronoi diagram.
ExPolygon expolygon;
const ExPolygon* bounds;
/// maximum width of the extrusion. _expolygon shouldn't have a spot where a circle diameter is higher than that (or almost).
const coord_t max_width;
/// minimum width of the extrusion, every spot where a circle diameter is lower than that will be ignored (unless it's the tip of the extrusion)
const coord_t min_width;
/// minimum length of continuous segments (may cross a crossing)
coord_t min_length;
/// resolution for simplifuing and stuff like that
const coord_t resolution;
/// height of the extrusion, used to compute the diufference between width and spacing.
const coord_t height;
/// Used to compute the real minimum width we can extrude. if != min_width, it activate grow_to_nozzle_diameter().
coord_t nozzle_diameter;
/// if != , it activates taper_ends(). Can use nozzle_diameter.
coord_t taper_size;
//if true, remove_too_* can shorten the bits created by extends_line.
bool stop_at_min_width;
//voronoi stuff
class VD : public voronoi_diagram<double> {
public:
typedef double coord_type;
typedef boost::polygon::point_data<coordinate_type> point_type;
typedef boost::polygon::segment_data<coordinate_type> segment_type;
typedef boost::polygon::rectangle_data<coordinate_type> rect_type;
};
void process_edge_neighbors(const VD::edge_type* edge, ThickPolyline* polyline, std::set<const VD::edge_type*>& edges, std::set<const VD::edge_type*>& valid_edges, std::map<const VD::edge_type*, std::pair<coordf_t, coordf_t> >& thickness);
bool validate_edge(const VD::edge_type* edge, Lines& lines, std::map<const VD::edge_type*, std::pair<coordf_t, coordf_t> >& thickness);
const Line& retrieve_segment(const VD::cell_type* cell, Lines& lines) const;
const Point& retrieve_endpoint(const VD::cell_type* cell, Lines& lines) const;
void polyline_from_voronoi(const Lines& voronoi_edges, ThickPolylines* polylines_out);
// functions called by build:
/// create a simplied version of surface, store it in expolygon
void simplify_polygon_frontier();
/// fusion little polylines created (by voronoi) on the external side of a curve inside the main polyline.
void fusion_curve(ThickPolylines& pp);
/// fusion polylines created by voronoi, where needed.
void main_fusion(ThickPolylines& pp);
/// like fusion_curve but for sharp angles like a square corner.
void fusion_corners(ThickPolylines& pp);
/// extends the polylines inside bounds, use extends_line on both end
void extends_line_both_side(ThickPolylines& pp);
/// extends the polylines inside bounds (anchors)
void extends_line(ThickPolyline& polyline, const ExPolygons& anchors, const coord_t join_width);
/// remove too thin bits at start & end of polylines
void remove_too_thin_extrusion(ThickPolylines& pp);
/// when we have a too small polyline, try to see if we can't concatenate it at a crossing to keep it.
void concatenate_small_polylines(ThickPolylines& pp);
/// instead of keeping polyline split at each corssing, we try to create long strait polylines that can cross each other.
void concatenate_polylines_with_crossing(ThickPolylines& pp);
/// remove bits around points that are too thin (can be inside the polyline)
void remove_too_thin_points(ThickPolylines& pp);
/// delete polylines that are too short (below the this->min_length)
void remove_too_short_polylines(ThickPolylines& pp);
/// be sure we didn't try to push more plastic than the volume defined by surface * height can receive. If overextruded, reduce all widths by the correct %.
void ensure_not_overextrude(ThickPolylines& pp);
/// if nozzle_diameter > min_width, grow bits that are < width(nozzle_diameter) to width(nozzle_diameter) (don't activate that for gapfill)
void grow_to_nozzle_diameter(ThickPolylines& pp, const ExPolygons& anchors);
/// taper the ends of polylines (don't activate that for gapfill)
void taper_ends(ThickPolylines& pp);
//cleaning method
void check_width(ThickPolylines& pp, coord_t max_width, std::string msg);
//removing small extrusion that won't be useful and will harm print. A bit like fusion_corners but more lenient and with just del.
void remove_bits(ThickPolylines& pp);
};
/// create a ExtrusionEntitiesPtr from ThickPolylines, discretizing the variable width into little sections (of 4*SCALED_RESOLUTION length) where needed. Please delete all ptr if not used.
ExtrusionEntitiesPtr thin_variable_width(const ThickPolylines& polylines, const ExtrusionRole role, const Flow &flow, const coord_t resolution_internal);
} } // namespace Slicer::Geometry
#endif // slic3r_Geometry_MedialAxis_hpp_
|