Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tikzgeom_algorithms.H
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
31#ifndef TIKZGEOM_ALGORITHMS_H
32#define TIKZGEOM_ALGORITHMS_H
33
34#include "geom_algorithms.H"
35#include "tikzgeom.H"
36#include "tpl_r_tree.H"
37
38namespace Aleph {
39namespace detail {
40inline std::string tikz_palette_color(const size_t idx)
41{
42 static const char *colors[] = {"blue!20", "orange!25", "green!20", "red!20", "cyan!22",
43 "magenta!20", "yellow!28", "teal!22", "lime!24", "brown!20"};
44 static constexpr size_t kNumColors = sizeof(colors) / sizeof(colors[0]);
45 return colors[idx % kNumColors];
46}
47
49{
50 size_t v[3];
51 size_t adj[3];
52};
53
59
60constexpr size_t SPP_NONE = ~static_cast<size_t>(0);
61
62[[nodiscard]] inline size_t spp_find_index(const Array<Point> &pts, const Point &p)
63{
64 for (size_t i = 0; i < pts.size(); ++i)
65 if (pts(i) == p)
66 return i;
67 return SPP_NONE;
68}
69
71 const DynList<Triangle> &tl)
72{
74 for (DynList<Triangle>::Iterator it(tl); it.has_curr(); it.next_ne())
75 {
76 const Triangle &t = it.get_curr();
77 SPP_ITri ti{};
78 ti.v[0] = spp_find_index(pts, t.get_p1());
79 ti.v[1] = spp_find_index(pts, t.get_p2());
80 ti.v[2] = spp_find_index(pts, t.get_p3());
81 ti.adj[0] = ti.adj[1] = ti.adj[2] = SPP_NONE;
82 tris.append(ti);
83 }
84
85 struct EdgeEntry
86 {
87 size_t u;
88 size_t v;
89 size_t tri;
90 size_t local;
91 };
92
93 Array<EdgeEntry> edges;
94 edges.reserve(tris.size() * 3);
95
96 for (size_t ti = 0; ti < tris.size(); ++ti)
97 for (int e = 0; e < 3; ++e)
98 {
99 size_t u = tris(ti).v[(e + 1) % 3];
100 size_t v = tris(ti).v[(e + 2) % 3];
101 if (u > v)
102 std::swap(u, v);
103 edges.append(EdgeEntry{u, v, ti, static_cast<size_t>(e)});
104 }
105
106 quicksort_op(edges, [](const EdgeEntry &a, const EdgeEntry &b)
107 {
108 if (a.u != b.u)
109 return a.u < b.u;
110 if (a.v != b.v)
111 return a.v < b.v;
112 return a.tri < b.tri;
113 });
114
115 for (size_t i = 0; i + 1 < edges.size(); ++i)
116 if (edges(i).u == edges(i + 1).u and edges(i).v == edges(i + 1).v)
117 {
118 const size_t t1 = edges(i).tri;
119 const size_t l1 = edges(i).local;
120 const size_t t2 = edges(i + 1).tri;
121 const size_t l2 = edges(i + 1).local;
122 tris(t1).adj[l1] = t2;
123 tris(t2).adj[l2] = t1;
124 ++i;
125 }
126
127 return tris;
128}
129
130[[nodiscard]] inline bool spp_point_in_triangle(const Array<Point> &pts, const SPP_ITri &t,
131 const Point &p)
132{
133 const Orientation o0 = orientation(pts(t.v[0]), pts(t.v[1]), p);
134 const Orientation o1 = orientation(pts(t.v[1]), pts(t.v[2]), p);
135 const Orientation o2 = orientation(pts(t.v[2]), pts(t.v[0]), p);
138 return not (has_cw and has_ccw);
139}
140
142 const Point &p)
143{
144 for (size_t i = 0; i < tris.size(); ++i)
145 if (spp_point_in_triangle(pts, tris(i), p))
146 return i;
147 return SPP_NONE;
148}
149
150[[nodiscard]] inline Array<size_t> spp_find_sleeve(const Array<SPP_ITri> &tris, const size_t src,
151 const size_t dst)
152{
153 if (src == dst)
154 {
156 s.append(src);
157 return s;
158 }
159
160 Array<size_t> parent;
161 parent.reserve(tris.size());
162 for (size_t i = 0; i < tris.size(); ++i)
163 parent.append(SPP_NONE);
164 parent(src) = src;
165
166 DynList<size_t> queue;
167 queue.append(src);
168
169 while (not queue.is_empty())
170 {
171 const size_t cur = queue.remove_first();
172 if (cur == dst)
173 break;
174
175 for (size_t nb : tris(cur).adj)
176 if (nb != SPP_NONE and parent(nb) == SPP_NONE)
177 {
178 parent(nb) = cur;
179 queue.append(nb);
180 }
181 }
182
183 Array<size_t> path;
184 if (parent(dst) == SPP_NONE)
185 return path;
186
187 for (size_t cur = dst; cur != src; cur = parent(cur))
188 path.append(cur);
189 path.append(src);
190
191 for (size_t i = 0; i < path.size() / 2; ++i)
192 std::swap(path(i), path(path.size() - 1 - i));
193
194 return path;
195}
196
197[[nodiscard]] inline Geom_Number spp_cross(const Point &a, const Point &b, const Point &c)
198{
199 return (b.get_x() - a.get_x()) * (c.get_y() - a.get_y()) -
200 (b.get_y() - a.get_y()) * (c.get_x() - a.get_x());
201}
202
204 const Point &source, const Point &target)
205{
206 ah_domain_error_if(not polygon.is_closed()) << "Polygon must be closed";
207 ah_domain_error_if(polygon.size() < 3) << "Polygon must have >= 3 vertices";
209 << "Source must be inside the polygon";
211 << "Target must be inside the polygon";
212
213 Array<SPP_Portal> portals;
214 if (source == target)
215 {
216 portals.append(SPP_Portal{source, source});
217 return portals;
218 }
219 {
220 const Segment seg(source, target);
221 bool blocked = false;
222 for (Polygon::Segment_Iterator it(polygon); it.has_curr() and not blocked; it.next_ne())
223 if (const Segment edge = it.get_current_segment(); seg.intersects_properly_with(edge))
224 blocked = true;
225 if (not blocked)
226 {
227 portals.append(SPP_Portal{source, source});
228 portals.append(SPP_Portal{target, target});
229 return portals;
230 }
231 }
232
234 for (Polygon::Vertex_Iterator it(polygon); it.has_curr(); it.next_ne())
235 pts.append(it.get_current_vertex().to_point());
236
238 const DynList<Triangle> tri_list = triangulator(polygon);
239
240 ah_domain_error_if(tri_list.is_empty()) << "Triangulation failed";
241
243 const size_t src_t = spp_find_tri(pts, tris, source);
244 const size_t dst_t = spp_find_tri(pts, tris, target);
245
246 ah_domain_error_if(src_t == SPP_NONE) << "Could not locate source in triangulation";
247 ah_domain_error_if(dst_t == SPP_NONE) << "Could not locate target in triangulation";
248
250
251 portals.append(SPP_Portal{source, source});
252
253 if (sleeve.size() <= 1)
254 {
255 portals.append(SPP_Portal{target, target});
256 return portals;
257 }
258
259 for (size_t i = 0; i + 1 < sleeve.size(); ++i)
260 {
261 size_t s0 = 0, s1 = 0;
262 size_t v_prev = 0;
263
264 int sc = 0;
265 bool found[3] = {false, false, false};
266 for (int a = 0; a < 3; ++a)
267 for (const size_t b : tris(sleeve(i + 1)).v)
268 if (tris(sleeve(i)).v[a] == b)
269 {
270 found[a] = true;
271 break;
272 }
273
274 for (int a = 0; a < 3; ++a)
275 if (found[a])
276 {
277 if (sc == 0)
278 s0 = tris(sleeve(i)).v[a];
279 else
280 s1 = tris(sleeve(i)).v[a];
281 ++sc;
282 }
283 else
284 v_prev = tris(sleeve(i)).v[a];
285
286 const Geom_Number c = spp_cross(pts(v_prev), pts(s0), pts(s1));
287 if (c < 0)
288 portals.append(SPP_Portal{pts(s0), pts(s1)});
289 else
290 portals.append(SPP_Portal{pts(s1), pts(s0)});
291 }
292
293 portals.append(SPP_Portal{target, target});
294 return portals;
295}
296} // namespace detail
297
320inline Tikz_Style tikz_points_style(const std::string &color = "black", const double opacity = -1.0)
321{
322 Tikz_Style s;
323 s.draw_color = color;
324 s.fill_color = color;
325 s.opacity = opacity;
326 return s;
327}
328
336inline Tikz_Style tikz_wire_style(const std::string &color = "black", const bool dashed = false,
337 const bool with_arrow = false)
338{
339 Tikz_Style s;
340 s.draw_color = color;
341 s.dashed = dashed;
343 return s;
344}
345
355inline Tikz_Style tikz_path_style(const std::string &color = "red", const bool with_arrow = false)
356{
358 s.thick = true;
359 return s;
360}
361
373inline Tikz_Style tikz_bold_wire_style(const std::string &color, const double width_mm = 1.2)
374{
377 return s;
378}
379
390inline Tikz_Style tikz_area_style(const std::string &draw_color = "black",
391 const std::string &fill_color = "gray!25",
392 const double opacity = 0.6)
393{
394 Tikz_Style s;
395 s.draw_color = draw_color;
396 s.fill_color = fill_color;
397 s.fill = true;
398 s.opacity = opacity;
399 return s;
400}
401
409inline void put_points(Tikz_Plane &plane, const Array<Point> &pts,
410 const Tikz_Style &style = tikz_points_style(),
411 const int layer = Tikz_Plane::Layer_Default)
412{
413 for (size_t i = 0; i < pts.size(); ++i)
414 put_in_plane(plane, pts(i), style, layer);
415}
416
424inline void put_points(Tikz_Plane &plane, const DynList<Point> &pts,
425 const Tikz_Style &style = tikz_points_style(),
426 const int layer = Tikz_Plane::Layer_Default)
427{
428 for (DynList<Point>::Iterator it(pts); it.has_curr(); it.next_ne())
429 put_in_plane(plane, it.get_curr(), style, layer);
430}
431
443inline void put_point_labels(Tikz_Plane &plane, const Array<Point> &pts,
444 const std::string &prefix = "p",
445 const std::string &placement = "above right",
446 const Tikz_Style &style = make_tikz_draw_style("black"),
447 const int layer = Tikz_Plane::Layer_Overlay)
448{
449 for (size_t i = 0; i < pts.size(); ++i)
450 put_point_label_in_plane(plane, pts(i), prefix + std::to_string(i), placement, style, layer);
451}
452
465 const std::string &prefix = "p",
466 const std::string &placement = "above right",
467 const Tikz_Style &style = make_tikz_draw_style("black"),
468 const int layer = Tikz_Plane::Layer_Overlay)
469{
470 size_t idx = 0;
471 for (DynList<Point>::Iterator it(pts); it.has_curr(); it.next_ne(), ++idx)
472 put_point_label_in_plane(plane, it.get_curr(), prefix + std::to_string(idx), placement, style,
473 layer);
474}
475
483inline void put_polygons(Tikz_Plane &plane, const Array<Polygon> &polys,
484 const Tikz_Style &style = tikz_wire_style(),
485 const int layer = Tikz_Plane::Layer_Default)
486{
487 for (size_t i = 0; i < polys.size(); ++i)
488 put_in_plane(plane, polys(i), style, layer);
489}
490
498inline void put_polygon_vertices(Tikz_Plane &plane, const Polygon &poly,
499 const Tikz_Style &style = tikz_points_style(),
500 const int layer = Tikz_Plane::Layer_Overlay)
501{
502 for (Polygon::Vertex_Iterator it(poly); it.has_curr(); it.next_ne())
503 put_in_plane(plane, it.get_current_vertex().to_point(), style, layer);
504}
505
513inline void put_polygon_vertices(Tikz_Plane &plane, const Regular_Polygon &poly,
514 const Tikz_Style &style = tikz_points_style(),
515 const int layer = Tikz_Plane::Layer_Overlay)
516{
517 for (size_t i = 0; i < poly.size(); ++i)
518 put_in_plane(plane, poly.get_vertex(i), style, layer);
519}
520
528inline Polygon polygon_from_vertices(const Array<Point> &vertices, const bool close = true)
529{
530 Polygon poly;
531 for (size_t i = 0; i < vertices.size(); ++i)
532 poly.add_vertex(vertices(i));
533
534 if (close and poly.size() >= 3)
535 poly.close();
536
537 return poly;
538}
539
551 const DynList<size_t> &indices, const bool close = true)
552{
553 Polygon poly;
554 for (DynList<size_t>::Iterator it(indices); it.has_curr(); it.next_ne())
555 if (const size_t idx = it.get_curr(); idx < vertices.size())
556 poly.add_vertex(vertices(idx));
557
558 if (close and poly.size() >= 3)
559 poly.close();
560
561 return poly;
562}
563
583template <typename HullAlgorithm>
586 const Tikz_Style &point_style = tikz_points_style("black", 0.6),
587 const Tikz_Style &hull_style = tikz_wire_style("red"),
591 const bool draw_hull_vertices = true)
592{
593 put_points(plane, points, point_style, point_layer);
594
595 Polygon hull = hull_algorithm(points);
596 if (hull.size() > 0)
598
599 if (draw_hull_vertices and hull.size() > 0)
601
602 return hull;
603}
604
622 Tikz_Plane &plane, const Polygon &subject, const Polygon &clip,
624 const Tikz_Style &subject_style = tikz_area_style("blue", "blue!15", 0.45),
625 const Tikz_Style &clip_style = tikz_area_style("orange", "orange!20", 0.45),
626 const Tikz_Style &result_style = tikz_area_style("red", "red!30", 0.60),
629{
632
634 if (inter.size() > 0)
636
637 return inter;
638}
639
660 Tikz_Plane &plane, const Polygon &a, const Polygon &b, const BooleanPolygonOperations::Op op,
661 const BooleanPolygonOperations &bop = {},
662 const Tikz_Style &a_style = tikz_area_style("blue", "blue!15", 0.35),
663 const Tikz_Style &b_style = tikz_area_style("green!60!black", "green!20", 0.35),
664 const Tikz_Style &result_style = tikz_area_style("red", "red!35", 0.65),
667{
668 put_in_plane(plane, a, a_style, input_layer);
669 put_in_plane(plane, b, b_style, input_layer + 1);
670
671 Array<Polygon> result = bop(a, b, op);
672 put_polygons(plane, result, result_style, result_layer);
673 return result;
674}
675
683 const bool draw_sites = true,
684 const Tikz_Style &site_style = tikz_points_style("black"),
687{
688 for (size_t i = 0; i < dt.triangles.size(); ++i)
689 {
690 const auto &tri = dt.triangles(i);
691 Triangle t(dt.sites(tri.i), dt.sites(tri.j), dt.sites(tri.k));
693 }
694
695 if (draw_sites)
697}
698
701 Tikz_Plane &plane, const DynList<Point> &points,
703 const Tikz_Style &triangle_style = tikz_wire_style("blue"), const bool draw_sites = true,
704 const Tikz_Style &site_style = tikz_points_style("black"))
705{
706 auto dt = algorithm(points);
708 return dt;
709}
710
711[[nodiscard]] inline Point ray_endpoint(const Point &src, const Point &direction,
712 const Geom_Number &length)
713{
714 const Geom_Number &dx = direction.get_x();
715 const Geom_Number &dy = direction.get_y();
716 const Geom_Number n2 = dx * dx + dy * dy;
717 if (n2 == 0)
718 return src;
719
720 const Geom_Number n = square_root(n2);
721 const Geom_Number scale = length / n;
722 return {src.get_x() + dx * scale, src.get_y() + dy * scale};
723}
724
730template <typename VoronoiResult>
731void put_voronoi_result(Tikz_Plane &plane, const VoronoiResult &vor, const bool draw_cells = false,
732 const Tikz_Style &cell_style = tikz_area_style("gray!50!black", "gray!15",
733 0.35),
734 const Tikz_Style &edge_style = tikz_wire_style("black"),
735 const Tikz_Style &unbounded_edge_style = tikz_wire_style("black", true, true),
741{
742 if (draw_cells)
743 for (size_t i = 0; i < vor.cells.size(); ++i)
744 {
745 const auto &cell = vor.cells(i);
746 if (not cell.bounded or cell.vertices.size() < 3)
747 continue;
748
749 Polygon poly = polygon_from_vertices(cell.vertices, true);
750 put_in_plane(plane, poly, cell_style, cell_layer);
751 }
752
753 for (size_t i = 0; i < vor.edges.size(); ++i)
754 if (const auto &e = vor.edges(i); e.unbounded)
755 {
756 const Point tgt = ray_endpoint(e.src, e.direction, unbounded_ray_length);
758 }
759 else
760 put_in_plane(plane, Segment(e.src, e.tgt), edge_style, edge_layer);
761
762 put_points(plane, vor.sites, site_style, site_layer);
763}
764
784
787 Tikz_Plane &plane, const PowerDiagram::Result &pd, const bool draw_cells = true,
788 const Tikz_Style &cell_style = tikz_area_style("violet", "violet!18", 0.35),
789 const Tikz_Style &edge_style = tikz_wire_style("violet"),
790 const Tikz_Style &site_style = tikz_points_style("purple"),
794{
795 if (draw_cells)
796 for (size_t i = 0; i < pd.cells.size(); ++i)
797 {
798 const auto &cell = pd.cells(i);
799 if (cell.vertices.size() < 3)
800 continue;
801
802 Polygon poly = polygon_from_vertices(cell.vertices, true);
803 put_in_plane(plane, poly, cell_style, cell_layer);
804 }
805
806 for (size_t i = 0; i < pd.edges.size(); ++i)
807 {
808 const auto &e = pd.edges(i);
809 put_in_plane(plane, Segment(e.src, e.tgt), edge_style, edge_layer);
810 }
811
812 for (size_t i = 0; i < pd.sites.size(); ++i)
813 put_in_plane(plane, pd.sites(i).position, site_style, site_layer);
814}
815
830
833 Tikz_Plane &plane, const SegmentArrangement::Result &arrangement, const bool draw_faces = true,
834 const bool draw_vertices = true, const bool draw_unbounded_face = false,
835 const Tikz_Style &face_style = tikz_area_style("teal!60!black", "teal!12", 0.30),
836 const Tikz_Style &edge_style = tikz_wire_style("teal!70!black"),
837 const Tikz_Style &vertex_style = tikz_points_style("teal!70!black"),
840 const int vertex_layer = Tikz_Plane::Layer_Foreground, const bool color_faces_by_index = false)
841{
842 if (draw_faces)
843 {
844 size_t face_color_idx = 0;
845 for (size_t i = 0; i < arrangement.faces.size(); ++i)
846 {
847 const auto &[boundary, unbounded] = arrangement.faces(i);
848 if (unbounded and not draw_unbounded_face)
849 continue;
850
851 Polygon poly = polygon_from_vertex_indices(arrangement.vertices, boundary, true);
852 if (poly.size() >= 3)
853 {
854 Tikz_Style style = face_style;
856 {
857 style.fill = true;
859 if (style.draw_color.empty())
860 style.draw_color = "black";
861 }
862
863 put_in_plane(plane, poly, style, face_layer);
864 }
865 }
866 }
867
868 for (size_t i = 0; i < arrangement.edges.size(); ++i)
869 {
870 const auto &e = arrangement.edges(i);
871 if (e.src >= arrangement.vertices.size() or e.tgt >= arrangement.vertices.size())
872 continue;
873
874 put_in_plane(plane, Segment(arrangement.vertices(e.src), arrangement.vertices(e.tgt)),
876 }
877
878 if (draw_vertices)
880}
881
884 Tikz_Plane &plane, const Array<Segment> &segments, const SegmentArrangement &algorithm = {},
885 const bool draw_faces = true, const bool draw_vertices = true,
886 const bool draw_unbounded_face = false,
887 const Tikz_Style &face_style = tikz_area_style("teal!60!black", "teal!12", 0.30),
888 const Tikz_Style &edge_style = tikz_wire_style("teal!70!black"),
889 const Tikz_Style &vertex_style = tikz_points_style("teal!70!black"),
890 const bool color_faces_by_index = false)
891{
897 return res;
898}
899
902 Tikz_Plane &plane, const KDTreePointSearch::DebugSnapshot &snapshot,
903 const bool draw_partition_boxes = false, const bool draw_points = true,
904 const Tikz_Style &partition_style = tikz_wire_style("gray!55", true),
905 const Tikz_Style &split_style = tikz_wire_style("blue!70"),
910{
911 for (size_t i = 0; i < snapshot.partitions.size(); ++i)
912 {
913 const auto &part = snapshot.partitions(i);
916
917 if (part.is_leaf)
918 continue;
919
920 const Geom_Number x0 = part.region.get_xmin();
921 const Geom_Number x1 = part.region.get_xmax();
922 const Geom_Number y0 = part.region.get_ymin();
923 const Geom_Number y1 = part.region.get_ymax();
924 Segment split_seg = part.split_on_x
925 ? Segment(Point(part.split_value, y0), Point(part.split_value, y1))
926 : Segment(Point(x0, part.split_value), Point(x1, part.split_value));
927
928 Tikz_Style style = split_style;
930 put_in_plane(plane, split_seg, style, split_layer);
931 }
932
933 if (draw_points)
934 put_points(plane, snapshot.points, point_style, point_layer);
935}
936
939 Tikz_Plane &plane, const KDTreePointSearch &kd_tree, const bool draw_partition_boxes = false,
940 const bool draw_points = true, const Tikz_Style &partition_style = tikz_wire_style("gray!55", true),
941 const Tikz_Style &split_style = tikz_wire_style("blue!70"),
943{
944 const auto snapshot = kd_tree.debug_snapshot();
947 return snapshot;
948}
949
952 const bool draw_points = true,
953 const Rectangle *query_rect = nullptr,
954 const DynList<Point> *query_hits = nullptr,
955 const Tikz_Style &split_style = tikz_wire_style("purple"),
956 const Tikz_Style &point_style = tikz_points_style("black"),
957 const Tikz_Style &query_rect_style = tikz_wire_style("red", true),
961{
962 if (snapshot.x_sorted_points.size() == 0)
963 return;
964
965 Geom_Number ymin = snapshot.x_sorted_points(0).get_y();
966 Geom_Number ymax = ymin;
967 for (size_t i = 1; i < snapshot.x_sorted_points.size(); ++i)
968 {
969 if (snapshot.x_sorted_points(i).get_y() < ymin)
970 ymin = snapshot.x_sorted_points(i).get_y();
971 if (snapshot.x_sorted_points(i).get_y() > ymax)
972 ymax = snapshot.x_sorted_points(i).get_y();
973 }
974
975 for (size_t i = 0; i < snapshot.nodes.size(); ++i)
976 {
977 const auto &node = snapshot.nodes(i);
978 if (node.is_leaf)
979 continue;
980
981 Tikz_Style style = split_style;
982 style.draw_color = detail::tikz_palette_color(node.tree_index);
983 put_in_plane(plane, Segment(Point(node.split_x, ymin), Point(node.split_x, ymax)), style,
985 }
986
987 if (draw_points)
989
990 if (query_rect != nullptr)
991 put_in_plane(plane, *query_rect, query_rect_style, point_layer + 1);
992
993 if (query_hits != nullptr)
994 put_points(plane, *query_hits, query_hit_style, point_layer + 2);
995}
996
999 Tikz_Plane &plane, const RangeTree2D &tree, const bool draw_points = true,
1000 const Tikz_Style &split_style = tikz_wire_style("purple"),
1001 const Tikz_Style &point_style = tikz_points_style("black"))
1002{
1003 const auto snapshot = tree.debug_snapshot();
1004 put_range_tree_result(plane, snapshot, draw_points, nullptr, nullptr, split_style, point_style);
1005 return snapshot;
1006}
1007
1015
1018 Tikz_Plane &plane, const RangeTree2D &tree, const Rectangle &query_rect,
1019 const bool draw_points = true, const Tikz_Style &split_style = tikz_wire_style("purple"),
1020 const Tikz_Style &point_style = tikz_points_style("black"),
1021 const Tikz_Style &query_rect_style = tikz_wire_style("red", true),
1023{
1025 out.snapshot = tree.debug_snapshot();
1026 out.query_rect = query_rect;
1027 out.query_hits = tree.query(query_rect.get_xmin(), query_rect.get_xmax(), query_rect.get_ymin(),
1028 query_rect.get_ymax());
1029 put_range_tree_result(plane, out.snapshot, draw_points, &out.query_rect, &out.query_hits,
1031 return out;
1032}
1033
1036 Tikz_Plane &plane, const AABBTree::DebugSnapshot &snapshot, const Rectangle *query_rect = nullptr,
1037 const Array<size_t> *query_hit_ids = nullptr,
1038 const Tikz_Style &node_bbox_style = tikz_wire_style("teal!70!black"),
1039 const Tikz_Style &leaf_bbox_style = tikz_wire_style("blue!70"),
1040 const Tikz_Style &query_rect_style = tikz_wire_style("red", true),
1044{
1045 for (size_t i = 0; i < snapshot.nodes.size(); ++i)
1046 {
1047 const auto &node = snapshot.nodes(i);
1048 Tikz_Style style = node.is_leaf ? leaf_bbox_style : node_bbox_style;
1049 style.draw_color = detail::tikz_palette_color(node.depth);
1050 put_in_plane(plane, node.bbox, style, node_layer);
1051 }
1052
1053 if (query_rect != nullptr)
1054 put_in_plane(plane, *query_rect, query_rect_style, query_layer);
1055
1056 if (query_hit_ids != nullptr)
1057 for (size_t i = 0; i < snapshot.nodes.size(); ++i)
1058 if (snapshot.nodes(i).is_leaf)
1059 for (size_t j = 0; j < query_hit_ids->size(); ++j)
1060 if (snapshot.nodes(i).user_index == (*query_hit_ids)(j))
1061 {
1062 put_in_plane(plane, snapshot.nodes(i).bbox, query_hit_style, query_layer + 1);
1063 break;
1064 }
1065}
1066
1069 Tikz_Plane &plane, const AABBTree &tree,
1070 const Tikz_Style &node_bbox_style = tikz_wire_style("teal!70!black"),
1071 const Tikz_Style &leaf_bbox_style = tikz_wire_style("blue!70"))
1072{
1073 const auto snapshot = tree.debug_snapshot();
1074 put_aabb_tree_result(plane, snapshot, nullptr, nullptr, node_bbox_style, leaf_bbox_style);
1075 return snapshot;
1076}
1077
1085
1088 Tikz_Plane &plane, const AABBTree &tree, const Rectangle &query_rect,
1089 const Tikz_Style &node_bbox_style = tikz_wire_style("teal!70!black"),
1090 const Tikz_Style &leaf_bbox_style = tikz_wire_style("blue!70"),
1091 const Tikz_Style &query_rect_style = tikz_wire_style("red", true),
1093{
1095 out.snapshot = tree.debug_snapshot();
1096 out.query_rect = query_rect;
1097 out.query_hit_ids = tree.query(query_rect);
1098 put_aabb_tree_result(plane, out.snapshot, &out.query_rect, &out.query_hit_ids, node_bbox_style,
1100 return out;
1101}
1102
1112template <typename Snapshot>
1113inline void put_rtree_result(Tikz_Plane &plane, const Snapshot &snapshot,
1114 const Rectangle *query_rect = nullptr,
1115 const Array<Rectangle> *query_hit_boxes = nullptr,
1116 const Tikz_Style &node_bbox_style = tikz_wire_style("teal!70!black"),
1117 const Tikz_Style &leaf_bbox_style = tikz_wire_style("blue!70"),
1118 const Tikz_Style &entry_bbox_style = tikz_wire_style("gray!55"),
1119 const Tikz_Style &query_rect_style = tikz_wire_style("red", true),
1124{
1125 for (size_t i = 0; i < snapshot.nodes.size(); ++i)
1126 {
1127 const auto &node = snapshot.nodes(i);
1128 Tikz_Style style = node.is_leaf ? leaf_bbox_style : node_bbox_style;
1129 style.draw_color = detail::tikz_palette_color(node.depth);
1130 put_in_plane(plane, node.bbox, style, node_layer);
1131
1132 if (node.is_leaf)
1133 for (size_t j = 0; j < node.entry_boxes.size(); ++j)
1134 put_in_plane(plane, node.entry_boxes(j), entry_bbox_style, entry_layer);
1135 }
1136
1137 if (query_rect != nullptr)
1138 put_in_plane(plane, *query_rect, query_rect_style, query_layer);
1139
1140 if (query_hit_boxes != nullptr)
1141 for (size_t i = 0; i < query_hit_boxes->size(); ++i)
1142 put_in_plane(plane, (*query_hit_boxes)(i), query_hit_style, query_layer + 1);
1143}
1144
1148template <typename Payload, size_t MaxEntries, size_t MinEntries, RTreeVariant Variant>
1151 const Tikz_Style &node_bbox_style = tikz_wire_style("teal!70!black"),
1152 const Tikz_Style &leaf_bbox_style = tikz_wire_style("blue!70"),
1153 const Tikz_Style &entry_bbox_style = tikz_wire_style("gray!55"))
1154{
1155 const auto snapshot = tree.debug_snapshot();
1156 put_rtree_result(plane, snapshot, nullptr, nullptr, node_bbox_style, leaf_bbox_style,
1158 return snapshot;
1159}
1160
1162template <typename Payload, size_t MaxEntries, size_t MinEntries, RTreeVariant Variant>
1169
1173template <typename Payload, size_t MaxEntries, size_t MinEntries, RTreeVariant Variant>
1176 const Rectangle &query_rect, const Tikz_Style &node_bbox_style = tikz_wire_style("teal!70!black"),
1177 const Tikz_Style &leaf_bbox_style = tikz_wire_style("blue!70"),
1178 const Tikz_Style &entry_bbox_style = tikz_wire_style("gray!55"),
1179 const Tikz_Style &query_rect_style = tikz_wire_style("red", true),
1181{
1183 out.snapshot = tree.debug_snapshot();
1184 out.query_rect = query_rect;
1185 tree.for_each_intersecting(query_rect, [&out](const Rectangle &bbox, const Payload &)
1186 {
1187 out.query_hit_boxes.append(bbox);
1188 });
1189 put_rtree_result(plane, out.snapshot, &out.query_rect, &out.query_hit_boxes, node_bbox_style,
1191 return out;
1192}
1193
1195inline void put_path(Tikz_Plane &plane, const DynList<Point> &path,
1197 const bool draw_waypoints = true,
1201{
1202 bool has_prev = false;
1203 Point prev;
1204
1205 for (DynList<Point>::Iterator it(path); it.has_curr(); it.next_ne())
1206 {
1207 const Point &curr = it.get_curr();
1208 if (has_prev)
1209 put_in_plane(plane, Segment(prev, curr), segment_style, segment_layer);
1210
1211 prev = curr;
1212 has_prev = true;
1213 }
1214
1215 if (draw_waypoints)
1217}
1218
1220inline void put_path(Tikz_Plane &plane, const Array<Point> &path,
1222 const bool draw_waypoints = true,
1226{
1227 if (path.size() == 0)
1228 return;
1229
1230 for (size_t i = 1; i < path.size(); ++i)
1231 put_in_plane(plane, Segment(path(i - 1), path(i)), segment_style, segment_layer);
1232
1233 if (draw_waypoints)
1235}
1236
1238
1240inline void put_portals(Tikz_Plane &plane, const Array<FunnelPortal> &portals,
1241 const bool skip_degenerate = true,
1242 const Tikz_Style &portal_style = tikz_wire_style("purple", true),
1244{
1245 for (size_t i = 0; i < portals.size(); ++i)
1246 {
1247 const auto &[left, right] = portals(i);
1248 if (skip_degenerate and left == right)
1249 continue;
1250
1251 put_in_plane(plane, Segment(left, right), portal_style, portal_layer);
1252 }
1253}
1254
1261
1277
1285
1291 const Point &source, const Point &target)
1292{
1294 trace.portals = detail::shortest_path_portals(polygon, source, target);
1295
1296 if (trace.portals.size() == 0)
1297 return trace;
1298
1299 Point apex = source;
1300 Point fl = source;
1301 Point fr = source;
1302 size_t ai = 0;
1303 size_t li = 0;
1304 size_t ri = 0;
1305
1306 Array<Point> committed;
1307 committed.append(source);
1308
1309 for (size_t i = 1; i < trace.portals.size(); ++i)
1310 {
1311 const Point &pr = trace.portals(i).right;
1312 const Point &pl = trace.portals(i).left;
1313
1314 FunnelTraceStep step;
1315 step.portal_index = i;
1316 step.portal_left = pl;
1317 step.portal_right = pr;
1318 step.apex = apex;
1319 step.left_boundary = fl;
1320 step.right_boundary = fr;
1321 step.committed_path = committed;
1322
1323 bool restart = false;
1324
1325 if (detail::spp_cross(apex, fr, pr) >= 0)
1326 {
1327 if (apex == fr or detail::spp_cross(apex, fl, pr) < 0)
1328 {
1329 fr = pr;
1330 ri = i;
1331 step.tightened_right = true;
1332 }
1333 else
1334 {
1335 committed.append(fl);
1336 step.emitted_left = true;
1337
1338 apex = fl;
1339 ai = li;
1340 fl = apex;
1341 fr = apex;
1342 li = ai;
1343 ri = ai;
1344 i = ai;
1345 restart = true;
1346 }
1347 }
1348
1349 if (not restart and detail::spp_cross(apex, fl, pl) <= 0)
1350 {
1351 if (apex == fl or detail::spp_cross(apex, fr, pl) > 0)
1352 {
1353 fl = pl;
1354 li = i;
1355 step.tightened_left = true;
1356 }
1357 else
1358 {
1359 committed.append(fr);
1360 step.emitted_right = true;
1361
1362 apex = fr;
1363 ai = ri;
1364 fl = apex;
1365 fr = apex;
1366 li = ai;
1367 ri = ai;
1368 i = ai;
1369 restart = true;
1370 }
1371 }
1372
1373 step.apex = apex;
1374 step.left_boundary = fl;
1375 step.right_boundary = fr;
1376 step.committed_path = committed;
1377 trace.steps.append(step);
1378
1379 if (restart)
1380 continue; // this is deliberately after appending the step, so the "restart" state is visible in the trace
1381 }
1382
1383 committed.append(target);
1384 trace.final_path = committed;
1385 return trace;
1386}
1387
1393 Tikz_Plane &plane, const Polygon &polygon, const Point &source, const Point &target,
1394 const FunnelTraceResult &trace, size_t step_index,
1395 const Tikz_Style &polygon_style = tikz_area_style("black", "gray!15", 0.22),
1396 const Tikz_Style &source_style = tikz_points_style("green!50!black"),
1397 const Tikz_Style &target_style = tikz_points_style("blue"),
1398 const Tikz_Style &all_portals_style = tikz_wire_style("purple", true),
1400 const Tikz_Style &funnel_leg_style = tikz_path_style("orange!90!black"),
1401 const Tikz_Style &committed_style = tikz_path_style("red"), const bool draw_waypoints = true,
1406{
1407 put_in_plane(plane, polygon, polygon_style, polygon_layer);
1408 put_in_plane(plane, source, source_style, highlight_layer + 1);
1409 put_in_plane(plane, target, target_style, highlight_layer + 1);
1410
1411 put_portals(plane, trace.portals, true, all_portals_style, portal_layer);
1412
1413 if (trace.steps.size() == 0)
1414 return;
1415
1416 if (step_index >= trace.steps.size())
1417 step_index = trace.steps.size() - 1;
1418
1419 const FunnelTraceStep &step = trace.steps(step_index);
1420
1421 // Active portal segment.
1422 if (step.portal_left != step.portal_right)
1425
1426 // Current funnel legs.
1427 if (step.apex != step.left_boundary)
1429 if (step.apex != step.right_boundary)
1431
1432 // Committed path prefix.
1435
1436 put_in_plane(plane, step.apex, tikz_points_style("orange!90!black"), highlight_layer + 2);
1437 put_in_plane(plane, step.left_boundary, tikz_points_style("orange!90!black"), highlight_layer + 2);
1438 put_in_plane(plane, step.right_boundary, tikz_points_style("orange!90!black"), highlight_layer + 2);
1439}
1440
1443 Tikz_Plane &plane, const Polygon &polygon, const Point &source, const Point &target,
1444 const ShortestPathInPolygon &algorithm = {},
1445 const Tikz_Style &polygon_style = tikz_area_style("black", "gray!15", 0.25),
1446 const Tikz_Style &source_style = tikz_points_style("green!50!black"),
1447 const Tikz_Style &target_style = tikz_points_style("blue"),
1448 const Tikz_Style &path_style = tikz_path_style("red"), const bool draw_waypoints = true,
1452{
1453 put_in_plane(plane, polygon, polygon_style, polygon_layer);
1454 put_in_plane(plane, source, source_style, path_layer + 1);
1455 put_in_plane(plane, target, target_style, path_layer + 1);
1456
1457 DynList<Point> path = algorithm(polygon, source, target);
1459 return path;
1460}
1461
1470 Tikz_Plane &plane, const Polygon &polygon, const Point &source, const Point &target,
1471 const ShortestPathInPolygon &algorithm = {},
1472 const Tikz_Style &polygon_style = tikz_area_style("black", "gray!15", 0.25),
1473 const Tikz_Style &source_style = tikz_points_style("green!50!black"),
1474 const Tikz_Style &target_style = tikz_points_style("blue"),
1475 const Tikz_Style &portal_style = tikz_wire_style("purple", true),
1476 const Tikz_Style &path_style = tikz_path_style("red"), const bool draw_waypoints = true,
1481{
1482 put_in_plane(plane, polygon, polygon_style, polygon_layer);
1483 put_in_plane(plane, source, source_style, portal_layer + 1);
1484 put_in_plane(plane, target, target_style, portal_layer + 1);
1485
1487 out.portals = detail::shortest_path_portals(polygon, source, target);
1488 put_portals(plane, out.portals, true, portal_style, portal_layer);
1489
1490 out.path = algorithm(polygon, source, target);
1492 return out;
1493}
1494
1500 Tikz_Plane &plane, const Array<Polygon> &parts, const bool color_parts_by_index = true,
1501 const Tikz_Style &part_style = tikz_area_style("blue!60!black", "blue!15", 0.40),
1503{
1504 size_t color_idx = 0;
1505 for (size_t i = 0; i < parts.size(); ++i)
1506 {
1507 Tikz_Style style = part_style;
1509 {
1510 style.fill = true;
1512 if (style.draw_color.empty())
1513 style.draw_color = "black";
1514 }
1515
1516 put_in_plane(plane, parts(i), style, part_layer);
1517 }
1518}
1519
1522 Tikz_Plane &plane, const Polygon &polygon, const ConvexPolygonDecomposition &algorithm = {},
1523 const bool draw_input_polygon = true,
1524 const Tikz_Style &input_style = tikz_wire_style("black", true),
1525 const bool color_parts_by_index = true,
1526 const Tikz_Style &part_style = tikz_area_style("blue!60!black", "blue!15", 0.40),
1529{
1531 put_in_plane(plane, polygon, input_style, input_layer);
1532
1533 Array<Polygon> parts = algorithm(polygon);
1535 return parts;
1536}
1537
1540 Tikz_Plane &plane, const AlphaShape::Result &alpha_shape, const bool draw_kept_triangles = false,
1541 const Tikz_Style &triangle_style = tikz_wire_style("gray!55"),
1542 const Tikz_Style &boundary_style = tikz_path_style("orange!90!black"),
1543 const bool draw_sites = true, const Tikz_Style &site_style = tikz_points_style("black"),
1547{
1549 for (size_t n = 0; n < alpha_shape.triangles.size(); ++n)
1550 {
1551 const auto &[i, j, k] = alpha_shape.triangles(n);
1552 if (i >= alpha_shape.sites.size() or j >= alpha_shape.sites.size() or
1553 k >= alpha_shape.sites.size())
1554 continue;
1555
1556 put_in_plane(plane,
1557 Triangle(alpha_shape.sites(i), alpha_shape.sites(j), alpha_shape.sites(k)),
1559 }
1560
1561 for (size_t i = 0; i < alpha_shape.boundary_edges.size(); ++i)
1562 put_in_plane(plane, alpha_shape.boundary_edges(i), boundary_style, boundary_layer);
1563
1564 if (draw_sites)
1566}
1567
1582
1586 const Tikz_Style &triangle_style = tikz_wire_style("blue!60"), const bool draw_sites = true,
1587 const Tikz_Style &site_style = tikz_points_style("black"),
1590{
1591 for (size_t i = 0; i < rt.triangles.size(); ++i)
1592 {
1593 const auto &tri = rt.triangles(i);
1594 Triangle t(rt.sites(tri.i).position, rt.sites(tri.j).position, rt.sites(tri.k).position);
1596 }
1597
1598 if (draw_sites)
1599 for (size_t i = 0; i < rt.sites.size(); ++i)
1600 put_in_plane(plane, rt.sites(i).position, site_style, site_layer);
1601}
1602
1614
1616inline void put_closest_pair_result(Tikz_Plane &plane, const DynList<Point> &points,
1618 const Tikz_Style &points_style = tikz_points_style("black"),
1619 const Tikz_Style &pair_style = tikz_path_style("red"),
1623{
1624 put_points(plane, points, points_style, points_layer);
1625 put_in_plane(plane, Segment(result.first, result.second), pair_style, pair_layer);
1626 put_in_plane(plane, result.first, pair_points_style, pair_layer + 1);
1627 put_in_plane(plane, result.second, pair_points_style, pair_layer + 1);
1628}
1629
1632 Tikz_Plane &plane, const DynList<Point> &points, const ClosestPairDivideAndConquer &algorithm = {},
1633 const Tikz_Style &points_style = tikz_points_style("black"),
1634 const Tikz_Style &pair_style = tikz_path_style("red"),
1636{
1637 auto result = algorithm(points);
1639 return result;
1640}
1641
1648
1651 Tikz_Plane &plane, const Polygon &polygon, const RotatingCalipersResult &result,
1652 const Tikz_Style &polygon_style = tikz_wire_style("gray!55"),
1654 const Tikz_Style &width_style = tikz_path_style("blue"),
1655 const Tikz_Style &witness_style = tikz_points_style("orange!90!black"),
1658{
1659 put_in_plane(plane, polygon, polygon_style, polygon_layer);
1665}
1666
1669 Tikz_Plane &plane, const Polygon &polygon,
1670 const Tikz_Style &polygon_style = tikz_wire_style("gray!55"),
1672 const Tikz_Style &width_style = tikz_path_style("blue"),
1673 const Tikz_Style &witness_style = tikz_points_style("orange!90!black"))
1674{
1679 return result;
1680}
1681
1685 const Polygon &intersection,
1686 const Tikz_Style &boundary_style = tikz_wire_style("gray!60", true, true),
1687 const Tikz_Style &result_style = tikz_area_style("red", "red!25", 0.50),
1690{
1691 for (size_t i = 0; i < halfplanes.size(); ++i)
1693
1694 if (intersection.size() > 0)
1695 put_in_plane(plane, intersection, result_style, result_layer);
1696}
1697
1701 const HalfPlaneIntersection &algorithm = {},
1702 const Tikz_Style &boundary_style = tikz_wire_style("gray!60", true, true),
1703 const Tikz_Style &result_style = tikz_area_style("red", "red!25", 0.50))
1704{
1705 Polygon intersection = algorithm(halfplanes);
1707 return intersection;
1708}
1709
1712 Tikz_Plane &plane, const Polygon &first, const Polygon &second, const Polygon &result,
1713 const Tikz_Style &first_style = tikz_area_style("blue", "blue!14", 0.30),
1714 const Tikz_Style &second_style = tikz_area_style("green!60!black", "green!16", 0.30),
1715 const Tikz_Style &result_style = tikz_area_style("red", "red!26", 0.60),
1718{
1719 put_in_plane(plane, first, first_style, input_layer);
1720 put_in_plane(plane, second, second_style, input_layer + 1);
1721 if (result.size() > 0)
1722 put_in_plane(plane, result, result_style, result_layer);
1723}
1724
1727 Tikz_Plane &plane, const Polygon &first, const Polygon &second,
1728 const MinkowskiSumConvex &algorithm = {},
1729 const Tikz_Style &first_style = tikz_area_style("blue", "blue!14", 0.30),
1730 const Tikz_Style &second_style = tikz_area_style("green!60!black", "green!16", 0.30),
1731 const Tikz_Style &result_style = tikz_area_style("red", "red!26", 0.60))
1732{
1733 Polygon result = algorithm(first, second);
1734 put_minkowski_sum_result(plane, first, second, result, first_style, second_style, result_style);
1735 return result;
1736}
1737
1740 Tikz_Plane &plane, const Polygon &polygon, const DynList<Triangle> &triangles,
1741 const Tikz_Style &polygon_style = tikz_wire_style("black"),
1742 const Tikz_Style &triangle_style = tikz_wire_style("blue!65"),
1745{
1746 put_in_plane(plane, polygon, polygon_style, polygon_layer);
1747 for (DynList<Triangle>::Iterator it(triangles); it.has_curr(); it.next_ne())
1748 put_in_plane(plane, it.get_curr(), triangle_style, triangle_layer);
1749}
1750
1753 Tikz_Plane &plane, const Polygon &polygon, const MonotonePolygonTriangulation &algorithm = {},
1754 const Tikz_Style &polygon_style = tikz_wire_style("black"),
1755 const Tikz_Style &triangle_style = tikz_wire_style("blue!65"))
1756{
1757 DynList<Triangle> triangles = algorithm(polygon);
1759 return triangles;
1760}
1761
1764 Tikz_Plane &plane, const Polygon &polygon, const Point &query_point,
1766 const Tikz_Style &visibility_style = tikz_area_style("orange!90!black", "orange!25", 0.50),
1770{
1771 put_in_plane(plane, polygon, polygon_style, polygon_layer);
1772 if (visibility_polygon.size() > 0)
1774 put_in_plane(plane, query_point, query_style, visibility_layer + 1);
1775}
1776
1779 Tikz_Plane &plane, const Polygon &polygon, const Point &query_point,
1781 const Tikz_Style &visibility_style = tikz_area_style("orange!90!black", "orange!25", 0.50),
1783{
1784 Polygon visibility_polygon = algorithm(polygon, query_point);
1787 return visibility_polygon;
1788}
1789
1791inline void put_line_sweep_result(Tikz_Plane &plane, const Array<Segment> &segments,
1793 const Tikz_Style &segment_style = tikz_wire_style("blue!60"),
1797{
1798 for (size_t i = 0; i < segments.size(); ++i)
1799 put_in_plane(plane, segments(i), segment_style, segment_layer);
1800
1801 for (size_t i = 0; i < intersections.size(); ++i)
1803}
1804
1816
1823 const Tikz_Style &triangle_style = tikz_wire_style("blue!60"),
1825 const bool draw_sites = true,
1826 const Tikz_Style &site_style = tikz_points_style("black"),
1830{
1831 for (size_t i = 0; i < cdt.triangles.size(); ++i)
1832 {
1833 const auto &tri = cdt.triangles(i);
1834 Triangle t(cdt.sites(tri.i), cdt.sites(tri.j), cdt.sites(tri.k));
1836 }
1837
1838 for (size_t i = 0; i < cdt.constrained_edges.size(); ++i)
1839 {
1840 const auto &e = cdt.constrained_edges(i);
1841 Segment s(cdt.sites(e.u), cdt.sites(e.v));
1843 }
1844
1845 if (draw_sites)
1846 put_points(plane, cdt.sites, site_style, site_layer);
1847}
1848
1851 Tikz_Plane &plane, const DynList<Point> &points, const DynList<Segment> &constraints,
1853 const Tikz_Style &triangle_style = tikz_wire_style("blue!60"),
1854 const Tikz_Style &constraint_style = tikz_path_style("red"), const bool draw_sites = true,
1855 const Tikz_Style &site_style = tikz_points_style("black"))
1856{
1857 auto result = algorithm(points, constraints);
1859 return result;
1860}
1861
1862// ---------- Minimum Enclosing Circle visualization ----------
1863
1871 const DynList<Point> &points,
1872 const Tikz_Style &circle_style = tikz_wire_style("blue!70"),
1873 const bool draw_sites = true,
1874 const Tikz_Style &site_style = tikz_points_style("black"),
1877{
1878 const Geom_Number r = circle.radius();
1880
1881 if (draw_sites)
1882 put_points(plane, points, site_style, site_layer);
1883}
1884
1891 Tikz_Plane &plane, const DynList<Point> &points, const MinimumEnclosingCircle &algorithm = {},
1892 const Tikz_Style &circle_style = tikz_wire_style("blue!70"), const bool draw_sites = true,
1893 const Tikz_Style &site_style = tikz_points_style("black"))
1894{
1895 auto circle = algorithm(points);
1896 put_mec_result(plane, circle, points, circle_style, draw_sites, site_style);
1897 return circle;
1898}
1899
1900// ==========================================================================
1901// Simplification visualization
1902// ==========================================================================
1903
1916 Tikz_Plane &plane, const Polygon &original, const Polygon &simplified,
1917 const Tikz_Style &original_style = tikz_wire_style("gray!50"),
1919 const bool draw_vertices = true, const Tikz_Style &vertex_style = tikz_points_style("red"))
1920{
1923 if (draw_vertices)
1925}
1926
1933 Tikz_Plane &plane, const Polygon &poly, const Geom_Number &epsilon,
1935 const Tikz_Style &original_style = tikz_wire_style("gray!50"),
1937 const bool draw_vertices = true, const Tikz_Style &vertex_style = tikz_points_style("red"))
1938{
1939 Polygon simplified = algorithm.simplify_polygon(poly, epsilon);
1942 return simplified;
1943}
1944
1951 Tikz_Plane &plane, const Polygon &poly, const Geom_Number &area_threshold,
1953 const Tikz_Style &original_style = tikz_wire_style("gray!50"),
1954 const Tikz_Style &simplified_style = tikz_bold_wire_style("green!70!black"),
1955 const bool draw_vertices = true, const Tikz_Style &vertex_style = tikz_points_style("red"))
1956{
1957 Polygon simplified = algorithm.simplify_polygon(poly, area_threshold);
1960 return simplified;
1961}
1962
1963// ==========================================================================
1964// Polygon offset visualization
1965// ==========================================================================
1966
1979 const PolygonOffset::Result &result,
1980 const Tikz_Style &original_style = tikz_wire_style("gray!50"),
1981 const Tikz_Style &offset_style = tikz_bold_wire_style("blue!80"),
1982 const bool draw_vertices = true,
1984{
1986 for (size_t i = 0; i < result.polygons.size(); ++i)
1987 {
1988 put_in_plane(plane, result.polygons(i), offset_style);
1989 if (draw_vertices)
1990 put_polygon_vertices(plane, result.polygons(i), vertex_style);
1991 }
1992}
1993
2000 Tikz_Plane &plane, const Polygon &poly, const Geom_Number &distance,
2003 const Tikz_Style &original_style = tikz_wire_style("gray!50"),
2004 const Tikz_Style &offset_style = tikz_bold_wire_style("blue!80"), const bool draw_vertices = true,
2006{
2007 PolygonOffset::Result result = algorithm(poly, distance, join, miter_limit);
2009 return result;
2010}
2011
2012// ==========================================================================
2013// Chaikin smoothing visualization
2014// ==========================================================================
2015
2028 const Tikz_Style &original_style = tikz_wire_style("gray!50"),
2029 const Tikz_Style &smoothed_style = tikz_bold_wire_style("violet!80"),
2030 const bool draw_vertices = true,
2032{
2035 if (draw_vertices)
2037}
2038
2045 Tikz_Plane &plane, const Polygon &poly, const size_t iterations,
2046 const Geom_Number &ratio = Geom_Number(1, 4),
2047 const Tikz_Style &original_style = tikz_wire_style("gray!50"),
2048 const Tikz_Style &smoothed_style = tikz_bold_wire_style("violet!80"),
2049 const bool draw_vertices = true, const Tikz_Style &vertex_style = tikz_points_style("red"))
2050{
2051 Polygon smoothed = ChaikinSmoothing::smooth_polygon(poly, iterations, ratio);
2053 vertex_style);
2054 return smoothed;
2055}
2056
2057// ==========================================================================
2058// Trapezoidal Map Visualization
2059// ==========================================================================
2060
2074 const Tikz_Style &extension_style = tikz_wire_style("gray!60", true),
2075 const bool draw_trapezoids = true, const double trapezoid_opacity = 0.3,
2078{
2080 constexpr size_t NONE = TrapezoidalMapPointLocation::NONE;
2081
2082 // Draw filled trapezoids.
2083 if (draw_trapezoids)
2084 {
2085 size_t color_idx = 0;
2086 for (size_t i = 0; i < res.trapezoids.size(); ++i)
2087 {
2088 const Trap &t = res.trapezoids(i);
2089 if (not t.active)
2090 continue;
2091
2092 // A trapezoid has 4 corners defined by:
2093 // top-left: intersection of left vertical with top segment
2094 // top-right: intersection of right vertical with top segment
2095 // bot-right: intersection of right vertical with bottom segment
2096 // bot-left: intersection of left vertical with bottom segment
2097 // For simplicity, approximate corners using the endpoints
2098 // and the x-coordinates of the left/right boundary points.
2099 const Point &lp = res.points(t.leftp);
2100 const Point &rp = res.points(t.rightp);
2101 const Segment &top_seg = res.segments(t.top);
2102 const Segment &bot_seg = res.segments(t.bottom);
2103
2104 // Compute y-coordinates at left and right x-boundaries.
2105 auto y_at_x = [](const Segment &seg, const Geom_Number &x) -> Geom_Number
2106 {
2107 const Geom_Number &x1 = seg.get_src_point().get_x();
2108 const Geom_Number &x2 = seg.get_tgt_point().get_x();
2109 const Geom_Number &y1 = seg.get_src_point().get_y();
2110 const Geom_Number &y2 = seg.get_tgt_point().get_y();
2111 if (x1 == x2)
2112 return (y1 + y2) / 2;
2113 return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
2114 };
2115
2116 const Geom_Number lx = lp.get_x();
2117 const Geom_Number rx = rp.get_x();
2118 if (lx == rx)
2119 {
2120 ++color_idx;
2121 continue;
2122 } // degenerate
2123
2124 const Point tl_corner(lx, y_at_x(top_seg, lx));
2125 const Point tr_corner(rx, y_at_x(top_seg, rx));
2126 const Point br_corner(rx, y_at_x(bot_seg, rx));
2127 const Point bl_corner(lx, y_at_x(bot_seg, lx));
2128
2129 // Draw as 4 segments (avoids Polygon self-intersection checks
2130 // that can fail when corners are collinear).
2131 Tikz_Style ts;
2134 ts.opacity = trapezoid_opacity;
2135
2136 // Build polygon with try/catch — skip if degenerate.
2137 try
2138 {
2139 Polygon quad;
2141 quad.add_vertex(br_corner);
2142 quad.add_vertex(tr_corner);
2143 quad.add_vertex(tl_corner);
2144 quad.close();
2145 ts.fill = true;
2146 put_in_plane(plane, quad, ts, trap_layer);
2147 }
2148 catch (...)
2149 {
2150 // Degenerate quad — draw edges instead.
2155 }
2156 ++color_idx;
2157 }
2158 }
2159
2160 // Draw vertical extensions from input endpoints.
2161 for (size_t i = 0; i < res.num_input_points; ++i)
2162 {
2163 // Find the topmost and bottommost trapezoid boundaries at this point.
2164 // For simplicity, draw a short vertical dashed line through each
2165 // input point spanning the local trapezoid.
2166 const Point &p = res.points(i);
2167 // Walk the trapezoids to find the vertical extent at p.
2168 Geom_Number top_y = p.get_y();
2169 Geom_Number bot_y = p.get_y();
2170 for (size_t j = 0; j < res.trapezoids.size(); ++j)
2171 {
2172 const Trap &t = res.trapezoids(j);
2173 if (not t.active)
2174 continue;
2175 if (t.leftp == NONE or t.rightp == NONE)
2176 continue;
2177 const Point &lp = res.points(t.leftp);
2178 const Point &rp = res.points(t.rightp);
2179 if (p.get_x() < lp.get_x() or p.get_x() > rp.get_x())
2180 continue;
2181 // This trapezoid covers x-coordinate of p.
2182 auto y_at_x = [](const Segment &seg, const Geom_Number &x) -> Geom_Number
2183 {
2184 const Geom_Number &x1 = seg.get_src_point().get_x();
2185 const Geom_Number &x2 = seg.get_tgt_point().get_x();
2186 const Geom_Number &y1 = seg.get_src_point().get_y();
2187 const Geom_Number &y2 = seg.get_tgt_point().get_y();
2188 if (x1 == x2)
2189 return (y1 + y2) / 2;
2190 return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
2191 };
2192 const Geom_Number ty = y_at_x(res.segments(t.top), p.get_x());
2193 const Geom_Number by = y_at_x(res.segments(t.bottom), p.get_x());
2194 if (ty > top_y)
2195 top_y = ty;
2196 if (by < bot_y)
2197 bot_y = by;
2198 }
2199 if (top_y > bot_y)
2200 put_in_plane(plane, Segment(Point(p.get_x(), bot_y), Point(p.get_x(), top_y)),
2202 }
2203
2204 // Draw input segments.
2205 for (size_t i = 0; i < res.num_input_segments; ++i)
2206 put_in_plane(plane, res.segments(i), segment_style, seg_layer);
2207}
2208
2215 Tikz_Plane &plane, const Array<Segment> &segments,
2217 const Tikz_Style &extension_style = tikz_wire_style("gray!60", true),
2218 const bool draw_trapezoids = true, const double trapezoid_opacity = 0.3)
2219{
2221 auto result = tm(segments);
2224 return result;
2225}
2226
2231 Tikz_Plane &plane, const Polygon &polygon, const Tikz_Style &segment_style = tikz_path_style("red"),
2232 const Tikz_Style &extension_style = tikz_wire_style("gray!60", true),
2233 const bool draw_trapezoids = true, const double trapezoid_opacity = 0.3)
2234{
2236 auto result = tm(polygon);
2239 return result;
2240}
2241} // namespace Aleph
2242
2243#endif // TIKZGEOM_ALGORITHMS_H
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:527
static int cell(const aleph_ca_engine_t *e, size_t r, size_t c)
Definition c_abi_smoke.c:53
size_t size_t int32_t * out
Definition ca-c-api.h:120
Axis-aligned bounding box tree for spatial queries.
DebugSnapshot debug_snapshot() const
Return the full tree structure for visualization/debug.
Array< size_t > query(const Rectangle &query) const
Find all entries whose bounding box overlaps the query rectangle.
Alpha shape of a point set.
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:138
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
Definition tpl_array.H:365
T & append(const T &data)
Append a copy of data
Definition tpl_array.H:250
void reserve(size_t cap)
Reserves cap cells into the array.
Definition tpl_array.H:320
Boolean operations on simple polygons (union, intersection, difference) using the Greiner-Hormann alg...
Op
Type of Boolean operation to perform.
static Polygon smooth_polygon(const Polygon &poly, size_t iterations, const Geom_Number &ratio=Geom_Number(1, 4))
Smooth a closed polygon.
Closest pair of points via divide and conquer.
Constrained Delaunay Triangulation via Sloan's flip-based method.
Decompose a simple polygon into convex parts using Hertel-Mehlhorn.
Basic exact intersection for closed convex polygons.
Polygon triangulation using the ear-cutting algorithm.
Exact Delaunay triangulation using the Bowyer-Watson incremental algorithm.
Douglas-Peucker polyline simplification.
Iterator on the items of list.
Definition htlist.H:1420
Doubly-linked list (defined in tpl_dynList.H).
Definition htlist.H:1155
T & append(const T &item)
Definition htlist.H:1271
An axis-aligned ellipse.
Definition point.H:2076
bool has_curr() const noexcept
Definition htlist.H:930
constexpr bool is_empty() const noexcept
Definition htlist.H:419
Exact bounded intersection of half-planes.
Spatial point index for O(log n) nearest-neighbor queries.
Smallest circle enclosing a point set (Welzl's algorithm).
Exact Minkowski sum of two closed convex polygons.
O(n log n) triangulation of simple polygons via y-monotone partition + linear-time monotone triangula...
static bool contains(const Polygon &poly, const Point &p)
Return true if the point is inside or on the boundary.
Represents a point with rectangular coordinates in a 2D plane.
Definition point.H:221
const Geom_Number & get_x() const noexcept
Gets the x-coordinate value.
Definition point.H:448
const Geom_Number & get_y() const noexcept
Gets the y-coordinate value.
Definition point.H:457
Offset (inflate/deflate) an arbitrary simple polygon.
JoinType
Strategy for connecting offset edges at vertices.
@ Miter
Extend edges until they intersect.
Iterator over the edges (segments) of a polygon.
Definition polygon.H:521
bool has_curr() const
Check if there is a current segment.
Definition polygon.H:538
A general (irregular) 2D polygon defined by a sequence of vertices.
Definition polygon.H:247
void add_vertex(const Point &point)
Add a vertex to the polygon.
Definition polygon.H:678
void close()
Close the polygon.
Definition polygon.H:843
const bool & is_closed() const
Check if the polygon is closed.
Definition polygon.H:474
const size_t & size() const
Get the number of vertices.
Definition polygon.H:478
Power diagram (weighted Voronoi diagram).
Dynamic R-tree indexing axis-aligned rectangles by payload.
Definition tpl_r_tree.H:118
DebugSnapshot debug_snapshot() const
Capture the full tree structure for visualization/debugging.
void for_each_intersecting(const Rectangle &rect, F &&f) const
Invoke f for every entry whose bbox intersects rect.
Static 2D range tree for orthogonal range queries.
DynList< Point > query(const Geom_Number &xmin, const Geom_Number &xmax, const Geom_Number &ymin, const Geom_Number &ymax) const
Query: return all points inside [xmin,xmax] × [ymin,ymax].
DebugSnapshot debug_snapshot() const
Return structural snapshot for visualization/debug.
An axis-aligned rectangle.
Definition point.H:1789
const Geom_Number & get_xmin() const
Gets the minimum x-coordinate.
Definition point.H:1815
const Geom_Number & get_ymax() const
Gets the maximum y-coordinate.
Definition point.H:1830
const Geom_Number & get_ymin() const
Gets the minimum y-coordinate.
Definition point.H:1820
const Geom_Number & get_xmax() const
Gets the maximum x-coordinate.
Definition point.H:1825
Exact regular triangulation (weighted Delaunay) via Bowyer-Watson.
A regular polygon defined by center, side length, and vertex count.
Definition polygon.H:1135
Point get_vertex(const size_t &i) const
Get the i-th vertex of the polygon.
Definition polygon.H:1218
const size_t & size() const
Get the number of vertices.
Definition polygon.H:1196
static DiameterResult diameter(const Polygon &poly)
Compute convex polygon diameter (farthest vertex pair).
static WidthResult minimum_width(const Polygon &poly)
Compute the minimum width of a closed convex polygon.
Compute the full planar subdivision induced by a set of segments.
Represents a line segment between two points.
Definition point.H:837
bool intersects_properly_with(const Segment &s) const
Checks if this segment properly intersects another segment.
Definition point.H:1241
const Point & get_tgt_point() const noexcept
Gets the target point of the segment.
Definition point.H:933
const Point & get_src_point() const noexcept
Gets the source point of the segment.
Definition point.H:924
Compute the shortest Euclidean path between two points inside a simple polygon.
Report all pairwise intersection points among a set of segments.
2D TikZ canvas storing geometry objects and emitting LaTeX output.
Definition tikzgeom.H:200
static constexpr int Layer_Default
Definition tikzgeom.H:203
static constexpr int Layer_Foreground
Definition tikzgeom.H:204
static constexpr int Layer_Background
Definition tikzgeom.H:202
static constexpr int Layer_Overlay
Definition tikzgeom.H:205
O(log n) point location via trapezoidal map with DAG search.
A non-degenerate triangle defined by three points.
Definition point.H:1512
const Point & get_p3() const
Gets the third vertex.
Definition point.H:1629
const Point & get_p2() const
Gets the second vertex.
Definition point.H:1624
const Point & get_p1() const
Gets the first vertex.
Definition point.H:1619
Compute the visibility polygon from a point inside a simple polygon.
Visvalingam-Whyatt polyline simplification.
O(n log n) Voronoi diagram construction.
Computational geometry algorithms.
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_y1_function > > y1(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4114
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_y0_function > > y0(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4113
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
bool spp_point_in_triangle(const Array< Point > &pts, const SPP_ITri &t, const Point &p)
size_t spp_find_tri(const Array< Point > &pts, const Array< SPP_ITri > &tris, const Point &p)
constexpr size_t SPP_NONE
size_t spp_find_index(const Array< Point > &pts, const Point &p)
Array< size_t > spp_find_sleeve(const Array< SPP_ITri > &tris, const size_t src, const size_t dst)
std::string tikz_palette_color(const size_t idx)
Geom_Number spp_cross(const Point &a, const Point &b, const Point &c)
Array< SPP_Portal > shortest_path_portals(const Polygon &polygon, const Point &source, const Point &target)
Array< SPP_ITri > spp_build_tris(const Array< Point > &pts, const DynList< Triangle > &tl)
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
void put_convex_decomposition_result(Tikz_Plane &plane, const Array< Polygon > &parts, const bool color_parts_by_index=true, const Tikz_Style &part_style=tikz_area_style("blue!60!black", "blue!15", 0.40), const int part_layer=Tikz_Plane::Layer_Default)
Insert convex decomposition polygons.
void put_half_plane_intersection_result(Tikz_Plane &plane, const Array< HalfPlaneIntersection::HalfPlane > &halfplanes, const Polygon &intersection, const Tikz_Style &boundary_style=tikz_wire_style("gray!60", true, true), const Tikz_Style &result_style=tikz_area_style("red", "red!25", 0.50), const int boundary_layer=Tikz_Plane::Layer_Default, const int result_layer=Tikz_Plane::Layer_Foreground)
Draw half-plane boundaries and their bounded intersection polygon.
AABBTreeQueryVizResult visualize_aabb_tree_query(Tikz_Plane &plane, const AABBTree &tree, const Rectangle &query_rect, const Tikz_Style &node_bbox_style=tikz_wire_style("teal!70!black"), const Tikz_Style &leaf_bbox_style=tikz_wire_style("blue!70"), const Tikz_Style &query_rect_style=tikz_wire_style("red", true), const Tikz_Style &query_hit_style=tikz_wire_style("red"))
Visualize AABB tree with a rectangle query overlay.
void put_rtree_result(Tikz_Plane &plane, const Snapshot &snapshot, const Rectangle *query_rect=nullptr, const Array< Rectangle > *query_hit_boxes=nullptr, const Tikz_Style &node_bbox_style=tikz_wire_style("teal!70!black"), const Tikz_Style &leaf_bbox_style=tikz_wire_style("blue!70"), const Tikz_Style &entry_bbox_style=tikz_wire_style("gray!55"), const Tikz_Style &query_rect_style=tikz_wire_style("red", true), const Tikz_Style &query_hit_style=tikz_wire_style("red"), const int node_layer=Tikz_Plane::Layer_Default, const int entry_layer=Tikz_Plane::Layer_Default, const int query_layer=Tikz_Plane::Layer_Foreground)
Draw every node MBR (colored by depth) of an R-tree/R*-tree snapshot, plus its leaf entry boxes,...
void put_range_tree_result(Tikz_Plane &plane, const RangeTree2D::DebugSnapshot &snapshot, const bool draw_points=true, const Rectangle *query_rect=nullptr, const DynList< Point > *query_hits=nullptr, const Tikz_Style &split_style=tikz_wire_style("purple"), const Tikz_Style &point_style=tikz_points_style("black"), const Tikz_Style &query_rect_style=tikz_wire_style("red", true), const Tikz_Style &query_hit_style=tikz_points_style("red"), const int split_layer=Tikz_Plane::Layer_Default, const int point_layer=Tikz_Plane::Layer_Foreground)
Draw range-tree X-axis hierarchy and optional query highlights.
Polygon visualize_convex_intersection(Tikz_Plane &plane, const Polygon &subject, const Polygon &clip, const ConvexPolygonIntersectionBasic &intersection_algorithm={}, const Tikz_Style &subject_style=tikz_area_style("blue", "blue!15", 0.45), const Tikz_Style &clip_style=tikz_area_style("orange", "orange!20", 0.45), const Tikz_Style &result_style=tikz_area_style("red", "red!30", 0.60), const int input_layer=Tikz_Plane::Layer_Default, const int result_layer=Tikz_Plane::Layer_Foreground)
Visualizes the intersection of two convex polygons.
Orientation
Classification of three-point orientation.
Definition point.H:2894
AlphaShape::Result visualize_alpha_shape(Tikz_Plane &plane, const DynList< Point > &points, const Geom_Number &alpha_squared, const AlphaShape &algorithm={}, const bool draw_kept_triangles=false, const Tikz_Style &triangle_style=tikz_wire_style("gray!55"), const Tikz_Style &boundary_style=tikz_path_style("orange!90!black"), const bool draw_sites=true, const Tikz_Style &site_style=tikz_points_style("black"))
Compute and insert alpha-shape for input points.
void put_funnel_trace_step(Tikz_Plane &plane, const Polygon &polygon, const Point &source, const Point &target, const FunnelTraceResult &trace, size_t step_index, const Tikz_Style &polygon_style=tikz_area_style("black", "gray!15", 0.22), const Tikz_Style &source_style=tikz_points_style("green!50!black"), const Tikz_Style &target_style=tikz_points_style("blue"), const Tikz_Style &all_portals_style=tikz_wire_style("purple", true), const Tikz_Style &active_portal_style=tikz_path_style("purple"), const Tikz_Style &funnel_leg_style=tikz_path_style("orange!90!black"), const Tikz_Style &committed_style=tikz_path_style("red"), const bool draw_waypoints=true, const Tikz_Style &waypoint_style=tikz_points_style("red"), const int polygon_layer=Tikz_Plane::Layer_Default, const int portal_layer=Tikz_Plane::Layer_Foreground, const int highlight_layer=Tikz_Plane::Layer_Overlay)
Render one funnel-trace frame in a plane.
PolygonOffset::Result visualize_polygon_offset(Tikz_Plane &plane, const Polygon &poly, const Geom_Number &distance, const PolygonOffset &algorithm={}, PolygonOffset::JoinType join=PolygonOffset::JoinType::Miter, const Geom_Number &miter_limit=Geom_Number(2), const Tikz_Style &original_style=tikz_wire_style("gray!50"), const Tikz_Style &offset_style=tikz_bold_wire_style("blue!80"), const bool draw_vertices=true, const Tikz_Style &vertex_style=tikz_points_style("red"))
Offset a polygon and draw the result.
Tikz_Style tikz_bold_wire_style(const std::string &color, const double width_mm=1.2)
Creates a solid wireframe style with an explicit line width.
void put_visibility_polygon_result(Tikz_Plane &plane, const Polygon &polygon, const Point &query_point, const Polygon &visibility_polygon, const Tikz_Style &polygon_style=tikz_wire_style("black"), const Tikz_Style &visibility_style=tikz_area_style("orange!90!black", "orange!25", 0.50), const Tikz_Style &query_style=tikz_points_style("red"), const int polygon_layer=Tikz_Plane::Layer_Default, const int visibility_layer=Tikz_Plane::Layer_Foreground)
Draw visibility polygon with source polygon and query point.
void put_rotating_calipers_result(Tikz_Plane &plane, const Polygon &polygon, const RotatingCalipersResult &result, const Tikz_Style &polygon_style=tikz_wire_style("gray!55"), const Tikz_Style &diameter_style=tikz_path_style("red"), const Tikz_Style &width_style=tikz_path_style("blue"), const Tikz_Style &witness_style=tikz_points_style("orange!90!black"), const int polygon_layer=Tikz_Plane::Layer_Default, const int witness_layer=Tikz_Plane::Layer_Foreground)
Draw diameter and minimum-width witnesses for a convex polygon.
@ Trap
Unreachable code path marker.
Polygon visualize_visvalingam_whyatt(Tikz_Plane &plane, const Polygon &poly, const Geom_Number &area_threshold, const VisvalingamWhyattSimplification &algorithm={}, const Tikz_Style &original_style=tikz_wire_style("gray!50"), const Tikz_Style &simplified_style=tikz_bold_wire_style("green!70!black"), const bool draw_vertices=true, const Tikz_Style &vertex_style=tikz_points_style("red"))
Simplify a polygon with Visvalingam-Whyatt and draw the result.
void put_cdt_result(Tikz_Plane &plane, const ConstrainedDelaunayTriangulation::Result &cdt, const Tikz_Style &triangle_style=tikz_wire_style("blue!60"), const Tikz_Style &constraint_style=tikz_path_style("red"), const bool draw_sites=true, const Tikz_Style &site_style=tikz_points_style("black"), const int triangle_layer=Tikz_Plane::Layer_Default, const int constraint_layer=Tikz_Plane::Layer_Foreground, const int site_layer=Tikz_Plane::Layer_Overlay)
Insert constrained Delaunay triangulation result.
AABBTree::DebugSnapshot visualize_aabb_tree(Tikz_Plane &plane, const AABBTree &tree, const Tikz_Style &node_bbox_style=tikz_wire_style("teal!70!black"), const Tikz_Style &leaf_bbox_style=tikz_wire_style("blue!70"))
Visualize AABB tree hierarchy.
MinimumEnclosingCircle::Circle visualize_mec(Tikz_Plane &plane, const DynList< Point > &points, const MinimumEnclosingCircle &algorithm={}, const Tikz_Style &circle_style=tikz_wire_style("blue!70"), const bool draw_sites=true, const Tikz_Style &site_style=tikz_points_style("black"))
Compute minimum enclosing circle and insert into plane.
RangeTreeQueryVizResult visualize_range_tree_query(Tikz_Plane &plane, const RangeTree2D &tree, const Rectangle &query_rect, const bool draw_points=true, const Tikz_Style &split_style=tikz_wire_style("purple"), const Tikz_Style &point_style=tikz_points_style("black"), const Tikz_Style &query_rect_style=tikz_wire_style("red", true), const Tikz_Style &query_hit_style=tikz_points_style("red"))
Visualize range-tree plus a query rectangle and matching points.
PowerDiagram::Result visualize_power_diagram(Tikz_Plane &plane, const Array< PowerDiagram::WeightedSite > &sites, const PowerDiagram &algorithm={}, const bool draw_cells=true, const Tikz_Style &cell_style=tikz_area_style("violet", "violet!18", 0.35), const Tikz_Style &edge_style=tikz_wire_style("violet"), const Tikz_Style &site_style=tikz_points_style("purple"))
Compute and insert Power diagram for weighted sites.
void put_alpha_shape_result(Tikz_Plane &plane, const AlphaShape::Result &alpha_shape, const bool draw_kept_triangles=false, const Tikz_Style &triangle_style=tikz_wire_style("gray!55"), const Tikz_Style &boundary_style=tikz_path_style("orange!90!black"), const bool draw_sites=true, const Tikz_Style &site_style=tikz_points_style("black"), const int triangle_layer=Tikz_Plane::Layer_Background, const int boundary_layer=Tikz_Plane::Layer_Foreground, const int site_layer=Tikz_Plane::Layer_Overlay)
Insert alpha-shape structures (kept triangles, boundary, sites).
DelaunayTriangulationBowyerWatson::Result visualize_delaunay(Tikz_Plane &plane, const DynList< Point > &points, const DelaunayTriangulationBowyerWatson &algorithm={}, const Tikz_Style &triangle_style=tikz_wire_style("blue"), const bool draw_sites=true, const Tikz_Style &site_style=tikz_points_style("black"))
Compute and insert Delaunay triangulation as triangle outlines.
RangeTree2D::DebugSnapshot visualize_range_tree(Tikz_Plane &plane, const RangeTree2D &tree, const bool draw_points=true, const Tikz_Style &split_style=tikz_wire_style("purple"), const Tikz_Style &point_style=tikz_points_style("black"))
Visualize range-tree structure without a query overlay.
void put_monotone_triangulation_result(Tikz_Plane &plane, const Polygon &polygon, const DynList< Triangle > &triangles, const Tikz_Style &polygon_style=tikz_wire_style("black"), const Tikz_Style &triangle_style=tikz_wire_style("blue!65"), const int polygon_layer=Tikz_Plane::Layer_Default, const int triangle_layer=Tikz_Plane::Layer_Foreground)
Draw a monotone triangulation result plus polygon boundary.
VoronoiDiagram::Result visualize_voronoi(Tikz_Plane &plane, const DynList< Point > &sites, const VoronoiDiagram &algorithm={}, const bool draw_cells=false, const Tikz_Style &cell_style=tikz_area_style("gray!50!black", "gray!15", 0.35), const Tikz_Style &edge_style=tikz_wire_style("black"), const Tikz_Style &unbounded_edge_style=tikz_wire_style("black", true, true), const Tikz_Style &site_style=tikz_points_style("red"), const Geom_Number &unbounded_ray_length=Geom_Number(50))
Compute and insert Voronoi diagram for input sites.
RegularTriangulationBowyerWatson::Result visualize_regular_triangulation(Tikz_Plane &plane, const Array< RegularTriangulationBowyerWatson::WeightedSite > &weighted_sites, const RegularTriangulationBowyerWatson &algorithm={}, const Tikz_Style &triangle_style=tikz_wire_style("blue!60"), const bool draw_sites=true, const Tikz_Style &site_style=tikz_points_style("black"))
Compute and insert regular (weighted Delaunay) triangulation.
Polygon visualize_half_plane_intersection(Tikz_Plane &plane, const Array< HalfPlaneIntersection::HalfPlane > &halfplanes, const HalfPlaneIntersection &algorithm={}, const Tikz_Style &boundary_style=tikz_wire_style("gray!60", true, true), const Tikz_Style &result_style=tikz_area_style("red", "red!25", 0.50))
Compute and draw bounded half-plane intersection.
TrapezoidalMapPointLocation::Result visualize_trapezoidal_map(Tikz_Plane &plane, const Array< Segment > &segments, const Tikz_Style &segment_style=tikz_path_style("red"), const Tikz_Style &extension_style=tikz_wire_style("gray!60", true), const bool draw_trapezoids=true, const double trapezoid_opacity=0.3)
Build a trapezoidal map and draw it.
Polygon polygon_from_vertex_indices(const Array< Point > &vertices, const DynList< size_t > &indices, const bool close=true)
Constructs a Polygon from a list of indices into a vertex array.
void put_in_plane(Tikz_Plane &plane, const Geom &geom_obj)
Insert any supported geometry type in a Tikz_Plane.
Definition tikzgeom.H:1511
RTree< Payload, MaxEntries, MinEntries, Variant >::DebugSnapshot visualize_rtree(Tikz_Plane &plane, const RTree< Payload, MaxEntries, MinEntries, Variant > &tree, const Tikz_Style &node_bbox_style=tikz_wire_style("teal!70!black"), const Tikz_Style &leaf_bbox_style=tikz_wire_style("blue!70"), const Tikz_Style &entry_bbox_style=tikz_wire_style("gray!55"))
Visualize an R-tree/R*-tree hierarchy (node MBRs by depth, plus leaf entry boxes).
Polygon visualize_visibility_polygon(Tikz_Plane &plane, const Polygon &polygon, const Point &query_point, const VisibilityPolygon &algorithm={}, const Tikz_Style &polygon_style=tikz_wire_style("black"), const Tikz_Style &visibility_style=tikz_area_style("orange!90!black", "orange!25", 0.50), const Tikz_Style &query_style=tikz_points_style("red"))
Compute and draw visibility polygon from a query point.
and
Check uniqueness with explicit hash + equality functors.
void put_mec_result(Tikz_Plane &plane, const MinimumEnclosingCircle::Circle &circle, const DynList< Point > &points, const Tikz_Style &circle_style=tikz_wire_style("blue!70"), const bool draw_sites=true, const Tikz_Style &site_style=tikz_points_style("black"), const int circle_layer=Tikz_Plane::Layer_Default, const int site_layer=Tikz_Plane::Layer_Overlay)
Draw a precomputed minimum enclosing circle result.
Polygon polygon_from_vertices(const Array< Point > &vertices, const bool close=true)
Constructs a Polygon from an ordered array of vertices.
void put_minkowski_sum_result(Tikz_Plane &plane, const Polygon &first, const Polygon &second, const Polygon &result, const Tikz_Style &first_style=tikz_area_style("blue", "blue!14", 0.30), const Tikz_Style &second_style=tikz_area_style("green!60!black", "green!16", 0.30), const Tikz_Style &result_style=tikz_area_style("red", "red!26", 0.60), const int input_layer=Tikz_Plane::Layer_Default, const int result_layer=Tikz_Plane::Layer_Foreground)
Draw input polygons and their Minkowski sum result.
void put_closest_pair_result(Tikz_Plane &plane, const DynList< Point > &points, const ClosestPairDivideAndConquer::Result &result, const Tikz_Style &points_style=tikz_points_style("black"), const Tikz_Style &pair_style=tikz_path_style("red"), const Tikz_Style &pair_points_style=tikz_points_style("red"), const int points_layer=Tikz_Plane::Layer_Default, const int pair_layer=Tikz_Plane::Layer_Foreground)
Draw closest-pair result over the full point set.
void put_segment_arrangement_result(Tikz_Plane &plane, const SegmentArrangement::Result &arrangement, const bool draw_faces=true, const bool draw_vertices=true, const bool draw_unbounded_face=false, const Tikz_Style &face_style=tikz_area_style("teal!60!black", "teal!12", 0.30), const Tikz_Style &edge_style=tikz_wire_style("teal!70!black"), const Tikz_Style &vertex_style=tikz_points_style("teal!70!black"), const int face_layer=Tikz_Plane::Layer_Background, const int edge_layer=Tikz_Plane::Layer_Default, const int vertex_layer=Tikz_Plane::Layer_Foreground, const bool color_faces_by_index=false)
Insert segment arrangement structures (faces, edges, vertices).
void put_kdtree_partitions_result(Tikz_Plane &plane, const KDTreePointSearch::DebugSnapshot &snapshot, const bool draw_partition_boxes=false, const bool draw_points=true, const Tikz_Style &partition_style=tikz_wire_style("gray!55", true), const Tikz_Style &split_style=tikz_wire_style("blue!70"), const Tikz_Style &point_style=tikz_points_style("red"), const int partition_layer=Tikz_Plane::Layer_Background, const int split_layer=Tikz_Plane::Layer_Default, const int point_layer=Tikz_Plane::Layer_Foreground)
Draw KD-tree partitions from a debug snapshot.
Geom_Number square_root(const Geom_Number &x)
Square root of x (wrapper over mpfr).
Definition point.H:197
static void prefix(Node *root, DynList< Node * > &acc)
ShortestPathDebugResult visualize_shortest_path_with_portals(Tikz_Plane &plane, const Polygon &polygon, const Point &source, const Point &target, const ShortestPathInPolygon &algorithm={}, const Tikz_Style &polygon_style=tikz_area_style("black", "gray!15", 0.25), const Tikz_Style &source_style=tikz_points_style("green!50!black"), const Tikz_Style &target_style=tikz_points_style("blue"), const Tikz_Style &portal_style=tikz_wire_style("purple", true), const Tikz_Style &path_style=tikz_path_style("red"), const bool draw_waypoints=true, const Tikz_Style &waypoint_style=tikz_points_style("red"), const int polygon_layer=Tikz_Plane::Layer_Default, const int portal_layer=Tikz_Plane::Layer_Foreground, const int path_layer=Tikz_Plane::Layer_Overlay)
Visualize the shortest path plus funnel portals.
void put_polygon_vertices(Tikz_Plane &plane, const Polygon &poly, const Tikz_Style &style=tikz_points_style(), const int layer=Tikz_Plane::Layer_Overlay)
Inserts the vertices of a polygon as styled points.
Array< SweepLineSegmentIntersection::Intersection > visualize_line_sweep(Tikz_Plane &plane, const Array< Segment > &segments, const SweepLineSegmentIntersection &algorithm={}, const Tikz_Style &segment_style=tikz_wire_style("blue!60"), const Tikz_Style &intersection_style=tikz_points_style("red"))
Compute and draw Bentley-Ottmann line-sweep intersections.
void put_regular_triangulation_result(Tikz_Plane &plane, const RegularTriangulationBowyerWatson::Result &rt, const Tikz_Style &triangle_style=tikz_wire_style("blue!60"), const bool draw_sites=true, const Tikz_Style &site_style=tikz_points_style("black"), const int triangle_layer=Tikz_Plane::Layer_Default, const int site_layer=Tikz_Plane::Layer_Foreground)
Draw regular (weighted Delaunay) triangulation output.
KDTreePointSearch::DebugSnapshot visualize_kdtree_partitions(Tikz_Plane &plane, const KDTreePointSearch &kd_tree, const bool draw_partition_boxes=false, const bool draw_points=true, const Tikz_Style &partition_style=tikz_wire_style("gray!55", true), const Tikz_Style &split_style=tikz_wire_style("blue!70"), const Tikz_Style &point_style=tikz_points_style("red"))
Visualize KD-tree recursive space partitions.
Tikz_Style tikz_path_style(const std::string &color="red", const bool with_arrow=false)
Creates a style optimized for polyline paths.
void put_points(Tikz_Plane &plane, const Array< Point > &pts, const Tikz_Style &style=tikz_points_style(), const int layer=Tikz_Plane::Layer_Default)
Inserts all points from an Array<Point> into the plane.
void put_offset_result(Tikz_Plane &plane, const Polygon &original, const PolygonOffset::Result &result, const Tikz_Style &original_style=tikz_wire_style("gray!50"), const Tikz_Style &offset_style=tikz_bold_wire_style("blue!80"), const bool draw_vertices=true, const Tikz_Style &vertex_style=tikz_points_style("red"))
Draw a polygon offset result overlaid on the original polygon.
void put_simplification_result(Tikz_Plane &plane, const Polygon &original, const Polygon &simplified, const Tikz_Style &original_style=tikz_wire_style("gray!50"), const Tikz_Style &simplified_style=tikz_bold_wire_style("blue!80"), const bool draw_vertices=true, const Tikz_Style &vertex_style=tikz_points_style("red"))
Draw original and simplified polygons overlaid.
void put_power_diagram_result(Tikz_Plane &plane, const PowerDiagram::Result &pd, const bool draw_cells=true, const Tikz_Style &cell_style=tikz_area_style("violet", "violet!18", 0.35), const Tikz_Style &edge_style=tikz_wire_style("violet"), const Tikz_Style &site_style=tikz_points_style("purple"), const int cell_layer=Tikz_Plane::Layer_Background, const int edge_layer=Tikz_Plane::Layer_Default, const int site_layer=Tikz_Plane::Layer_Foreground)
Insert Power diagram structures (cells, edges, weighted sites).
Orientation orientation(const Point &a, const Point &b, const Point &c)
Return the orientation of the triple (a, b, c).
Definition point.H:2902
void put_polygons(Tikz_Plane &plane, const Array< Polygon > &polys, const Tikz_Style &style=tikz_wire_style(), const int layer=Tikz_Plane::Layer_Default)
Inserts all polygons from an Array<Polygon> into the plane.
void put_voronoi_result(Tikz_Plane &plane, const VoronoiResult &vor, const bool draw_cells=false, const Tikz_Style &cell_style=tikz_area_style("gray!50!black", "gray!15", 0.35), const Tikz_Style &edge_style=tikz_wire_style("black"), const Tikz_Style &unbounded_edge_style=tikz_wire_style("black", true, true), const Tikz_Style &site_style=tikz_points_style("red"), const Geom_Number &unbounded_ray_length=Geom_Number(50), const int cell_layer=Tikz_Plane::Layer_Background, const int edge_layer=Tikz_Plane::Layer_Default, const int site_layer=Tikz_Plane::Layer_Foreground)
Insert Voronoi diagram structures (cells, edges, sites).
mpq_class Geom_Number
Numeric type used by the geometry module.
Definition point.H:113
DynList< Point > visualize_shortest_path_in_polygon(Tikz_Plane &plane, const Polygon &polygon, const Point &source, const Point &target, const ShortestPathInPolygon &algorithm={}, const Tikz_Style &polygon_style=tikz_area_style("black", "gray!15", 0.25), const Tikz_Style &source_style=tikz_points_style("green!50!black"), const Tikz_Style &target_style=tikz_points_style("blue"), const Tikz_Style &path_style=tikz_path_style("red"), const bool draw_waypoints=true, const Tikz_Style &waypoint_style=tikz_points_style("red"), const int polygon_layer=Tikz_Plane::Layer_Default, const int path_layer=Tikz_Plane::Layer_Foreground)
Visualize the shortest path inside a simple polygon.
void put_point_label_in_plane(Tikz_Plane &plane, const Point &point, const std::string &label, const std::string &placement="above", const Tikz_Style &style=make_tikz_draw_style("black"), const int layer=Tikz_Plane::Layer_Overlay)
Insert a point label with configurable placement (above, etc.).
Definition tikzgeom.H:1616
ClosestPairDivideAndConquer::Result visualize_closest_pair(Tikz_Plane &plane, const DynList< Point > &points, const ClosestPairDivideAndConquer &algorithm={}, const Tikz_Style &points_style=tikz_points_style("black"), const Tikz_Style &pair_style=tikz_path_style("red"), const Tikz_Style &pair_points_style=tikz_points_style("red"))
Compute and draw the closest pair from an input point set.
void put_point_labels(Tikz_Plane &plane, const Array< Point > &pts, const std::string &prefix="p", const std::string &placement="above right", const Tikz_Style &style=make_tikz_draw_style("black"), const int layer=Tikz_Plane::Layer_Overlay)
Adds a text label to each point in an Array<Point>.
void put_line_sweep_result(Tikz_Plane &plane, const Array< Segment > &segments, const Array< SweepLineSegmentIntersection::Intersection > &intersections, const Tikz_Style &segment_style=tikz_wire_style("blue!60"), const Tikz_Style &intersection_style=tikz_points_style("red"), const int segment_layer=Tikz_Plane::Layer_Default, const int intersection_layer=Tikz_Plane::Layer_Foreground)
Draw line segments and all sweep-line intersection points.
RTreeQueryVizResult< Payload, MaxEntries, MinEntries, Variant > visualize_rtree_query(Tikz_Plane &plane, const RTree< Payload, MaxEntries, MinEntries, Variant > &tree, const Rectangle &query_rect, const Tikz_Style &node_bbox_style=tikz_wire_style("teal!70!black"), const Tikz_Style &leaf_bbox_style=tikz_wire_style("blue!70"), const Tikz_Style &entry_bbox_style=tikz_wire_style("gray!55"), const Tikz_Style &query_rect_style=tikz_wire_style("red", true), const Tikz_Style &query_hit_style=tikz_wire_style("red"))
Visualize an R-tree/R*-tree with a rectangle query overlay, highlighting every entry whose bbox inter...
RotatingCalipersResult visualize_rotating_calipers(Tikz_Plane &plane, const Polygon &polygon, const Tikz_Style &polygon_style=tikz_wire_style("gray!55"), const Tikz_Style &diameter_style=tikz_path_style("red"), const Tikz_Style &width_style=tikz_path_style("blue"), const Tikz_Style &witness_style=tikz_points_style("orange!90!black"))
Compute and draw rotating-calipers diameter and minimum width.
Tikz_Style make_tikz_draw_style(const std::string &draw_color)
Create a basic draw style with a custom color.
Definition tikzgeom.H:172
Polygon visualize_chaikin_smoothing(Tikz_Plane &plane, const Polygon &poly, const size_t iterations, const Geom_Number &ratio=Geom_Number(1, 4), const Tikz_Style &original_style=tikz_wire_style("gray!50"), const Tikz_Style &smoothed_style=tikz_bold_wire_style("violet!80"), const bool draw_vertices=true, const Tikz_Style &vertex_style=tikz_points_style("red"))
Smooth a polygon with Chaikin subdivision and draw the result.
void put_aabb_tree_result(Tikz_Plane &plane, const AABBTree::DebugSnapshot &snapshot, const Rectangle *query_rect=nullptr, const Array< size_t > *query_hit_ids=nullptr, const Tikz_Style &node_bbox_style=tikz_wire_style("teal!70!black"), const Tikz_Style &leaf_bbox_style=tikz_wire_style("blue!70"), const Tikz_Style &query_rect_style=tikz_wire_style("red", true), const Tikz_Style &query_hit_style=tikz_wire_style("red"), const int node_layer=Tikz_Plane::Layer_Default, const int query_layer=Tikz_Plane::Layer_Foreground)
Draw AABB tree hierarchy and optional query results.
std::ostream & join(const C &c, const std::string &sep, std::ostream &out)
Join elements of an Aleph-style container into a stream.
Point ray_endpoint(const Point &src, const Point &direction, const Geom_Number &length)
Tikz_Style tikz_wire_style(const std::string &color="black", const bool dashed=false, const bool with_arrow=false)
Creates a style optimized for wireframe segments and polygons.
void put_trapezoidal_map_result(Tikz_Plane &plane, const TrapezoidalMapPointLocation::Result &res, const Tikz_Style &segment_style=tikz_path_style("red"), const Tikz_Style &extension_style=tikz_wire_style("gray!60", true), const bool draw_trapezoids=true, const double trapezoid_opacity=0.3, const int trap_layer=Tikz_Plane::Layer_Background, const int seg_layer=Tikz_Plane::Layer_Foreground, const int ext_layer=Tikz_Plane::Layer_Default)
Draw the trapezoidal map result into a Tikz_Plane.
ConstrainedDelaunayTriangulation::Result visualize_cdt(Tikz_Plane &plane, const DynList< Point > &points, const DynList< Segment > &constraints, const ConstrainedDelaunayTriangulation &algorithm={}, const Tikz_Style &triangle_style=tikz_wire_style("blue!60"), const Tikz_Style &constraint_style=tikz_path_style("red"), const bool draw_sites=true, const Tikz_Style &site_style=tikz_points_style("black"))
Compute and insert constrained Delaunay triangulation.
SegmentArrangement::Result visualize_segment_arrangement(Tikz_Plane &plane, const Array< Segment > &segments, const SegmentArrangement &algorithm={}, const bool draw_faces=true, const bool draw_vertices=true, const bool draw_unbounded_face=false, const Tikz_Style &face_style=tikz_area_style("teal!60!black", "teal!12", 0.30), const Tikz_Style &edge_style=tikz_wire_style("teal!70!black"), const Tikz_Style &vertex_style=tikz_points_style("teal!70!black"), const bool color_faces_by_index=false)
Compute and insert arrangement for input segments.
Polygon visualize_minkowski_sum(Tikz_Plane &plane, const Polygon &first, const Polygon &second, const MinkowskiSumConvex &algorithm={}, const Tikz_Style &first_style=tikz_area_style("blue", "blue!14", 0.30), const Tikz_Style &second_style=tikz_area_style("green!60!black", "green!16", 0.30), const Tikz_Style &result_style=tikz_area_style("red", "red!26", 0.60))
Compute and draw Minkowski sum of two convex polygons.
Array< Polygon > visualize_boolean_operation(Tikz_Plane &plane, const Polygon &a, const Polygon &b, const BooleanPolygonOperations::Op op, const BooleanPolygonOperations &bop={}, const Tikz_Style &a_style=tikz_area_style("blue", "blue!15", 0.35), const Tikz_Style &b_style=tikz_area_style("green!60!black", "green!20", 0.35), const Tikz_Style &result_style=tikz_area_style("red", "red!35", 0.65), const int input_layer=Tikz_Plane::Layer_Default, const int result_layer=Tikz_Plane::Layer_Foreground)
Visualizes a boolean operation (union, intersection, difference) on two polygons.
Polygon visualize_douglas_peucker(Tikz_Plane &plane, const Polygon &poly, const Geom_Number &epsilon, const DouglasPeuckerSimplification &algorithm={}, const Tikz_Style &original_style=tikz_wire_style("gray!50"), const Tikz_Style &simplified_style=tikz_bold_wire_style("blue!80"), const bool draw_vertices=true, const Tikz_Style &vertex_style=tikz_points_style("red"))
Simplify a polygon with Douglas-Peucker and draw the result.
FunnelTraceResult compute_shortest_path_funnel_trace(const Polygon &polygon, const Point &source, const Point &target)
Compute a full SSFA trace (portal-by-portal states).
void put_smoothing_result(Tikz_Plane &plane, const Polygon &original, const Polygon &smoothed, const Tikz_Style &original_style=tikz_wire_style("gray!50"), const Tikz_Style &smoothed_style=tikz_bold_wire_style("violet!80"), const bool draw_vertices=true, const Tikz_Style &vertex_style=tikz_points_style("red"))
Draw original and smoothed polygons overlaid.
void put_portals(Tikz_Plane &plane, const Array< FunnelPortal > &portals, const bool skip_degenerate=true, const Tikz_Style &portal_style=tikz_wire_style("purple", true), const int portal_layer=Tikz_Plane::Layer_Default)
Insert funnel portals as segment connectors.
DynList< Triangle > visualize_monotone_triangulation(Tikz_Plane &plane, const Polygon &polygon, const MonotonePolygonTriangulation &algorithm={}, const Tikz_Style &polygon_style=tikz_wire_style("black"), const Tikz_Style &triangle_style=tikz_wire_style("blue!65"))
Compute and draw triangulation via monotone partition pipeline.
Tikz_Style tikz_area_style(const std::string &draw_color="black", const std::string &fill_color="gray!25", const double opacity=0.6)
Creates a style for drawing filled polygons.
Polygon visualize_convex_hull(Tikz_Plane &plane, const DynList< Point > &points, const HullAlgorithm &hull_algorithm, const Tikz_Style &point_style=tikz_points_style("black", 0.6), const Tikz_Style &hull_style=tikz_wire_style("red"), const Tikz_Style &hull_vertex_style=tikz_points_style("red"), const int point_layer=Tikz_Plane::Layer_Default, const int hull_layer=Tikz_Plane::Layer_Foreground, const bool draw_hull_vertices=true)
Runs a convex hull algorithm and visualizes the result.
void put_delaunay_result(Tikz_Plane &plane, const DelaunayTriangulationBowyerWatson::Result &dt, const Tikz_Style &triangle_style=tikz_wire_style("blue"), const bool draw_sites=true, const Tikz_Style &site_style=tikz_points_style("black"), const int triangle_layer=Tikz_Plane::Layer_Default, const int site_layer=Tikz_Plane::Layer_Foreground)
Insert Delaunay triangulation as triangle outlines.
Tikz_Style tikz_points_style(const std::string &color="black", const double opacity=-1.0)
Creates a style optimized for point clouds.
Array< Polygon > visualize_convex_decomposition(Tikz_Plane &plane, const Polygon &polygon, const ConvexPolygonDecomposition &algorithm={}, const bool draw_input_polygon=true, const Tikz_Style &input_style=tikz_wire_style("black", true), const bool color_parts_by_index=true, const Tikz_Style &part_style=tikz_area_style("blue!60!black", "blue!15", 0.40), const int input_layer=Tikz_Plane::Layer_Default, const int part_layer=Tikz_Plane::Layer_Foreground)
Compute and insert convex decomposition for a polygon.
void put_path(Tikz_Plane &plane, const DynList< Point > &path, const Tikz_Style &segment_style=tikz_path_style("red"), const bool draw_waypoints=true, const Tikz_Style &waypoint_style=tikz_points_style("red"), const int segment_layer=Tikz_Plane::Layer_Foreground, const int waypoint_layer=Tikz_Plane::Layer_Overlay)
Insert a point path as connected segments and optional waypoints.
static long & color(typename GT::Node *p)
void quicksort_op(C< T > &a, const Compare &cmp=Compare(), const size_t threshold=Quicksort_Threshold)
Optimized quicksort for containers using operator().
Result bundle for AABB query visualization.
A snapshot of the entire tree for debugging.
Array< DebugNode > nodes
Array of all nodes in debug format.
Result of an alpha-shape computation.
The result of a Delaunay triangulation.
Array< IndexedTriangle > triangles
Triangles forming the Delaunay triangulation.
Array< Point > sites
Unique, sorted input points used for triangulation.
Full trace for shortest-path funnel processing.
Array< FunnelPortal > portals
Array< FunnelTraceStep > steps
One SSFA (funnel) iteration snapshot.
A complete snapshot of the tree for debugging.
Array< DebugPartition > partitions
List of all internal and leaf partitions.
Array< Point > points
All points stored in the tree.
Result type: a circle defined by center and squared radius.
Geom_Number radius() const
Exact radius (square root of radius_squared).
The result of an offset operation, which may produce multiple polygons.
Array< Polygon > polygons
Set of resulting simple polygons.
Iterator over the vertices of a polygon.
Definition polygon.H:490
Complete result of a power diagram computation.
Result bundle for R-tree/R*-tree query visualization.
RTree< Payload, MaxEntries, MinEntries, Variant >::DebugSnapshot snapshot
Array< Rectangle > query_hit_boxes
bboxes of every entry intersecting query_rect
Full tree structure captured for visualization/debugging.
Definition tpl_r_tree.H:154
A complete snapshot of the range tree for debugging.
Array< DebugNode > nodes
List of all nodes in debug format.
Array< Point > x_sorted_points
The underlying x-sorted point array.
Result bundle for range-tree query visualization.
RangeTree2D::DebugSnapshot snapshot
Bundle of rotating-calipers results used by visualization helpers.
RotatingCalipersConvexPolygon::WidthResult width
RotatingCalipersConvexPolygon::DiameterResult diameter
The complete result of the segment arrangement computation.
Result bundle for shortest-path + funnel portal visualization.
Style descriptor for TikZ primitives.
Definition tikzgeom.H:102
std::string fill_color
TikZ fill color (fill=<color>)
Definition tikzgeom.H:105
bool with_arrow
Add ->
Definition tikzgeom.H:120
double opacity
opacity=<value> in [0,1], when >= 0
Definition tikzgeom.H:115
bool thick
Add thick
Definition tikzgeom.H:119
bool fill
Fill closed shapes (polygon/triangle/ellipse)
Definition tikzgeom.H:121
double line_width_mm
line width=<value>mm when > 0
Definition tikzgeom.H:114
bool dashed
Add dashed
Definition tikzgeom.H:117
std::string draw_color
TikZ draw color (draw=<color>)
Definition tikzgeom.H:104
The trapezoidal map and DAG search structure.
The complete result of a Voronoi diagram computation.
DynList< int > l1
DynList< int > l2
static int * k
gsl_rng * r
TikZ/LaTeX geometric drawing utilities.
Dynamic R-tree spatial index over axis-aligned rectangles.
bool with_arrow