Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
robust_predicates_example.cc
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
51#include <iostream>
52#include <cassert>
53#include <geom_algorithms.H>
54#include <point.H>
55
56using namespace std;
57
58static void print_banner(const char * title)
59{
60 cout << "[Aleph Geometry Example] " << title << "\n";
61 cout << "============================================================\n";
62}
63
64static const char * orientation_str(Orientation o)
65{
66 switch (o)
67 {
68 case Orientation::CCW: return "Counter-Clockwise";
69 case Orientation::CW: return "Clockwise";
70 case Orientation::COLLINEAR: return "Collinear";
71 }
72 return "?";
73}
74
75static const char * in_circle_str(InCircleResult r)
76{
77 switch (r)
78 {
79 case InCircleResult::INSIDE: return "INSIDE";
80 case InCircleResult::ON_CIRCLE: return "ON_CIRCLE";
81 case InCircleResult::OUTSIDE: return "OUTSIDE";
82 case InCircleResult::DEGENERATE: return "DEGENERATE";
83 }
84 return "?";
85}
86
87
88// ===================== Scenario 1 =====================
89
91{
92 cout << "=== Scenario 1: Orientation Classification ===" << endl;
93 cout << endl;
94 cout << "Classifying triples of points as CCW, CW, or Collinear using" << endl;
95 cout << "exact rational arithmetic (no floating-point error)." << endl;
96 cout << endl;
97
98 Point a(0, 0), b(4, 0), c(2, 3);
99 cout << " Triple (0,0)-(4,0)-(2,3): "
100 << orientation_str(orientation(a, b, c)) << endl;
101 assert(orientation(a, b, c) == Orientation::CCW);
102
103 cout << " Triple (0,0)-(2,3)-(4,0): "
104 << orientation_str(orientation(a, c, b)) << endl;
105 assert(orientation(a, c, b) == Orientation::CW);
106
107 Point d(1, 1), e(2, 2), f(3, 3);
108 cout << " Triple (1,1)-(2,2)-(3,3): "
109 << orientation_str(orientation(d, e, f)) << endl;
110 assert(orientation(d, e, f) == Orientation::COLLINEAR);
111
112 cout << endl;
113}
114
115
116// ===================== Scenario 2 =====================
117
119{
120 cout << "=== Scenario 2: Segment Intersection Detection ===" << endl;
121 cout << endl;
122
123 // X-cross
124 Segment s1(Point(0, 0), Point(4, 4));
125 Segment s2(Point(0, 4), Point(4, 0));
126 cout << " X-cross (0,0)-(4,4) vs (0,4)-(4,0): "
127 << (segments_intersect(s1, s2) ? "INTERSECT" : "no") << endl;
129
130 // T-shaped
131 Segment s3(Point(0, 0), Point(6, 0));
132 Segment s4(Point(3, 0), Point(3, 5));
133 cout << " T-shaped (0,0)-(6,0) vs (3,0)-(3,5): "
134 << (segments_intersect(s3, s4) ? "INTERSECT" : "no") << endl;
136
137 // Parallel
138 Segment s5(Point(0, 0), Point(4, 0));
139 Segment s6(Point(0, 2), Point(4, 2));
140 cout << " Parallel (0,0)-(4,0) vs (0,2)-(4,2): "
141 << (segments_intersect(s5, s6) ? "INTERSECT" : "no") << endl;
143
144 // Collinear overlap
145 Segment s7(Point(0, 0), Point(3, 0));
146 Segment s8(Point(2, 0), Point(5, 0));
147 cout << " Collinear overlap (0,0)-(3,0) vs (2,0)-(5,0): "
148 << (segments_intersect(s7, s8) ? "INTERSECT" : "no") << endl;
150
151 // Disjoint
152 Segment s9(Point(0, 0), Point(1, 1));
153 Segment s10(Point(5, 5), Point(6, 7));
154 cout << " Disjoint (0,0)-(1,1) vs (5,5)-(6,7): "
155 << (segments_intersect(s9, s10) ? "INTERSECT" : "no") << endl;
157
158 // 4-point overload
159 cout << " 4-point API (0,0)-(2,2) vs (0,2)-(2,0): "
160 << (segments_intersect(Point(0,0), Point(2,2), Point(0,2), Point(2,0))
161 ? "INTERSECT" : "no") << endl;
162 assert(segments_intersect(Point(0,0), Point(2,2), Point(0,2), Point(2,0)));
163
164 cout << endl;
165}
166
167
168// ===================== Scenario 3 =====================
169
171{
172 cout << "=== Scenario 3: Exact Intersection Points ===" << endl;
173 cout << endl;
174 cout << "All intersection points are computed in exact rational arithmetic" << endl;
175 cout << "(mpq_class), so there is no floating-point rounding error." << endl;
176 cout << endl;
177
178 // Simple X: result is (1,1)
179 Segment s1(Point(0, 0), Point(2, 2));
180 Segment s2(Point(0, 2), Point(2, 0));
182 cout << " (0,0)-(2,2) x (0,2)-(2,0) = " << p1.to_string() << endl;
183 assert(p1.get_x() == 1 && p1.get_y() == 1);
184
185 // Exact rational: intersection at (3/2, 0)
186 Segment h(Point(0, 0), Point(3, 0));
187 Segment d(Point(1, 1), Point(2, -1));
189 cout << " (0,0)-(3,0) x (1,1)-(2,-1) = " << p2.to_string()
190 << " [exact: x=" << p2.get_x() << "]" << endl;
191 assert(p2.get_x() == Geom_Number(3, 2));
192 assert(p2.get_y() == 0);
193
194 // Non-trivial: intersection at (7/3, 2/3)
195 Segment a(Point(0, 0), Point(7, 2));
196 Segment b(Point(0, 3), Point(3, 0));
198 cout << " (0,0)-(7,2) x (0,3)-(3,0) = " << p3.to_string()
199 << " [exact: x=" << p3.get_x() << " y=" << p3.get_y() << "]" << endl;
200 assert(p3.get_x() == Geom_Number(7, 3));
201 assert(p3.get_y() == Geom_Number(2, 3));
202
203 // Vertical x diagonal
204 Segment v(Point(3, 0), Point(3, 6));
205 Segment diag(Point(0, 0), Point(6, 6));
207 cout << " Vertical x=3 x diagonal y=x: " << p4.to_string() << endl;
208 assert(p4.get_x() == 3 && p4.get_y() == 3);
209
210 cout << endl;
211}
212
213
214// ===================== Scenario 4 =====================
215
217{
218 cout << "=== Scenario 4: Road Network Crossing Analysis ===" << endl;
219 cout << endl;
220 cout << "Given a small network of road segments, detect which pairs cross." << endl;
221 cout << endl;
222
223 struct Road
224 {
225 const char * name;
226 Segment seg;
227 };
228
230 roads.append({"Main St", Segment(Point(0, 2), Point(10, 2))});
231 roads.append({"Broadway", Segment(Point(3, 0), Point(3, 8))});
232 roads.append({"Diagonal Av", Segment(Point(0, 0), Point(8, 6))});
233 roads.append({"Park Rd", Segment(Point(6, 0), Point(6, 8))});
234 const size_t n = roads.size();
235
236 for (size_t i = 0; i < n; ++i)
237 for (size_t j = i + 1; j < n; ++j)
238 if (segments_intersect(roads[i].seg, roads[j].seg))
239 {
240 if (roads[i].seg.is_parallel_with(roads[j].seg))
241 {
242 cout << " " << roads[i].name << " overlaps with "
243 << roads[j].name << " (collinear)" << endl;
244 }
245 else
246 {
248 cout << " " << roads[i].name << " crosses " << roads[j].name
249 << " at " << ix.to_string() << endl;
250 }
251 }
252
253 cout << endl;
254
255 // Verify known crossings
256 // Main St x Broadway at (3,2)
258 assert(ix1.get_x() == 3 && ix1.get_y() == 2);
259
260 // Main St x Diagonal Av: y=2 => 2 = (6/8)*x => x = 8/3
262 assert(ix2.get_x() == Geom_Number(8, 3));
263
264 cout << " All crossing points verified with exact arithmetic." << endl;
265 cout << endl;
266}
267
268
269// ===================== Scenario 5 =====================
270
272{
273 cout << "=== Scenario 5: in_circle() in a Delaunay Context ===" << endl;
274 cout << endl;
275 cout << "Checking local Delaunay legality using exact in-circle predicates." << endl;
276 cout << endl;
277
278 const Point a(0, 0), b(4, 0), c(0, 4);
279 const Point d_inside(1, 1);
280 const Point d_outside(5, 5);
281
282 const InCircleResult r1 = in_circle(a, b, c, d_inside);
283 const InCircleResult r2 = in_circle(a, b, c, d_outside);
284
285 cout << " in_circle((0,0),(4,0),(0,4),(1,1)) = " << in_circle_str(r1) << endl;
286 cout << " in_circle((0,0),(4,0),(0,4),(5,5)) = " << in_circle_str(r2) << endl;
287 assert(r1 == InCircleResult::INSIDE);
288 assert(r2 == InCircleResult::OUTSIDE);
289
291 pts.append(a);
292 pts.append(b);
293 pts.append(c);
294 pts.append(Point(4, 4));
295 pts.append(Point(2, 1));
296
298 const auto dt = delaunay(pts);
299
300 cout << " Delaunay triangles built from the same predicate logic: "
301 << dt.triangles.size() << endl;
302 assert(not dt.triangles.is_empty());
303 cout << endl;
304}
305
306
307int main()
308{
309 print_banner("Robust Predicates");
310 cout << endl;
311
317
318 cout << "All scenarios completed successfully." << endl;
319 cout << "STATUS: OK" << endl;
320 return 0;
321}
long double h
Definition btreepic.C:154
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:139
T & append(const T &data)
Append a copy of data
Definition tpl_array.H:245
Exact Delaunay triangulation using the Bowyer-Watson incremental algorithm.
Dynamic singly linked list with functional programming support.
Definition htlist.H:1155
T & append(const T &item)
Definition htlist.H:1271
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
std::string to_string() const
Returns a string representation of the point as "(x,y)".
Definition point.H:651
const Geom_Number & get_y() const noexcept
Gets the y-coordinate value.
Definition point.H:466
Represents a line segment between two points.
Definition point.H:827
Computational geometry algorithms.
Orientation
Classification of three-point orientation.
Definition point.H:2812
bool segments_intersect(const Segment &s1, const Segment &s2)
Return true if segments s1 and s2 intersect (including endpoints).
Definition point.H:2883
InCircleResult in_circle(const Point &a, const Point &b, const Point &c, const Point &p)
Classify point p against circumcircle of triangle (a,b,c), exactly.
Definition point.H:2857
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.
Point segment_intersection_point(const Segment &s1, const Segment &s2)
Compute the exact intersection point of segments s1 and s2.
Definition point.H:2900
InCircleResult
Classification of a point with respect to a triangle circumcircle.
Definition point.H:2830
Orientation orientation(const Point &a, const Point &b, const Point &c)
Return the orientation of the triple (a, b, c).
Definition point.H:2821
STL namespace.
2D point and geometric utilities.
void scenario_in_circle_in_delaunay_context()
void scenario_exact_intersection()
void scenario_orientation()
void scenario_intersection_detection()
static const char * in_circle_str(InCircleResult r)
static void print_banner(const char *title)
static const char * orientation_str(Orientation o)
void scenario_road_network()
gsl_rng * r