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
37namespace Aleph
38{
39 namespace detail
40 {
41 inline std::string tikz_palette_color(const size_t idx)
42 {
43 static const char *colors[] =
44 {
45 "blue!20", "orange!25", "green!20", "red!20", "cyan!22",
46 "magenta!20", "yellow!28", "teal!22", "lime!24", "brown!20"
47 };
48 static constexpr size_t kNumColors = sizeof(colors) / sizeof(colors[0]);
49 return colors[idx % kNumColors];
50 }
51
52 struct SPP_ITri
53 {
54 size_t v[3];
55 size_t adj[3];
56 };
57
59 {
62 };
63
64 constexpr size_t SPP_NONE = ~static_cast<size_t>(0);
65
66 [[nodiscard]] inline size_t spp_find_index(const Array<Point> & pts,
67 const Point & p)
68 {
69 for (size_t i = 0; i < pts.size(); ++i)
70 if (pts(i) == p) return i;
71 return SPP_NONE;
72 }
73
75 const DynList<Triangle> & tl)
76 {
78 for (DynList<Triangle>::Iterator it(tl); it.has_curr(); it.next_ne())
79 {
80 const Triangle & t = it.get_curr();
81 SPP_ITri ti{};
82 ti.v[0] = spp_find_index(pts, t.get_p1());
83 ti.v[1] = spp_find_index(pts, t.get_p2());
84 ti.v[2] = spp_find_index(pts, t.get_p3());
85 ti.adj[0] = ti.adj[1] = ti.adj[2] = SPP_NONE;
86 tris.append(ti);
87 }
88
89 struct EdgeEntry
90 {
91 size_t u;
92 size_t v;
93 size_t tri;
94 size_t local;
95 };
96
97 Array<EdgeEntry> edges;
98 edges.reserve(tris.size() * 3);
99
100 for (size_t ti = 0; ti < tris.size(); ++ti)
101 for (int e = 0; e < 3; ++e)
102 {
103 size_t u = tris(ti).v[(e + 1) % 3];
104 size_t v = tris(ti).v[(e + 2) % 3];
105 if (u > v)
106 std::swap(u, v);
107 edges.append(EdgeEntry{u, v, ti, static_cast<size_t>(e)});
108 }
109
110 quicksort_op(edges, [](const EdgeEntry & a, const EdgeEntry & b)
111 {
112 if (a.u != b.u) return a.u < b.u;
113 if (a.v != b.v) return a.v < b.v;
114 return a.tri < b.tri;
115 });
116
117 for (size_t i = 0; i + 1 < edges.size(); ++i)
118 if (edges(i).u == edges(i + 1).u and edges(i).v == edges(i + 1).v)
119 {
120 const size_t t1 = edges(i).tri;
121 const size_t l1 = edges(i).local;
122 const size_t t2 = edges(i + 1).tri;
123 const size_t l2 = edges(i + 1).local;
124 tris(t1).adj[l1] = t2;
125 tris(t2).adj[l2] = t1;
126 ++i;
127 }
128
129 return tris;
130 }
131
133 const SPP_ITri & t,
134 const Point & p)
135 {
136 const Orientation o0 = orientation(pts(t.v[0]), pts(t.v[1]), p);
137 const Orientation o1 = orientation(pts(t.v[1]), pts(t.v[2]), p);
138 const Orientation o2 = orientation(pts(t.v[2]), pts(t.v[0]), p);
139 const bool has_cw = o0 == Orientation::CW or o1 == Orientation::CW
143 return not (has_cw and has_ccw);
144 }
145
146 [[nodiscard]] inline size_t spp_find_tri(const Array<Point> & pts,
147 const Array<SPP_ITri> & tris,
148 const Point & p)
149 {
150 for (size_t i = 0; i < tris.size(); ++i)
151 if (spp_point_in_triangle(pts, tris(i), p))
152 return i;
153 return SPP_NONE;
154 }
155
157 const size_t src,
158 const size_t dst)
159 {
160 if (src == dst)
161 {
163 s.append(src);
164 return s;
165 }
166
167 Array<size_t> parent;
168 parent.reserve(tris.size());
169 for (size_t i = 0; i < tris.size(); ++i)
170 parent.append(SPP_NONE);
171 parent(src) = src;
172
173 DynList<size_t> queue;
174 queue.append(src);
175
176 while (not queue.is_empty())
177 {
178 const size_t cur = queue.remove_first();
179 if (cur == dst)
180 break;
181
182 for (unsigned long nb: tris(cur).adj)
183 if (nb != SPP_NONE and parent(nb) == SPP_NONE)
184 {
185 parent(nb) = cur;
186 queue.append(nb);
187 }
188 }
189
190 Array<size_t> path;
191 if (parent(dst) == SPP_NONE)
192 return path;
193
194 for (size_t cur = dst; cur != src; cur = parent(cur))
195 path.append(cur);
196 path.append(src);
197
198 for (size_t i = 0; i < path.size() / 2; ++i)
199 std::swap(path(i), path(path.size() - 1 - i));
200
201 return path;
202 }
203
204 [[nodiscard]] inline Geom_Number spp_cross(const Point & a,
205 const Point & b,
206 const Point & c)
207 {
208 return (b.get_x() - a.get_x()) * (c.get_y() - a.get_y()) -
209 (b.get_y() - a.get_y()) * (c.get_x() - a.get_x());
210 }
211
214 const Point & source,
215 const Point & target)
216 {
217 ah_domain_error_if(not polygon.is_closed()) << "Polygon must be closed";
218 ah_domain_error_if(polygon.size() < 3) << "Polygon must have >= 3 vertices";
220 << "Source must be inside the polygon";
222 << "Target must be inside the polygon";
223
224 Array<SPP_Portal> portals;
225 if (source == target)
226 {
227 portals.append(SPP_Portal{source, source});
228 return portals;
229 } {
230 const Segment seg(source, target);
231 bool blocked = false;
232 for (Polygon::Segment_Iterator it(polygon); it.has_curr() and not blocked; it.next_ne())
233 if (const Segment edge = it.get_current_segment();
234 seg.intersects_properly_with(edge))
235 blocked = true;
236 if (not blocked)
237 {
238 portals.append(SPP_Portal{source, source});
239 portals.append(SPP_Portal{target, target});
240 return portals;
241 }
242 }
243
245 for (Polygon::Vertex_Iterator it(polygon); it.has_curr(); it.next_ne())
246 pts.append(it.get_current_vertex());
247
249 const DynList<Triangle> tri_list = triangulator(polygon);
250
251 ah_domain_error_if(tri_list.is_empty()) << "Triangulation failed";
252
254 const size_t src_t = spp_find_tri(pts, tris, source);
255 const size_t dst_t = spp_find_tri(pts, tris, target);
256
257 ah_domain_error_if(src_t == SPP_NONE) << "Could not locate source in triangulation";
258 ah_domain_error_if(dst_t == SPP_NONE) << "Could not locate target in triangulation";
259
261
262 portals.append(SPP_Portal{source, source});
263
264 if (sleeve.size() <= 1)
265 {
266 portals.append(SPP_Portal{target, target});
267 return portals;
268 }
269
270 for (size_t i = 0; i + 1 < sleeve.size(); ++i)
271 {
272 size_t s0 = 0, s1 = 0;
273 size_t v_prev = 0;
274
275 int sc = 0;
276 bool found[3] = {false, false, false};
277 for (int a = 0; a < 3; ++a)
278 for (const unsigned long b: tris(sleeve(i + 1)).v)
279 if (tris(sleeve(i)).v[a] == b)
280 {
281 found[a] = true;
282 break;
283 }
284
285 for (int a = 0; a < 3; ++a)
286 if (found[a])
287 {
288 if (sc == 0) s0 = tris(sleeve(i)).v[a];
289 else s1 = tris(sleeve(i)).v[a];
290 ++sc;
291 }
292 else
293 v_prev = tris(sleeve(i)).v[a];
294
295 const Geom_Number c = spp_cross(pts(v_prev), pts(s0), pts(s1));
296 if (c < 0)
297 portals.append(SPP_Portal{pts(s0), pts(s1)});
298 else
299 portals.append(SPP_Portal{pts(s1), pts(s0)});
300 }
301
302 portals.append(SPP_Portal{target, target});
303 return portals;
304 }
305 } // namespace detail
306
329 inline Tikz_Style tikz_points_style(const std::string & color = "black",
330 const double opacity = -1.0)
331 {
332 Tikz_Style s;
333 s.draw_color = color;
334 s.fill_color = color;
335 s.opacity = opacity;
336 return s;
337 }
338
346 inline Tikz_Style tikz_wire_style(const std::string & color = "black",
347 const bool dashed = false,
348 const bool with_arrow = false)
349 {
350 Tikz_Style s;
351 s.draw_color = color;
352 s.dashed = dashed;
354 return s;
355 }
356
366 inline Tikz_Style tikz_path_style(const std::string & color = "red",
367 const bool with_arrow = false)
368 {
370 s.thick = true;
371 return s;
372 }
373
384 inline Tikz_Style tikz_area_style(const std::string & draw_color = "black",
385 const std::string & fill_color = "gray!25",
386 const double opacity = 0.6)
387 {
388 Tikz_Style s;
389 s.draw_color = draw_color;
390 s.fill_color = fill_color;
391 s.fill = true;
392 s.opacity = opacity;
393 return s;
394 }
395
403 inline void put_points(Tikz_Plane & plane, const Array<Point> & pts,
404 const Tikz_Style & style = tikz_points_style(),
405 const int layer = Tikz_Plane::Layer_Default)
406 {
407 for (size_t i = 0; i < pts.size(); ++i)
408 put_in_plane(plane, pts(i), style, layer);
409 }
410
418 inline void put_points(Tikz_Plane & plane, const DynList<Point> & pts,
419 const Tikz_Style & style = tikz_points_style(),
420 const int layer = Tikz_Plane::Layer_Default)
421 {
422 for (DynList<Point>::Iterator it(pts); it.has_curr(); it.next_ne())
423 put_in_plane(plane, it.get_curr(), style, layer);
424 }
425
437 inline void put_point_labels(Tikz_Plane & plane,
438 const Array<Point> & pts,
439 const std::string & prefix = "p",
440 const std::string & placement = "above right",
441 const Tikz_Style & style = make_tikz_draw_style("black"),
442 const int layer = Tikz_Plane::Layer_Overlay)
443 {
444 for (size_t i = 0; i < pts.size(); ++i)
446 prefix + std::to_string(i),
447 placement, style, layer);
448 }
449
461 inline void put_point_labels(Tikz_Plane & plane,
462 const DynList<Point> & pts,
463 const std::string & prefix = "p",
464 const std::string & placement = "above right",
465 const Tikz_Style & style = make_tikz_draw_style("black"),
466 const int layer = Tikz_Plane::Layer_Overlay)
467 {
468 size_t idx = 0;
469 for (DynList<Point>::Iterator it(pts); it.has_curr(); it.next_ne(), ++idx)
470 put_point_label_in_plane(plane, it.get_curr(),
471 prefix + std::to_string(idx),
472 placement, style, layer);
473 }
474
482 inline void put_polygons(Tikz_Plane & plane, const Array<Polygon> & polys,
483 const Tikz_Style & style = tikz_wire_style(),
484 const int layer = Tikz_Plane::Layer_Default)
485 {
486 for (size_t i = 0; i < polys.size(); ++i)
487 put_in_plane(plane, polys(i), style, layer);
488 }
489
497 inline void put_polygon_vertices(Tikz_Plane & plane, const Polygon & poly,
498 const Tikz_Style & style = tikz_points_style(),
499 const int layer = Tikz_Plane::Layer_Overlay)
500 {
501 for (Polygon::Vertex_Iterator it(poly); it.has_curr(); it.next_ne())
502 put_in_plane(plane, it.get_current_vertex().to_point(), style, layer);
503 }
504
512 inline void put_polygon_vertices(Tikz_Plane & plane, const Regular_Polygon & poly,
513 const Tikz_Style & style = tikz_points_style(),
514 const int layer = Tikz_Plane::Layer_Overlay)
515 {
516 for (size_t i = 0; i < poly.size(); ++i)
517 put_in_plane(plane, poly.get_vertex(i), style, layer);
518 }
519
528 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,
552 const bool close = true)
553 {
554 Polygon poly;
555 for (DynList<size_t>::Iterator it(indices); it.has_curr(); it.next_ne())
556 if (const size_t idx = it.get_curr(); idx < vertices.size())
557 poly.add_vertex(vertices(idx));
558
559 if (close and poly.size() >= 3)
560 poly.close();
561
562 return poly;
563 }
564
584 template <typename HullAlgorithm>
586 const DynList<Point> & points,
588 const Tikz_Style & point_style =
589 tikz_points_style("black", 0.6),
590 const Tikz_Style & hull_style =
591 tikz_wire_style("red"),
593 tikz_points_style("red"),
596 const bool draw_hull_vertices = true)
597 {
598 put_points(plane, points, point_style, point_layer);
599
600 Polygon hull = hull_algorithm(points);
601 if (hull.size() > 0)
603
604 if (draw_hull_vertices and hull.size() > 0)
606
607 return hull;
608 }
609
627 Tikz_Plane & plane,
628 const Polygon & subject,
629 const Polygon & clip,
631 const Tikz_Style & subject_style = tikz_area_style("blue", "blue!15", 0.45),
632 const Tikz_Style & clip_style = tikz_area_style("orange", "orange!20", 0.45),
633 const Tikz_Style & result_style = tikz_area_style("red", "red!30", 0.60),
636 {
639
641 if (inter.size() > 0)
643
644 return inter;
645 }
646
667 Tikz_Plane & plane,
668 const Polygon & a,
669 const Polygon & b,
671 const BooleanPolygonOperations & bop = {},
672 const Tikz_Style & a_style = tikz_area_style("blue", "blue!15", 0.35),
673 const Tikz_Style & b_style = tikz_area_style("green!60!black", "green!20", 0.35),
674 const Tikz_Style & result_style = tikz_area_style("red", "red!35", 0.65),
677 {
678 put_in_plane(plane, a, a_style, input_layer);
679 put_in_plane(plane, b, b_style, input_layer + 1);
680
681 Array<Polygon> result = bop(a, b, op);
682 put_polygons(plane, result, result_style, result_layer);
683 return result;
684 }
685
691 Tikz_Plane & plane,
693 const Tikz_Style & triangle_style = tikz_wire_style("blue"),
694 const bool draw_sites = true,
695 const Tikz_Style & site_style = tikz_points_style("black"),
698 {
699 for (size_t i = 0; i < dt.triangles.size(); ++i)
700 {
701 const auto & tri = dt.triangles(i);
702 Triangle t(dt.sites(tri.i), dt.sites(tri.j), dt.sites(tri.k));
704 }
705
706 if (draw_sites)
707 put_points(plane, dt.sites, site_style, site_layer);
708 }
709
713 Tikz_Plane & plane,
714 const DynList<Point> & points,
716 const Tikz_Style & triangle_style = tikz_wire_style("blue"),
717 const bool draw_sites = true,
718 const Tikz_Style & site_style = tikz_points_style("black"))
719 {
720 auto dt = algorithm(points);
722 return dt;
723 }
724
725 [[nodiscard]] inline Point ray_endpoint(const Point & src, const Point & direction,
726 const Geom_Number & length)
727 {
728 const Geom_Number & dx = direction.get_x();
729 const Geom_Number & dy = direction.get_y();
730 const Geom_Number n2 = dx * dx + dy * dy;
731 if (n2 == 0)
732 return src;
733
734 const Geom_Number n = square_root(n2);
735 const Geom_Number scale = length / n;
736 return {src.get_x() + dx * scale, src.get_y() + dy * scale};
737 }
738
744 template <typename VoronoiResult>
746 Tikz_Plane & plane,
747 const VoronoiResult & vor,
748 const bool draw_cells = false,
749 const Tikz_Style & cell_style = tikz_area_style("gray!50!black", "gray!15", 0.35),
750 const Tikz_Style & edge_style = tikz_wire_style("black"),
751 const Tikz_Style & unbounded_edge_style = tikz_wire_style("black", true, true),
752 const Tikz_Style & site_style = tikz_points_style("red"),
757 {
758 if (draw_cells)
759 for (size_t i = 0; i < vor.cells.size(); ++i)
760 {
761 const auto & cell = vor.cells(i);
762 if (not cell.bounded or cell.vertices.size() < 3)
763 continue;
764
765 Polygon poly = polygon_from_vertices(cell.vertices, true);
766 put_in_plane(plane, poly, cell_style, cell_layer);
767 }
768
769 for (size_t i = 0; i < vor.edges.size(); ++i)
770 if (const auto & e = vor.edges(i); e.unbounded)
771 {
772 const Point tgt = ray_endpoint(e.src, e.direction, unbounded_ray_length);
774 }
775 else
776 put_in_plane(plane, Segment(e.src, e.tgt), edge_style, edge_layer);
777
778 put_points(plane, vor.sites, site_style, site_layer);
779 }
780
786 Tikz_Plane & plane,
787 const DynList<Point> & sites,
788 const VoronoiDiagram & algorithm = {},
789 const bool draw_cells = false,
790 const Tikz_Style & cell_style = tikz_area_style("gray!50!black", "gray!15", 0.35),
791 const Tikz_Style & edge_style = tikz_wire_style("black"),
792 const Tikz_Style & unbounded_edge_style = tikz_wire_style("black", true, true),
793 const Tikz_Style & site_style = tikz_points_style("red"),
795 {
797 put_voronoi_result(plane, vor,
804 return vor;
805 }
806
809 Tikz_Plane & plane,
810 const PowerDiagram::Result & pd,
811 const bool draw_cells = true,
812 const Tikz_Style & cell_style = tikz_area_style("violet", "violet!18", 0.35),
813 const Tikz_Style & edge_style = tikz_wire_style("violet"),
814 const Tikz_Style & site_style = tikz_points_style("purple"),
818 {
819 if (draw_cells)
820 for (size_t i = 0; i < pd.cells.size(); ++i)
821 {
822 const auto & cell = pd.cells(i);
823 if (cell.vertices.size() < 3)
824 continue;
825
826 Polygon poly = polygon_from_vertices(cell.vertices, true);
827 put_in_plane(plane, poly, cell_style, cell_layer);
828 }
829
830 for (size_t i = 0; i < pd.edges.size(); ++i)
831 {
832 const auto & e = pd.edges(i);
833 put_in_plane(plane, Segment(e.src, e.tgt), edge_style, edge_layer);
834 }
835
836 for (size_t i = 0; i < pd.sites.size(); ++i)
837 put_in_plane(plane, pd.sites(i).position, site_style, site_layer);
838 }
839
842 Tikz_Plane & plane,
844 const PowerDiagram & algorithm = {},
845 const bool draw_cells = true,
846 const Tikz_Style & cell_style = tikz_area_style("violet", "violet!18", 0.35),
847 const Tikz_Style & edge_style = tikz_wire_style("violet"),
848 const Tikz_Style & site_style = tikz_points_style("purple"))
849 {
856 return res;
857 }
858
861 Tikz_Plane & plane,
863 const bool draw_faces = true,
864 const bool draw_vertices = true,
865 const bool draw_unbounded_face = false,
866 const Tikz_Style & face_style =
867 tikz_area_style("teal!60!black", "teal!12", 0.30),
868 const Tikz_Style & edge_style = tikz_wire_style("teal!70!black"),
869 const Tikz_Style & vertex_style = tikz_points_style("teal!70!black"),
873 const bool color_faces_by_index = false)
874 {
875 if (draw_faces)
876 {
877 size_t face_color_idx = 0;
878 for (size_t i = 0; i < arrangement.faces.size(); ++i)
879 {
880 const auto & [boundary, unbounded] = arrangement.faces(i);
881 if (unbounded and not draw_unbounded_face)
882 continue;
883
884 Polygon poly =
885 polygon_from_vertex_indices(arrangement.vertices, boundary, true);
886 if (poly.size() >= 3)
887 {
888 Tikz_Style style = face_style;
890 {
891 style.fill = true;
893 if (style.draw_color.empty())
894 style.draw_color = "black";
895 }
896
897 put_in_plane(plane, poly, style, face_layer);
898 }
899 }
900 }
901
902 for (size_t i = 0; i < arrangement.edges.size(); ++i)
903 {
904 const auto & e = arrangement.edges(i);
905 if (e.src >= arrangement.vertices.size() or
906 e.tgt >= arrangement.vertices.size())
907 continue;
908
909 put_in_plane(plane,
910 Segment(arrangement.vertices(e.src), arrangement.vertices(e.tgt)),
912 }
913
914 if (draw_vertices)
916 }
917
920 Tikz_Plane & plane,
921 const Array<Segment> & segments,
922 const SegmentArrangement & algorithm = {},
923 const bool draw_faces = true,
924 const bool draw_vertices = true,
925 const bool draw_unbounded_face = false,
926 const Tikz_Style & face_style =
927 tikz_area_style("teal!60!black", "teal!12", 0.30),
928 const Tikz_Style & edge_style = tikz_wire_style("teal!70!black"),
929 const Tikz_Style & vertex_style = tikz_points_style("teal!70!black"),
930 const bool color_faces_by_index = false)
931 {
940 return res;
941 }
942
945 Tikz_Plane & plane,
946 const KDTreePointSearch::DebugSnapshot & snapshot,
947 const bool draw_partition_boxes = false,
948 const bool draw_points = true,
949 const Tikz_Style & partition_style = tikz_wire_style("gray!55", true),
950 const Tikz_Style & split_style = tikz_wire_style("blue!70"),
955 {
956 for (size_t i = 0; i < snapshot.partitions.size(); ++i)
957 {
958 const auto & part = snapshot.partitions(i);
961
962 if (part.is_leaf)
963 continue;
964
965 const Geom_Number x0 = part.region.get_xmin();
966 const Geom_Number x1 = part.region.get_xmax();
967 const Geom_Number y0 = part.region.get_ymin();
968 const Geom_Number y1 = part.region.get_ymax();
969 Segment split_seg = part.split_on_x ?
970 Segment(Point(part.split_value, y0),
971 Point(part.split_value, y1)) :
972 Segment(Point(x0, part.split_value),
973 Point(x1, part.split_value));
974
975 Tikz_Style style = split_style;
977 put_in_plane(plane, split_seg, style, split_layer);
978 }
979
980 if (draw_points)
981 put_points(plane, snapshot.points, point_style, point_layer);
982 }
983
986 Tikz_Plane & plane,
988 const bool draw_partition_boxes = false,
989 const bool draw_points = true,
990 const Tikz_Style & partition_style = tikz_wire_style("gray!55", true),
991 const Tikz_Style & split_style = tikz_wire_style("blue!70"),
993 {
994 const auto snapshot = kd_tree.debug_snapshot();
996 plane, snapshot, draw_partition_boxes, draw_points,
998 return snapshot;
999 }
1000
1003 Tikz_Plane & plane,
1004 const RangeTree2D::DebugSnapshot & snapshot,
1005 const bool draw_points = true,
1006 const Rectangle *query_rect = nullptr,
1007 const DynList<Point> *query_hits = nullptr,
1008 const Tikz_Style & split_style = tikz_wire_style("purple"),
1009 const Tikz_Style & point_style = tikz_points_style("black"),
1010 const Tikz_Style & query_rect_style = tikz_wire_style("red", true),
1014 {
1015 if (snapshot.x_sorted_points.size() == 0)
1016 return;
1017
1018 Geom_Number ymin = snapshot.x_sorted_points(0).get_y();
1019 Geom_Number ymax = ymin;
1020 for (size_t i = 1; i < snapshot.x_sorted_points.size(); ++i)
1021 {
1022 if (snapshot.x_sorted_points(i).get_y() < ymin)
1023 ymin = snapshot.x_sorted_points(i).get_y();
1024 if (snapshot.x_sorted_points(i).get_y() > ymax)
1025 ymax = snapshot.x_sorted_points(i).get_y();
1026 }
1027
1028 for (size_t i = 0; i < snapshot.nodes.size(); ++i)
1029 {
1030 const auto & node = snapshot.nodes(i);
1031 if (node.is_leaf)
1032 continue;
1033
1034 Tikz_Style style = split_style;
1035 style.draw_color = detail::tikz_palette_color(node.tree_index);
1036 put_in_plane(plane,
1037 Segment(Point(node.split_x, ymin), Point(node.split_x, ymax)),
1038 style, split_layer);
1039 }
1040
1041 if (draw_points)
1043
1044 if (query_rect != nullptr)
1045 put_in_plane(plane, *query_rect, query_rect_style, point_layer + 1);
1046
1047 if (query_hits != nullptr)
1048 put_points(plane, *query_hits, query_hit_style, point_layer + 2);
1049 }
1050
1053 Tikz_Plane & plane,
1054 const RangeTree2D & tree,
1055 const bool draw_points = true,
1056 const Tikz_Style & split_style = tikz_wire_style("purple"),
1057 const Tikz_Style & point_style = tikz_points_style("black"))
1058 {
1059 const auto snapshot = tree.debug_snapshot();
1060 put_range_tree_result(plane, snapshot, draw_points, nullptr, nullptr,
1062 return snapshot;
1063 }
1064
1072
1075 Tikz_Plane & plane,
1076 const RangeTree2D & tree,
1077 const Rectangle & query_rect,
1078 const bool draw_points = true,
1079 const Tikz_Style & split_style = tikz_wire_style("purple"),
1080 const Tikz_Style & point_style = tikz_points_style("black"),
1081 const Tikz_Style & query_rect_style = tikz_wire_style("red", true),
1083 {
1085 out.snapshot = tree.debug_snapshot();
1086 out.query_rect = query_rect;
1087 out.query_hits = tree.query(query_rect.get_xmin(), query_rect.get_xmax(),
1088 query_rect.get_ymin(), query_rect.get_ymax());
1089 put_range_tree_result(plane, out.snapshot, draw_points, &out.query_rect, &out.query_hits,
1091 return out;
1092 }
1093
1096 Tikz_Plane & plane,
1097 const AABBTree::DebugSnapshot & snapshot,
1098 const Rectangle *query_rect = nullptr,
1099 const Array<size_t> *query_hit_ids = nullptr,
1100 const Tikz_Style & node_bbox_style = tikz_wire_style("teal!70!black"),
1101 const Tikz_Style & leaf_bbox_style = tikz_wire_style("blue!70"),
1102 const Tikz_Style & query_rect_style = tikz_wire_style("red", true),
1106 {
1107 for (size_t i = 0; i < snapshot.nodes.size(); ++i)
1108 {
1109 const auto & node = snapshot.nodes(i);
1110 Tikz_Style style = node.is_leaf ? leaf_bbox_style : node_bbox_style;
1111 style.draw_color = detail::tikz_palette_color(node.depth);
1112 put_in_plane(plane, node.bbox, style, node_layer);
1113 }
1114
1115 if (query_rect != nullptr)
1116 put_in_plane(plane, *query_rect, query_rect_style, query_layer);
1117
1118 if (query_hit_ids != nullptr)
1119 for (size_t i = 0; i < snapshot.nodes.size(); ++i)
1120 if (snapshot.nodes(i).is_leaf)
1121 for (size_t j = 0; j < query_hit_ids->size(); ++j)
1122 if (snapshot.nodes(i).user_index == (*query_hit_ids)(j))
1123 {
1124 put_in_plane(plane, snapshot.nodes(i).bbox, query_hit_style, query_layer + 1);
1125 break;
1126 }
1127 }
1128
1131 Tikz_Plane & plane,
1132 const AABBTree & tree,
1133 const Tikz_Style & node_bbox_style = tikz_wire_style("teal!70!black"),
1134 const Tikz_Style & leaf_bbox_style = tikz_wire_style("blue!70"))
1135 {
1136 const auto snapshot = tree.debug_snapshot();
1137 put_aabb_tree_result(plane, snapshot, nullptr, nullptr,
1139 return snapshot;
1140 }
1141
1149
1152 Tikz_Plane & plane,
1153 const AABBTree & tree,
1154 const Rectangle & query_rect,
1155 const Tikz_Style & node_bbox_style = tikz_wire_style("teal!70!black"),
1156 const Tikz_Style & leaf_bbox_style = tikz_wire_style("blue!70"),
1157 const Tikz_Style & query_rect_style = tikz_wire_style("red", true),
1159 {
1161 out.snapshot = tree.debug_snapshot();
1162 out.query_rect = query_rect;
1163 out.query_hit_ids = tree.query(query_rect);
1165 plane, out.snapshot, &out.query_rect, &out.query_hit_ids,
1167 return out;
1168 }
1169
1171 inline void put_path(
1172 Tikz_Plane & plane,
1173 const DynList<Point> & path,
1174 const Tikz_Style & segment_style = tikz_path_style("red"),
1175 const bool draw_waypoints = true,
1179 {
1180 bool has_prev = false;
1181 Point prev;
1182
1183 for (DynList<Point>::Iterator it(path); it.has_curr(); it.next_ne())
1184 {
1185 const Point & curr = it.get_curr();
1186 if (has_prev)
1187 put_in_plane(plane, Segment(prev, curr), segment_style, segment_layer);
1188
1189 prev = curr;
1190 has_prev = true;
1191 }
1192
1193 if (draw_waypoints)
1195 }
1196
1198 inline void put_path(
1199 Tikz_Plane & plane,
1200 const Array<Point> & path,
1201 const Tikz_Style & segment_style = tikz_path_style("red"),
1202 const bool draw_waypoints = true,
1206 {
1207 if (path.size() == 0)
1208 return;
1209
1210 for (size_t i = 1; i < path.size(); ++i)
1211 put_in_plane(plane, Segment(path(i - 1), path(i)), segment_style, segment_layer);
1212
1213 if (draw_waypoints)
1215 }
1216
1218
1220 inline void put_portals(
1221 Tikz_Plane & plane,
1222 const Array<FunnelPortal> & portals,
1223 const bool skip_degenerate = true,
1224 const Tikz_Style & portal_style = tikz_wire_style("purple", true),
1226 {
1227 for (size_t i = 0; i < portals.size(); ++i)
1228 {
1229 const auto & [left, right] = portals(i);
1230 if (skip_degenerate and left == right)
1231 continue;
1232
1233 put_in_plane(plane, Segment(left, right), portal_style, portal_layer);
1234 }
1235 }
1236
1243
1259
1267
1273 const Polygon & polygon,
1274 const Point & source,
1275 const Point & target)
1276 {
1278 trace.portals = detail::shortest_path_portals(polygon, source, target);
1279
1280 if (trace.portals.size() == 0)
1281 return trace;
1282
1283 Point apex = source;
1284 Point fl = source;
1285 Point fr = source;
1286 size_t ai = 0;
1287 size_t li = 0;
1288 size_t ri = 0;
1289
1290 Array<Point> committed;
1291 committed.append(source);
1292
1293 for (size_t i = 1; i < trace.portals.size(); ++i)
1294 {
1295 const Point & pr = trace.portals(i).right;
1296 const Point & pl = trace.portals(i).left;
1297
1299 step.portal_index = i;
1300 step.portal_left = pl;
1301 step.portal_right = pr;
1302 step.apex = apex;
1303 step.left_boundary = fl;
1304 step.right_boundary = fr;
1305 step.committed_path = committed;
1306
1307 bool restart = false;
1308
1309 if (detail::spp_cross(apex, fr, pr) >= 0)
1310 {
1311 if (apex == fr or detail::spp_cross(apex, fl, pr) < 0)
1312 {
1313 fr = pr;
1314 ri = i;
1315 step.tightened_right = true;
1316 }
1317 else
1318 {
1319 committed.append(fl);
1320 step.emitted_left = true;
1321
1322 apex = fl;
1323 ai = li;
1324 fl = apex;
1325 fr = apex;
1326 li = ai;
1327 ri = ai;
1328 i = ai;
1329 restart = true;
1330 }
1331 }
1332
1333 if (not restart and detail::spp_cross(apex, fl, pl) <= 0)
1334 {
1335 if (apex == fl or detail::spp_cross(apex, fr, pl) > 0)
1336 {
1337 fl = pl;
1338 li = i;
1339 step.tightened_left = true;
1340 }
1341 else
1342 {
1343 committed.append(fr);
1344 step.emitted_right = true;
1345
1346 apex = fr;
1347 ai = ri;
1348 fl = apex;
1349 fr = apex;
1350 li = ai;
1351 ri = ai;
1352 i = ai;
1353 restart = true;
1354 }
1355 }
1356
1357 step.apex = apex;
1358 step.left_boundary = fl;
1359 step.right_boundary = fr;
1360 step.committed_path = committed;
1361 trace.steps.append(step);
1362
1363 if (restart)
1364 continue; // this is deliberately after appending the step, so the "restart" state is visible in the trace
1365 }
1366
1367 committed.append(target);
1368 trace.final_path = committed;
1369 return trace;
1370 }
1371
1377 Tikz_Plane & plane,
1378 const Polygon & polygon,
1379 const Point & source,
1380 const Point & target,
1381 const FunnelTraceResult & trace,
1382 size_t step_index,
1383 const Tikz_Style & polygon_style = tikz_area_style("black", "gray!15", 0.22),
1384 const Tikz_Style & source_style = tikz_points_style("green!50!black"),
1385 const Tikz_Style & target_style = tikz_points_style("blue"),
1386 const Tikz_Style & all_portals_style = tikz_wire_style("purple", true),
1388 const Tikz_Style & funnel_leg_style = tikz_path_style("orange!90!black"),
1390 const bool draw_waypoints = true,
1395 {
1396 put_in_plane(plane, polygon, polygon_style, polygon_layer);
1397 put_in_plane(plane, source, source_style, highlight_layer + 1);
1398 put_in_plane(plane, target, target_style, highlight_layer + 1);
1399
1400 put_portals(plane, trace.portals, true, all_portals_style, portal_layer);
1401
1402 if (trace.steps.size() == 0)
1403 return;
1404
1405 if (step_index >= trace.steps.size())
1406 step_index = trace.steps.size() - 1;
1407
1408 const FunnelTraceStep & step = trace.steps(step_index);
1409
1410 // Active portal segment.
1411 if (step.portal_left != step.portal_right)
1412 put_in_plane(plane, Segment(step.portal_left, step.portal_right),
1414
1415 // Current funnel legs.
1416 if (step.apex != step.left_boundary)
1417 put_in_plane(plane, Segment(step.apex, step.left_boundary),
1419 if (step.apex != step.right_boundary)
1420 put_in_plane(plane, Segment(step.apex, step.right_boundary),
1422
1423 // Committed path prefix.
1424 put_path(plane, step.committed_path,
1427
1428 put_in_plane(plane, step.apex, tikz_points_style("orange!90!black"), highlight_layer + 2);
1429 put_in_plane(plane, step.left_boundary, tikz_points_style("orange!90!black"), highlight_layer + 2);
1430 put_in_plane(plane, step.right_boundary, tikz_points_style("orange!90!black"), highlight_layer + 2);
1431 }
1432
1435 Tikz_Plane & plane,
1436 const Polygon & polygon,
1437 const Point & source,
1438 const Point & target,
1439 const ShortestPathInPolygon & algorithm = {},
1440 const Tikz_Style & polygon_style =
1441 tikz_area_style("black", "gray!15", 0.25),
1442 const Tikz_Style & source_style = tikz_points_style("green!50!black"),
1443 const Tikz_Style & target_style = tikz_points_style("blue"),
1444 const Tikz_Style & path_style = tikz_path_style("red"),
1445 const bool draw_waypoints = true,
1449 {
1450 put_in_plane(plane, polygon, polygon_style, polygon_layer);
1451 put_in_plane(plane, source, source_style, path_layer + 1);
1452 put_in_plane(plane, target, target_style, path_layer + 1);
1453
1454 DynList<Point> path = algorithm(polygon, source, target);
1455 put_path(plane, path,
1457 path_layer, path_layer + 1);
1458 return path;
1459 }
1460
1469 Tikz_Plane & plane,
1470 const Polygon & polygon,
1471 const Point & source,
1472 const Point & target,
1473 const ShortestPathInPolygon & algorithm = {},
1474 const Tikz_Style & polygon_style =
1475 tikz_area_style("black", "gray!15", 0.25),
1476 const Tikz_Style & source_style = tikz_points_style("green!50!black"),
1477 const Tikz_Style & target_style = tikz_points_style("blue"),
1478 const Tikz_Style & portal_style = tikz_wire_style("purple", true),
1479 const Tikz_Style & path_style = tikz_path_style("red"),
1480 const bool draw_waypoints = true,
1485 {
1486 put_in_plane(plane, polygon, polygon_style, polygon_layer);
1487 put_in_plane(plane, source, source_style, portal_layer + 1);
1488 put_in_plane(plane, target, target_style, portal_layer + 1);
1489
1491 out.portals = detail::shortest_path_portals(polygon, source, target);
1492 put_portals(plane, out.portals, true, portal_style, portal_layer);
1493
1494 out.path = algorithm(polygon, source, target);
1495 put_path(plane, out.path,
1497 path_layer, path_layer + 1);
1498 return out;
1499 }
1500
1506 Tikz_Plane & plane,
1507 const Array<Polygon> & parts,
1508 const bool color_parts_by_index = true,
1509 const Tikz_Style & part_style =
1510 tikz_area_style("blue!60!black", "blue!15", 0.40),
1512 {
1513 size_t color_idx = 0;
1514 for (size_t i = 0; i < parts.size(); ++i)
1515 {
1516 Tikz_Style style = part_style;
1518 {
1519 style.fill = true;
1521 if (style.draw_color.empty())
1522 style.draw_color = "black";
1523 }
1524
1525 put_in_plane(plane, parts(i), style, part_layer);
1526 }
1527 }
1528
1531 Tikz_Plane & plane,
1532 const Polygon & polygon,
1534 const bool draw_input_polygon = true,
1535 const Tikz_Style & input_style = tikz_wire_style("black", true),
1536 const bool color_parts_by_index = true,
1537 const Tikz_Style & part_style =
1538 tikz_area_style("blue!60!black", "blue!15", 0.40),
1541 {
1543 put_in_plane(plane, polygon, input_style, input_layer);
1544
1545 Array<Polygon> parts = algorithm(polygon);
1548 part_style,
1549 part_layer);
1550 return parts;
1551 }
1552
1555 Tikz_Plane & plane,
1557 const bool draw_kept_triangles = false,
1558 const Tikz_Style & triangle_style = tikz_wire_style("gray!55"),
1559 const Tikz_Style & boundary_style = tikz_path_style("orange!90!black"),
1560 const bool draw_sites = true,
1561 const Tikz_Style & site_style = tikz_points_style("black"),
1565 {
1567 {
1568 for (size_t n = 0; n < alpha_shape.triangles.size(); ++n)
1569 {
1570 const auto & [i, j, k] = alpha_shape.triangles(n);
1571 if (i >= alpha_shape.sites.size() or
1572 j >= alpha_shape.sites.size() or
1573 k >= alpha_shape.sites.size())
1574 continue;
1575
1576 put_in_plane(plane,
1577 Triangle(alpha_shape.sites(i),
1578 alpha_shape.sites(j),
1579 alpha_shape.sites(k)),
1581 }
1582 }
1583
1584 for (size_t i = 0; i < alpha_shape.boundary_edges.size(); ++i)
1585 put_in_plane(plane, alpha_shape.boundary_edges(i), boundary_style, boundary_layer);
1586
1587 if (draw_sites)
1589 }
1590
1593 Tikz_Plane & plane,
1594 const DynList<Point> & points,
1595 const Geom_Number & alpha_squared,
1596 const AlphaShape & algorithm = {},
1597 const bool draw_kept_triangles = false,
1598 const Tikz_Style & triangle_style = tikz_wire_style("gray!55"),
1599 const Tikz_Style & boundary_style = tikz_path_style("orange!90!black"),
1600 const bool draw_sites = true,
1601 const Tikz_Style & site_style = tikz_points_style("black"))
1602 {
1608 draw_sites,
1609 site_style,
1613 return res;
1614 }
1615
1618 Tikz_Plane & plane,
1620 const Tikz_Style & triangle_style = tikz_wire_style("blue!60"),
1621 const bool draw_sites = true,
1622 const Tikz_Style & site_style = tikz_points_style("black"),
1625 {
1626 for (size_t i = 0; i < rt.triangles.size(); ++i)
1627 {
1628 const auto & tri = rt.triangles(i);
1629 Triangle t(rt.sites(tri.i).position,
1630 rt.sites(tri.j).position,
1631 rt.sites(tri.k).position);
1633 }
1634
1635 if (draw_sites)
1636 for (size_t i = 0; i < rt.sites.size(); ++i)
1637 put_in_plane(plane, rt.sites(i).position, site_style, site_layer);
1638 }
1639
1643 Tikz_Plane & plane,
1646 const Tikz_Style & triangle_style = tikz_wire_style("blue!60"),
1647 const bool draw_sites = true,
1648 const Tikz_Style & site_style = tikz_points_style("black"))
1649 {
1650 auto result = algorithm(weighted_sites);
1652 plane, result, triangle_style, draw_sites, site_style);
1653 return result;
1654 }
1655
1658 Tikz_Plane & plane,
1659 const DynList<Point> & points,
1661 const Tikz_Style & points_style = tikz_points_style("black"),
1662 const Tikz_Style & pair_style = tikz_path_style("red"),
1666 {
1667 put_points(plane, points, points_style, points_layer);
1668 put_in_plane(plane, Segment(result.first, result.second), pair_style, pair_layer);
1669 put_in_plane(plane, result.first, pair_points_style, pair_layer + 1);
1670 put_in_plane(plane, result.second, pair_points_style, pair_layer + 1);
1671 }
1672
1676 Tikz_Plane & plane,
1677 const DynList<Point> & points,
1679 const Tikz_Style & points_style = tikz_points_style("black"),
1680 const Tikz_Style & pair_style = tikz_path_style("red"),
1682 {
1683 auto result = algorithm(points);
1685 plane, points, result,
1687 return result;
1688 }
1689
1696
1699 Tikz_Plane & plane,
1700 const Polygon & polygon,
1701 const RotatingCalipersResult & result,
1702 const Tikz_Style & polygon_style = tikz_wire_style("gray!55"),
1703 const Tikz_Style & diameter_style = tikz_path_style("red"),
1704 const Tikz_Style & width_style = tikz_path_style("blue"),
1705 const Tikz_Style & witness_style = tikz_points_style("orange!90!black"),
1708 {
1709 put_in_plane(plane, polygon, polygon_style, polygon_layer);
1710 put_in_plane(plane, Segment(result.diameter.first, result.diameter.second),
1712 put_in_plane(plane, Segment(result.width.edge_first, result.width.edge_second),
1715 }
1716
1720 Tikz_Plane & plane,
1721 const Polygon & polygon,
1722 const Tikz_Style & polygon_style = tikz_wire_style("gray!55"),
1723 const Tikz_Style & diameter_style = tikz_path_style("red"),
1724 const Tikz_Style & width_style = tikz_path_style("blue"),
1725 const Tikz_Style & witness_style = tikz_points_style("orange!90!black"))
1726 {
1730 };
1732 plane, polygon, result, polygon_style, diameter_style, width_style, witness_style);
1733 return result;
1734 }
1735
1738 Tikz_Plane & plane,
1740 const Polygon & intersection,
1741 const Tikz_Style & boundary_style = tikz_wire_style("gray!60", true, true),
1742 const Tikz_Style & result_style = tikz_area_style("red", "red!25", 0.50),
1745 {
1746 for (size_t i = 0; i < halfplanes.size(); ++i)
1747 put_in_plane(plane,
1748 Segment(halfplanes(i).p, halfplanes(i).q),
1750
1751 if (intersection.size() > 0)
1752 put_in_plane(plane, intersection, result_style, result_layer);
1753 }
1754
1756 [[nodiscard]] inline Polygon
1758 Tikz_Plane & plane,
1760 const HalfPlaneIntersection & algorithm = {},
1761 const Tikz_Style & boundary_style = tikz_wire_style("gray!60", true, true),
1762 const Tikz_Style & result_style = tikz_area_style("red", "red!25", 0.50))
1763 {
1764 Polygon intersection = algorithm(halfplanes);
1766 plane, halfplanes, intersection, boundary_style, result_style);
1767 return intersection;
1768 }
1769
1772 Tikz_Plane & plane,
1773 const Polygon & first,
1774 const Polygon & second,
1775 const Polygon & result,
1776 const Tikz_Style & first_style = tikz_area_style("blue", "blue!14", 0.30),
1777 const Tikz_Style & second_style = tikz_area_style("green!60!black", "green!16", 0.30),
1778 const Tikz_Style & result_style = tikz_area_style("red", "red!26", 0.60),
1781 {
1782 put_in_plane(plane, first, first_style, input_layer);
1783 put_in_plane(plane, second, second_style, input_layer + 1);
1784 if (result.size() > 0)
1785 put_in_plane(plane, result, result_style, result_layer);
1786 }
1787
1789 [[nodiscard]] inline Polygon
1791 Tikz_Plane & plane,
1792 const Polygon & first,
1793 const Polygon & second,
1794 const MinkowskiSumConvex & algorithm = {},
1795 const Tikz_Style & first_style = tikz_area_style("blue", "blue!14", 0.30),
1796 const Tikz_Style & second_style = tikz_area_style("green!60!black", "green!16", 0.30),
1797 const Tikz_Style & result_style = tikz_area_style("red", "red!26", 0.60))
1798 {
1799 Polygon result = algorithm(first, second);
1801 plane, first, second, result, first_style, second_style, result_style);
1802 return result;
1803 }
1804
1807 Tikz_Plane & plane,
1808 const Polygon & polygon,
1809 const DynList<Triangle> & triangles,
1810 const Tikz_Style & polygon_style = tikz_wire_style("black"),
1811 const Tikz_Style & triangle_style = tikz_wire_style("blue!65"),
1814 {
1815 put_in_plane(plane, polygon, polygon_style, polygon_layer);
1816 for (DynList<Triangle>::Iterator it(triangles); it.has_curr(); it.next_ne())
1817 put_in_plane(plane, it.get_curr(), triangle_style, triangle_layer);
1818 }
1819
1821 [[nodiscard]] inline DynList<Triangle>
1823 Tikz_Plane & plane,
1824 const Polygon & polygon,
1826 const Tikz_Style & polygon_style = tikz_wire_style("black"),
1827 const Tikz_Style & triangle_style = tikz_wire_style("blue!65"))
1828 {
1829 DynList<Triangle> triangles = algorithm(polygon);
1831 plane, polygon, triangles, polygon_style, triangle_style);
1832 return triangles;
1833 }
1834
1837 Tikz_Plane & plane,
1838 const Polygon & polygon,
1839 const Point & query_point,
1841 const Tikz_Style & polygon_style = tikz_wire_style("black"),
1842 const Tikz_Style & visibility_style = tikz_area_style("orange!90!black", "orange!25", 0.50),
1843 const Tikz_Style & query_style = tikz_points_style("red"),
1846 {
1847 put_in_plane(plane, polygon, polygon_style, polygon_layer);
1848 if (visibility_polygon.size() > 0)
1850 put_in_plane(plane, query_point, query_style, visibility_layer + 1);
1851 }
1852
1854 [[nodiscard]] inline Polygon
1856 Tikz_Plane & plane,
1857 const Polygon & polygon,
1858 const Point & query_point,
1859 const VisibilityPolygon & algorithm = {},
1860 const Tikz_Style & polygon_style = tikz_wire_style("black"),
1861 const Tikz_Style & visibility_style = tikz_area_style("orange!90!black", "orange!25", 0.50),
1862 const Tikz_Style & query_style = tikz_points_style("red"))
1863 {
1864 Polygon visibility_polygon = algorithm(polygon, query_point);
1866 plane, polygon, query_point, visibility_polygon,
1868 return visibility_polygon;
1869 }
1870
1873 Tikz_Plane & plane,
1874 const Array<Segment> & segments,
1876 const Tikz_Style & segment_style = tikz_wire_style("blue!60"),
1880 {
1881 for (size_t i = 0; i < segments.size(); ++i)
1882 put_in_plane(plane, segments(i), segment_style, segment_layer);
1883
1884 for (size_t i = 0; i < intersections.size(); ++i)
1886 }
1887
1902
1908 inline void put_cdt_result(
1909 Tikz_Plane & plane,
1911 const Tikz_Style & triangle_style = tikz_wire_style("blue!60"),
1913 const bool draw_sites = true,
1914 const Tikz_Style & site_style = tikz_points_style("black"),
1918 {
1919 for (size_t i = 0; i < cdt.triangles.size(); ++i)
1920 {
1921 const auto & tri = cdt.triangles(i);
1922 Triangle t(cdt.sites(tri.i), cdt.sites(tri.j), cdt.sites(tri.k));
1924 }
1925
1926 for (size_t i = 0; i < cdt.constrained_edges.size(); ++i)
1927 {
1928 const auto & e = cdt.constrained_edges(i);
1929 Segment s(cdt.sites(e.u), cdt.sites(e.v));
1931 }
1932
1933 if (draw_sites)
1934 put_points(plane, cdt.sites, site_style, site_layer);
1935 }
1936
1940 Tikz_Plane & plane,
1941 const DynList<Point> & points,
1944 const Tikz_Style & triangle_style = tikz_wire_style("blue!60"),
1946 const bool draw_sites = true,
1947 const Tikz_Style & site_style = tikz_points_style("black"))
1948 {
1949 auto result = algorithm(points, constraints);
1950 put_cdt_result(plane, result,
1953 return result;
1954 }
1955
1956 // ---------- Minimum Enclosing Circle visualization ----------
1957
1964 inline void put_mec_result(
1965 Tikz_Plane & plane,
1966 const MinimumEnclosingCircle::Circle & circle,
1967 const DynList<Point> & points,
1968 const Tikz_Style & circle_style = tikz_wire_style("blue!70"),
1969 const bool draw_sites = true,
1970 const Tikz_Style & site_style = tikz_points_style("black"),
1973 {
1974 const Geom_Number r = circle.radius();
1975 put_in_plane(plane, Ellipse(circle.center, r, r),
1977
1978 if (draw_sites)
1979 put_points(plane, points, site_style, site_layer);
1980 }
1981
1989 Tikz_Plane & plane,
1990 const DynList<Point> & points,
1991 const MinimumEnclosingCircle & algorithm = {},
1992 const Tikz_Style & circle_style = tikz_wire_style("blue!70"),
1993 const bool draw_sites = true,
1994 const Tikz_Style & site_style = tikz_points_style("black"))
1995 {
1996 auto circle = algorithm(points);
1997 put_mec_result(plane, circle, points,
1999 return circle;
2000 }
2001
2002 // ==========================================================================
2003 // Simplification visualization
2004 // ==========================================================================
2005
2018 Tikz_Plane & plane,
2019 const Polygon & original,
2020 const Polygon & simplified,
2021 const Tikz_Style & original_style = tikz_wire_style("gray!50"),
2022 const Tikz_Style & simplified_style = tikz_wire_style("blue!80", 1.2),
2023 const bool draw_vertices = true,
2024 const Tikz_Style & vertex_style = tikz_points_style("red"))
2025 {
2028 if (draw_vertices)
2030 }
2031
2038 Tikz_Plane & plane,
2039 const Polygon & poly,
2040 const Geom_Number & epsilon,
2042 const Tikz_Style & original_style = tikz_wire_style("gray!50"),
2043 const Tikz_Style & simplified_style = tikz_wire_style("blue!80", 1.2),
2044 const bool draw_vertices = true,
2045 const Tikz_Style & vertex_style = tikz_points_style("red"))
2046 {
2047 Polygon simplified = algorithm.simplify_polygon(poly, epsilon);
2051 return simplified;
2052 }
2053
2060 Tikz_Plane & plane,
2061 const Polygon & poly,
2064 const Tikz_Style & original_style = tikz_wire_style("gray!50"),
2065 const Tikz_Style & simplified_style = tikz_wire_style("green!70!black", 1.2),
2066 const bool draw_vertices = true,
2067 const Tikz_Style & vertex_style = tikz_points_style("red"))
2068 {
2069 Polygon simplified = algorithm.simplify_polygon(poly, area_threshold);
2073 return simplified;
2074 }
2075
2076 // ==========================================================================
2077 // Polygon offset visualization
2078 // ==========================================================================
2079
2092 Tikz_Plane & plane,
2093 const Polygon & original,
2094 const PolygonOffset::Result & result,
2095 const Tikz_Style & original_style = tikz_wire_style("gray!50"),
2096 const Tikz_Style & offset_style = tikz_wire_style("blue!80", 1.2),
2097 const bool draw_vertices = true,
2098 const Tikz_Style & vertex_style = tikz_points_style("red"))
2099 {
2101 for (size_t i = 0; i < result.polygons.size(); ++i)
2102 {
2103 put_in_plane(plane, result.polygons(i), offset_style);
2104 if (draw_vertices)
2105 put_polygon_vertices(plane, result.polygons(i), vertex_style);
2106 }
2107 }
2108
2115 Tikz_Plane & plane,
2116 const Polygon & poly,
2117 const Geom_Number & distance,
2118 const PolygonOffset & algorithm = {},
2120 const Geom_Number & miter_limit = Geom_Number(2),
2121 const Tikz_Style & original_style = tikz_wire_style("gray!50"),
2122 const Tikz_Style & offset_style = tikz_wire_style("blue!80", 1.2),
2123 const bool draw_vertices = true,
2124 const Tikz_Style & vertex_style = tikz_points_style("red"))
2125 {
2126 PolygonOffset::Result result = algorithm(poly, distance, join, miter_limit);
2127 put_offset_result(plane, poly, result,
2130 return result;
2131 }
2132
2133 // ==========================================================================
2134 // Chaikin smoothing visualization
2135 // ==========================================================================
2136
2149 Tikz_Plane & plane,
2150 const Polygon & original,
2151 const Polygon & smoothed,
2152 const Tikz_Style & original_style = tikz_wire_style("gray!50"),
2153 const Tikz_Style & smoothed_style = tikz_wire_style("violet!80", 1.2),
2154 const bool draw_vertices = true,
2155 const Tikz_Style & vertex_style = tikz_points_style("red"))
2156 {
2159 if (draw_vertices)
2161 }
2162
2169 Tikz_Plane & plane,
2170 const Polygon & poly,
2171 const size_t iterations,
2172 const Geom_Number & ratio = Geom_Number(1, 4),
2173 const Tikz_Style & original_style = tikz_wire_style("gray!50"),
2174 const Tikz_Style & smoothed_style = tikz_wire_style("violet!80", 1.2),
2175 const bool draw_vertices = true,
2176 const Tikz_Style & vertex_style = tikz_points_style("red"))
2177 {
2178 Polygon smoothed = ChaikinSmoothing::smooth_polygon(poly, iterations, ratio);
2179 put_smoothing_result(plane, poly, smoothed,
2182 return smoothed;
2183 }
2184
2185 // ==========================================================================
2186 // Trapezoidal Map Visualization
2187 // ==========================================================================
2188
2200 Tikz_Plane & plane,
2202 const Tikz_Style & segment_style = tikz_path_style("red"),
2203 const Tikz_Style & extension_style = tikz_wire_style("gray!60", true),
2204 const bool draw_trapezoids = true,
2205 const double trapezoid_opacity = 0.3,
2209 {
2211 constexpr size_t NONE = TrapezoidalMapPointLocation::NONE;
2212
2213 // Draw filled trapezoids.
2214 if (draw_trapezoids)
2215 {
2216 size_t color_idx = 0;
2217 for (size_t i = 0; i < res.trapezoids.size(); ++i)
2218 {
2219 const Trap & t = res.trapezoids(i);
2220 if (! t.active) continue;
2221
2222 // A trapezoid has 4 corners defined by:
2223 // top-left: intersection of left vertical with top segment
2224 // top-right: intersection of right vertical with top segment
2225 // bot-right: intersection of right vertical with bottom segment
2226 // bot-left: intersection of left vertical with bottom segment
2227 // For simplicity, approximate corners using the endpoints
2228 // and the x-coordinates of the left/right boundary points.
2229 const Point & lp = res.points(t.leftp);
2230 const Point & rp = res.points(t.rightp);
2231 const Segment & top_seg = res.segments(t.top);
2232 const Segment & bot_seg = res.segments(t.bottom);
2233
2234 // Compute y-coordinates at left and right x-boundaries.
2235 auto y_at_x = [](const Segment & seg, const Geom_Number & x)
2236 -> Geom_Number
2237 {
2238 const Geom_Number & x1 = seg.get_src_point().get_x();
2239 const Geom_Number & x2 = seg.get_tgt_point().get_x();
2240 const Geom_Number & y1 = seg.get_src_point().get_y();
2241 const Geom_Number & y2 = seg.get_tgt_point().get_y();
2242 if (x1 == x2) return (y1 + y2) / 2;
2243 return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
2244 };
2245
2246 const Geom_Number lx = lp.get_x();
2247 const Geom_Number rx = rp.get_x();
2248 if (lx == rx)
2249 {
2250 ++color_idx;
2251 continue;
2252 } // degenerate
2253
2254 const Point tl_corner(lx, y_at_x(top_seg, lx));
2255 const Point tr_corner(rx, y_at_x(top_seg, rx));
2256 const Point br_corner(rx, y_at_x(bot_seg, rx));
2257 const Point bl_corner(lx, y_at_x(bot_seg, lx));
2258
2259 // Draw as 4 segments (avoids Polygon self-intersection checks
2260 // that can fail when corners are collinear).
2261 Tikz_Style ts;
2264 ts.opacity = trapezoid_opacity;
2265
2266 // Build polygon with try/catch — skip if degenerate.
2267 try
2268 {
2269 Polygon quad;
2271 quad.add_vertex(br_corner);
2272 quad.add_vertex(tr_corner);
2273 quad.add_vertex(tl_corner);
2274 quad.close();
2275 ts.fill = true;
2276 put_in_plane(plane, quad, ts, trap_layer);
2277 }
2278 catch (...)
2279 {
2280 // Degenerate quad — draw edges instead.
2282 ts, trap_layer);
2284 ts, trap_layer);
2286 ts, trap_layer);
2288 ts, trap_layer);
2289 }
2290 ++color_idx;
2291 }
2292 }
2293
2294 // Draw vertical extensions from input endpoints.
2295 for (size_t i = 0; i < res.num_input_points; ++i)
2296 {
2297 // Find the topmost and bottommost trapezoid boundaries at this point.
2298 // For simplicity, draw a short vertical dashed line through each
2299 // input point spanning the local trapezoid.
2300 const Point & p = res.points(i);
2301 // Walk the trapezoids to find the vertical extent at p.
2302 Geom_Number top_y = p.get_y();
2303 Geom_Number bot_y = p.get_y();
2304 for (size_t j = 0; j < res.trapezoids.size(); ++j)
2305 {
2306 const Trap & t = res.trapezoids(j);
2307 if (! t.active) continue;
2308 if (t.leftp == NONE or t.rightp == NONE) continue;
2309 const Point & lp = res.points(t.leftp);
2310 const Point & rp = res.points(t.rightp);
2311 if (p.get_x() < lp.get_x() or p.get_x() > rp.get_x())
2312 continue;
2313 // This trapezoid covers x-coordinate of p.
2314 auto y_at_x = [](const Segment & seg, const Geom_Number & x)
2315 -> Geom_Number
2316 {
2317 const Geom_Number & x1 = seg.get_src_point().get_x();
2318 const Geom_Number & x2 = seg.get_tgt_point().get_x();
2319 const Geom_Number & y1 = seg.get_src_point().get_y();
2320 const Geom_Number & y2 = seg.get_tgt_point().get_y();
2321 if (x1 == x2) return (y1 + y2) / 2;
2322 return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
2323 };
2324 const Geom_Number ty = y_at_x(res.segments(t.top), p.get_x());
2325 const Geom_Number by = y_at_x(res.segments(t.bottom), p.get_x());
2326 if (ty > top_y) top_y = ty;
2327 if (by < bot_y) bot_y = by;
2328 }
2329 if (top_y > bot_y)
2330 put_in_plane(plane, Segment(Point(p.get_x(), bot_y),
2331 Point(p.get_x(), top_y)),
2333 }
2334
2335 // Draw input segments.
2336 for (size_t i = 0; i < res.num_input_segments; ++i)
2337 put_in_plane(plane, res.segments(i), segment_style, seg_layer);
2338 }
2339
2347 Tikz_Plane & plane,
2348 const Array<Segment> & segments,
2349 const Tikz_Style & segment_style = tikz_path_style("red"),
2350 const Tikz_Style & extension_style = tikz_wire_style("gray!60", true),
2351 const bool draw_trapezoids = true,
2352 const double trapezoid_opacity = 0.3)
2353 {
2355 auto result = tm(segments);
2358 return result;
2359 }
2360
2366 Tikz_Plane & plane,
2367 const Polygon & polygon,
2368 const Tikz_Style & segment_style = tikz_path_style("red"),
2369 const Tikz_Style & extension_style = tikz_wire_style("gray!60", true),
2370 const bool draw_trapezoids = true,
2371 const double trapezoid_opacity = 0.3)
2372 {
2374 auto result = tm(polygon);
2377 return result;
2378 }
2379} // namespace Aleph
2380
2381# endif // TIKZGEOM_ALGORITHMS_H
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
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:139
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
Definition tpl_array.H:351
T & append(const T &data)
Append a copy of data
Definition tpl_array.H:245
void reserve(size_t cap)
Reserves cap cells into the array.
Definition tpl_array.H:315
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
Dynamic singly linked list with functional programming support.
Definition htlist.H:1155
T & append(const T &item)
Definition htlist.H:1271
An axis-aligned ellipse.
Definition point.H:2006
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:229
const Geom_Number & get_x() const noexcept
Gets the x-coordinate value.
Definition point.H:457
const Geom_Number & get_y() const noexcept
Gets the y-coordinate value.
Definition point.H:466
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:520
bool has_curr() const
Check if there is a current segment.
Definition polygon.H:537
A general (irregular) 2D polygon defined by a sequence of vertices.
Definition polygon.H:246
void add_vertex(const Point &point)
Add a vertex to the polygon.
Definition polygon.H:677
void close()
Close the polygon.
Definition polygon.H:840
const bool & is_closed() const
Check if the polygon is closed.
Definition polygon.H:473
const size_t & size() const
Get the number of vertices.
Definition polygon.H:477
Power diagram (weighted Voronoi diagram).
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:1737
const Geom_Number & get_xmin() const
Gets the minimum x-coordinate.
Definition point.H:1764
const Geom_Number & get_ymax() const
Gets the maximum y-coordinate.
Definition point.H:1770
const Geom_Number & get_ymin() const
Gets the minimum y-coordinate.
Definition point.H:1766
const Geom_Number & get_xmax() const
Gets the maximum x-coordinate.
Definition point.H:1768
Exact regular triangulation (weighted Delaunay) via Bowyer-Watson.
A regular polygon defined by center, side length, and vertex count.
Definition polygon.H:1132
Point get_vertex(const size_t &i) const
Get the i-th vertex of the polygon.
Definition polygon.H:1197
const size_t & size() const
Get the number of vertices.
Definition polygon.H:1178
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:827
bool intersects_properly_with(const Segment &s) const
Checks if this segment properly intersects another segment.
Definition point.H:1228
const Point & get_tgt_point() const noexcept
Gets the target point of the segment.
Definition point.H:921
const Point & get_src_point() const noexcept
Gets the source point of the segment.
Definition point.H:915
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:184
static constexpr int Layer_Default
Definition tikzgeom.H:187
static constexpr int Layer_Foreground
Definition tikzgeom.H:188
static constexpr int Layer_Background
Definition tikzgeom.H:186
static constexpr int Layer_Overlay
Definition tikzgeom.H:189
O(log n) point location via trapezoidal map with DAG search.
A non-degenerate triangle defined by three points.
Definition point.H:1478
const Point & get_p3() const
Gets the third vertex.
Definition point.H:1591
const Point & get_p2() const
Gets the second vertex.
Definition point.H:1589
const Point & get_p1() const
Gets the first vertex.
Definition point.H:1587
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:4103
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_y0_function > > y0(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4102
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.
and
Check uniqueness with explicit hash + equality functors.
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_in_plane(Tikz_Plane &plane, const Geom &geom_obj)
Insert any supported geometry type in a Tikz_Plane.
Definition tikzgeom.H:1456
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_wire_style("green!70!black", 1.2), 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_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:2812
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.
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.
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.
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_wire_style("blue!80", 1.2), const bool draw_vertices=true, const Tikz_Style &vertex_style=tikz_points_style("red"))
Draw a polygon offset result overlaid on the original polygon.
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_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_wire_style("violet!80", 1.2), const bool draw_vertices=true, const Tikz_Style &vertex_style=tikz_points_style("red"))
Draw original and smoothed polygons overlaid.
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.
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
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:205
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_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:2821
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:115
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:1561
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_wire_style("blue!80", 1.2), const bool draw_vertices=true, const Tikz_Style &vertex_style=tikz_points_style("red"))
Offset a polygon and draw the result.
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.
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_wire_style("blue!80", 1.2), const bool draw_vertices=true, const Tikz_Style &vertex_style=tikz_points_style("red"))
Simplify a polygon with Douglas-Peucker and draw the result.
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:156
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.
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_wire_style("blue!80", 1.2), const bool draw_vertices=true, const Tikz_Style &vertex_style=tikz_points_style("red"))
Draw original and simplified polygons overlaid.
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.
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_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.
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_wire_style("violet!80", 1.2), const bool draw_vertices=true, const Tikz_Style &vertex_style=tikz_points_style("red"))
Smooth a polygon with Chaikin subdivision and draw the result.
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.
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:489
Complete result of a power diagram computation.
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:86
std::string fill_color
TikZ fill color (fill=<color>)
Definition tikzgeom.H:89
bool with_arrow
Add ->
Definition tikzgeom.H:104
double opacity
opacity=<value> in [0,1], when >= 0
Definition tikzgeom.H:99
bool thick
Add thick
Definition tikzgeom.H:103
bool fill
Fill closed shapes (polygon/triangle/ellipse)
Definition tikzgeom.H:105
bool dashed
Add dashed
Definition tikzgeom.H:101
std::string draw_color
TikZ draw color (draw=<color>)
Definition tikzgeom.H:88
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.
bool with_arrow