OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::Triangulation Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/Triangulation.hpp>

Public Types

using HalfEdge = std::pair<uint32_t, uint32_t>
using HalfEdges = std::vector<HalfEdge>
using Indices = std::vector<Vec3i32>
using Changes = std::vector<uint32_t>

Public Member Functions

 Triangulation ()=delete

Static Public Member Functions

static Indices triangulate (const Points &points, const HalfEdges &half_edges)
 Connect points by triangulation to create filled surface by triangles Input points have to be unique Inspiration for make unique points is Emboss::dilate_to_unique_points.
static Indices triangulate (const Polygon &polygon)
static Indices triangulate (const Polygons &polygons)
static Indices triangulate (const ExPolygon &expolygon)
static Indices triangulate (const ExPolygons &expolygons)
static Changes create_changes (const Points &points, const Points &duplicits)
 Create conversion map from original index into new with respect of duplicit point.
static Indices triangulate (const ExPolygons &expolygons, const Points &points)
 Triangulation for expolygons, speed up when points are already collected NOTE: Not working properly for ExPolygons with multiple point on same coordinate You should check it by "collect_changes".
static Indices triangulate (const ExPolygons &expolygons, const Points &points, const Changes &changes)
 Triangulation for expolygons containing multiple points with same coordinate.

Detailed Description

Member Typedef Documentation

◆ Changes

using Slic3r::Triangulation::Changes = std::vector<uint32_t>

◆ HalfEdge

using Slic3r::Triangulation::HalfEdge = std::pair<uint32_t, uint32_t>

◆ HalfEdges

◆ Indices

Constructor & Destructor Documentation

◆ Triangulation()

Slic3r::Triangulation::Triangulation ( )
delete

Member Function Documentation

◆ create_changes()

Triangulation::Changes Triangulation::create_changes ( const Points & points,
const Points & duplicits )
static

Create conversion map from original index into new with respect of duplicit point.

Parameters
pointsinput set of points
duplicitsduplicit points collected from points
Returns
Conversion map for point index
322{
323 assert(!duplicits.empty());
324 assert(duplicits.size() < points.size()/2);
325 std::vector<uint32_t> duplicit_indices(duplicits.size(), std::numeric_limits<uint32_t>::max());
326 Changes changes;
327 changes.reserve(points.size());
328 uint32_t index = 0;
329 for (const Point &p: points) {
330 auto it = std::lower_bound(duplicits.begin(), duplicits.end(), p);
331 if (it == duplicits.end() || *it != p) {
332 changes.push_back(index);
333 ++index;
334 continue;
335 }
336 uint32_t &d_index = duplicit_indices[it - duplicits.begin()];
337 if (d_index == std::numeric_limits<uint32_t>::max()) {
338 d_index = index;
339 changes.push_back(index);
340 ++index;
341 } else {
342 changes.push_back(d_index);
343 }
344 }
345 return changes;
346}
std::vector< uint32_t > Changes
Definition Triangulation.hpp:42

Referenced by anonymous_namespace{Emboss.cpp}::polygons2model_duplicit(), and triangulate().

Here is the caller graph for this function:

◆ triangulate() [1/7]

Triangulation::Indices Triangulation::triangulate ( const ExPolygon & expolygon)
static
255 {
256 ExPolygons expolys({expolygon});
257 return triangulate(expolys);
258}
static Indices triangulate(const Points &points, const HalfEdges &half_edges)
Connect points by triangulation to create filled surface by triangles Input points have to be unique ...
Definition Triangulation.cpp:103
std::vector< ExPolygon > ExPolygons
Definition ExPolygon.hpp:20

References triangulate().

Here is the call graph for this function:

◆ triangulate() [2/7]

Triangulation::Indices Triangulation::triangulate ( const ExPolygons & expolygons)
static
260 {
261 Points pts = to_points(expolygons);
262 Points d_pts = collect_duplicates(pts);
263 if (d_pts.empty()) return triangulate(expolygons, pts);
264
265 Changes changes = create_changes(pts, d_pts);
266 Indices indices = triangulate(expolygons, pts, changes);
267 // reverse map for changes
268 Changes changes2(changes.size(), std::numeric_limits<uint32_t>::max());
269 for (size_t i = 0; i < changes.size(); ++i)
270 changes2[changes[i]] = i;
271
272 // convert indices into expolygons indicies
273 for (Vec3i32 &t : indices)
274 for (size_t ti = 0; ti < 3; ti++) t[ti] = changes2[t[ti]];
275
276 return indices;
277}
std::vector< Vec3i32 > Indices
Definition Triangulation.hpp:22
static Changes create_changes(const Points &points, const Points &duplicits)
Create conversion map from original index into new with respect of duplicit point.
Definition Triangulation.cpp:321
Points collect_duplicates(Points pts)
Definition Point.cpp:147
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:73
Eigen::Matrix< int32_t, 3, 1, Eigen::DontAlign > Vec3i32
Definition Point.hpp:59
Points to_points(const ExPolygons &src)
Definition ExPolygon.hpp:222

References Slic3r::collect_duplicates(), create_changes(), Slic3r::to_points(), and triangulate().

Here is the call graph for this function:

◆ triangulate() [3/7]

Triangulation::Indices Triangulation::triangulate ( const ExPolygons & expolygons,
const Points & points )
static

Triangulation for expolygons, speed up when points are already collected NOTE: Not working properly for ExPolygons with multiple point on same coordinate You should check it by "collect_changes".

Parameters
expolygonsInput shape to triangulation - define edges
pointsPoints from expolygons
Returns
Triangle indices
280{
281 assert(count_points(expolygons) == points.size());
282 // when contain duplicit coordinate in points will not work properly
283 assert(collect_duplicates(points).empty());
284
285 HalfEdges edges;
286 edges.reserve(points.size());
287 uint32_t offset = 0;
288 for (const ExPolygon &expolygon : expolygons) {
289 priv::insert_edges(edges, offset, expolygon.contour);
290 for (const Polygon &hole : expolygon.holes)
291 priv::insert_edges(edges, offset, hole);
292 }
293 std::sort(edges.begin(), edges.end());
294 return triangulate(points, edges);
295}
std::vector< HalfEdge > HalfEdges
Definition Triangulation.hpp:21
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:582
bool empty(const BoundingBoxBase< PointType, PointsType > &bb)
Definition BoundingBox.hpp:273
size_t count_points(const ExPolygons &expolys)
Definition ExPolygon.hpp:95
void insert_edges(Triangulation::HalfEdges &edges, uint32_t &offset, const Polygon &polygon, const Triangulation::Changes &changes)
Definition Triangulation.cpp:28

References Slic3r::collect_duplicates(), Slic3r::count_points(), Slic3r::empty(), priv::insert_edges(), Slic3r::offset(), and triangulate().

Here is the call graph for this function:

◆ triangulate() [4/7]

Triangulation::Indices Triangulation::triangulate ( const ExPolygons & expolygons,
const Points & points,
const Changes & changes )
static

Triangulation for expolygons containing multiple points with same coordinate.

Parameters
expolygonsInput shape to triangulation - define edge
pointsPoints from expolygons
changesChanges swap for indicies into points
Returns
Triangle indices
298{
299 assert(!points.empty());
300 assert(count_points(expolygons) == points.size());
301 assert(changes.size() == points.size());
302 // IMPROVE: search from end and somehow distiquish that value is not a change
303 uint32_t count_points = *std::max_element(changes.begin(), changes.end())+1;
304 Points pts(count_points);
305 for (size_t i = 0; i < changes.size(); i++)
306 pts[changes[i]] = points[i];
307
308 HalfEdges edges;
309 edges.reserve(points.size());
310 uint32_t offset = 0;
311 for (const ExPolygon &expolygon : expolygons) {
312 priv::insert_edges(edges, offset, expolygon.contour, changes);
313 for (const Polygon &hole : expolygon.holes)
314 priv::insert_edges(edges, offset, hole, changes);
315 }
316
317 std::sort(edges.begin(), edges.end());
318 return triangulate(pts, edges);
319}

References Slic3r::count_points(), priv::insert_edges(), Slic3r::offset(), and triangulate().

Here is the call graph for this function:

◆ triangulate() [5/7]

Triangulation::Indices Triangulation::triangulate ( const Points & points,
const HalfEdges & half_edges )
static

Connect points by triangulation to create filled surface by triangles Input points have to be unique Inspiration for make unique points is Emboss::dilate_to_unique_points.

Parameters
pointsPoints to connect
edgesConstraint for edges, pair is from point(first) to point(second), sorted lexicographically
Returns
Triangles
105{
106 assert(!points.empty());
107 assert(!constrained_half_edges.empty());
108 // constrained must be sorted
109 assert(std::is_sorted(constrained_half_edges.begin(),
110 constrained_half_edges.end()));
111 // check that there is no duplicit constrained edge
112 assert(std::adjacent_find(constrained_half_edges.begin(), constrained_half_edges.end()) == constrained_half_edges.end());
113 // edges can NOT contain bidirectional constrained
114 assert(!priv::has_bidirectional_constrained(constrained_half_edges));
115 // check that there is only unique poistion of points
116 assert(priv::is_unique(points));
117 assert(!priv::has_self_intersection(points, constrained_half_edges));
118 // use cgal triangulation
119 using K = CGAL::Exact_predicates_inexact_constructions_kernel;
120 using Vb = CGAL::Triangulation_vertex_base_with_info_2<uint32_t, K>;
121 using Fb = CGAL::Constrained_triangulation_face_base_2<K>;
122 using Tds = CGAL::Triangulation_data_structure_2<Vb, Fb>;
123 using CDT = CGAL::Constrained_Delaunay_triangulation_2<K, Tds, CGAL::Exact_predicates_tag>;
124
125 // construct a constrained triangulation
126 CDT cdt;
127 {
128 std::vector<CDT::Vertex_handle> vertices_handle(points.size()); // for constriants
129 using Point_with_ord = std::pair<CDT::Point, size_t>;
130 using SearchTrait = CGAL::Spatial_sort_traits_adapter_2
131 <K, CGAL::First_of_pair_property_map<Point_with_ord> >;
132
133 std::vector<Point_with_ord> cdt_points;
134 cdt_points.reserve(points.size());
135 size_t ord = 0;
136 for (const auto &p : points)
137 cdt_points.emplace_back(std::make_pair(CDT::Point{p.x(), p.y()}, ord++));
138
139 SearchTrait st;
140 CGAL::spatial_sort(cdt_points.begin(), cdt_points.end(), st);
141 CDT::Face_handle f;
142 for (const auto& p : cdt_points) {
143 auto handle = cdt.insert(p.first, f);
144 handle->info() = p.second;
145 vertices_handle[p.second] = handle;
146 f = handle->face();
147 }
148
149 // Constrain the triangulation.
150 for (const HalfEdge &edge : constrained_half_edges)
151 cdt.insert_constraint(vertices_handle[edge.first], vertices_handle[edge.second]);
152 }
153
154 auto faces = cdt.finite_face_handles();
155
156 // Unmark constrained edges of outside faces.
157 size_t num_faces = 0;
158 for (CDT::Face_handle fh : faces) {
159 for (int i = 0; i < 3; ++i) {
160 if (!fh->is_constrained(i)) continue;
161 auto key = std::make_pair(fh->vertex((i + 2) % 3)->info(), fh->vertex((i + 1) % 3)->info());
162 auto it = std::lower_bound(constrained_half_edges.begin(), constrained_half_edges.end(), key);
163 if (it == constrained_half_edges.end() || *it != key) continue;
164 // This face contains a constrained edge and it is outside.
165 for (int j = 0; j < 3; ++ j)
166 fh->set_constraint(j, false);
167 --num_faces;
168 break;
169 }
170 ++num_faces;
171 }
172
173 auto inside = [](CDT::Face_handle &fh) {
174 return fh->neighbor(0) != fh &&
175 (fh->is_constrained(0) ||
176 fh->is_constrained(1) ||
177 fh->is_constrained(2));
178 };
179
180#ifdef VISUALIZE_TRIANGULATION
181 std::vector<Vec3i32> indices2;
182 indices2.reserve(num_faces);
183 for (CDT::Face_handle fh : faces)
184 if (inside(fh)) indices2.emplace_back(fh->vertex(0)->info(), fh->vertex(1)->info(), fh->vertex(2)->info());
185 visualize(points, indices2, "C:/data/temp/triangulation_without_floodfill.obj");
186#endif // VISUALIZE_TRIANGULATION
187
188 // Propagate inside the constrained regions.
189 std::vector<CDT::Face_handle> queue;
190 queue.reserve(num_faces);
191 for (CDT::Face_handle seed : faces){
192 if (!inside(seed)) continue;
193 // Seed fill to neighbor faces.
194 queue.emplace_back(seed);
195 while (! queue.empty()) {
196 CDT::Face_handle fh = queue.back();
197 queue.pop_back();
198 for (int i = 0; i < 3; ++i) {
199 if (fh->is_constrained(i)) continue;
200 // Propagate along this edge.
201 fh->set_constraint(i, true);
202 CDT::Face_handle nh = fh->neighbor(i);
203 bool was_inside = inside(nh);
204 // Mark the other side of this edge.
205 nh->set_constraint(nh->index(fh), true);
206 if (! was_inside)
207 queue.push_back(nh);
208 }
209 }
210 }
211
212 std::vector<Vec3i32> indices;
213 indices.reserve(num_faces);
214 for (CDT::Face_handle fh : faces)
215 if (inside(fh))
216 indices.emplace_back(fh->vertex(0)->info(), fh->vertex(1)->info(), fh->vertex(2)->info());
217
218#ifdef VISUALIZE_TRIANGULATION
219 visualize(points, indices, "C:/data/temp/triangulation.obj");
220#endif // VISUALIZE_TRIANGULATION
221
222 return indices;
223}
std::pair< uint32_t, uint32_t > HalfEdge
Definition Triangulation.hpp:20
bool inside(const Polygons &polygons, const Point &p)
Definition TreeNode.cpp:160
CGAL::Simple_cartesian< double > K
Definition VoronoiUtilsCgal.cpp:49
static double f(double x, double z_sin, double z_cos, bool vertical, bool flip)
Definition FillGyroid.cpp:124
bool has_bidirectional_constrained(const Triangulation::HalfEdges &constrained)
Definition Triangulation.cpp:55
bool has_self_intersection(const Points &points, const Triangulation::HalfEdges &constrained_half_edges)
Definition Triangulation.cpp:74
bool is_unique(const Points &points)
Definition Triangulation.cpp:67

References Slic3r::f(), priv::has_bidirectional_constrained(), priv::has_self_intersection(), and priv::is_unique().

Referenced by Slic3r::WipeTower::its_make_rib_brim(), Slic3r::WipeTower::its_make_rib_tower(), anonymous_namespace{Emboss.cpp}::polygons2model_duplicit(), anonymous_namespace{Emboss.cpp}::polygons2model_unique(), triangulate(), triangulate(), triangulate(), triangulate(), triangulate(), and triangulate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ triangulate() [6/7]

Triangulation::Indices Triangulation::triangulate ( const Polygon & polygon)
static
226{
227 const Points &pts = polygon.points;
228 HalfEdges edges;
229 edges.reserve(pts.size());
230 uint32_t offset = 0;
231 priv::insert_edges(edges, offset, polygon);
232 std::sort(edges.begin(), edges.end());
233 return triangulate(pts, edges);
234}
Points points
Definition MultiPoint.hpp:22

References priv::insert_edges(), Slic3r::offset(), Slic3r::MultiPoint::points, and triangulate().

Here is the call graph for this function:

◆ triangulate() [7/7]

Triangulation::Indices Triangulation::triangulate ( const Polygons & polygons)
static
237{
238 size_t count = count_points(polygons);
239 Points points;
240 points.reserve(count);
241
242 HalfEdges edges;
243 edges.reserve(count);
244 uint32_t offset = 0;
245
246 for (const Polygon &polygon : polygons) {
247 Slic3r::append(points, polygon.points);
248 priv::insert_edges(edges, offset, polygon);
249 }
250
251 std::sort(edges.begin(), edges.end());
252 return triangulate(points, edges);
253}
static unsigned int count
Definition AuxiliaryDataViewModel.cpp:246
void append(std::vector< T, Alloc > &dest, const std::vector< T, Alloc2 > &src)
Definition libslic3r.h:157

References Slic3r::append(), count, Slic3r::count_points(), priv::insert_edges(), Slic3r::offset(), and triangulate().

Here is the call graph for this function:

The documentation for this class was generated from the following files: