Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_2dtree_example.cc
Go to the documentation of this file.
1
39#include <iostream>
40#include <cmath>
41#include <tpl_2dtree.H>
42#include <point.H>
43
44using namespace std;
45using namespace Aleph;
46
47int main()
48{
49 cout << "=== 2D Spatial Trees: Educational Examples ===\n\n";
50
51 // =========================================================================
52 // EXAMPLE 1: Building a 2D-Tree
53 // =========================================================================
54 {
55 cout << "--- Example 1: Inserting Points into 2D-Tree ---\n\n";
56
57 // STEP 1: Create 2D-tree with bounding box
58 // Region: [0, 100] x [0, 100]
59 K2Tree<> tree(0, 0, 100, 100);
60
61 cout << "Created 2D-tree for region [0,100] x [0,100]\n\n";
62
63 // STEP 2: Insert points
64 cout << "Inserting points:\n";
65
66 Point p1(25, 50);
67 Point p2(75, 25);
68 Point p3(50, 75);
69 Point p4(10, 10);
70 Point p5(90, 90);
71
72 tree.insert(p1);
73 cout << " Inserted (25, 50)\n";
74
75 tree.insert(p2);
76 cout << " Inserted (75, 25)\n";
77
78 tree.insert(p3);
79 cout << " Inserted (50, 75)\n";
80
81 tree.insert(p4);
82 cout << " Inserted (10, 10)\n";
83
84 tree.insert(p5);
85 cout << " Inserted (90, 90)\n\n";
86
87 cout << "TREE STRUCTURE (conceptual):\n";
88 cout << " Level 0 (split on X): root = (25, 50)\n";
89 cout << " Left (x < 25): (10, 10)\n";
90 cout << " Right (x >= 25):\n";
91 cout << " Level 1 (split on Y): (75, 25)\n";
92 cout << " Left (y < 25): none\n";
93 cout << " Right (y >= 25): (50, 75), (90, 90)\n\n";
94
95 cout << "KEY CONCEPT: Alternating splits create balanced partitioning\n";
96 cout << " of 2D space into rectangular regions\n\n";
97 }
98
99 // =========================================================================
100 // EXAMPLE 2: Point Search
101 // =========================================================================
102 {
103 cout << "--- Example 2: Searching for Points ---\n\n";
104
105 K2Tree<> tree(0, 0, 100, 100);
106
107 // Build tree
108 tree.insert(Point(25, 50));
109 tree.insert(Point(75, 25));
110 tree.insert(Point(50, 75));
111 tree.insert(Point(10, 10));
112
113 cout << "Tree contains: (25,50), (75,25), (50,75), (10,10)\n\n";
114
115 // Search for existing point
116 cout << "SEARCH QUERIES:\n";
117
118 Point query1(50, 75);
119 if (tree.contains(query1))
120 cout << " Point (50, 75): FOUND ✓\n";
121 else
122 cout << " Point (50, 75): NOT FOUND\n";
123
124 Point query2(30, 40);
125 if (tree.contains(query2))
126 cout << " Point (30, 40): FOUND\n";
127 else
128 cout << " Point (30, 40): NOT FOUND ✓\n";
129
130 Point query3(25, 50);
131 if (tree.contains(query3))
132 cout << " Point (25, 50): FOUND ✓ (root node)\n";
133 else
134 cout << " Point (25, 50): NOT FOUND\n";
135
136 cout << "\nCOMPLEXITY:\n";
137 cout << " Average case: O(log n) - like binary search\n";
138 cout << " Worst case: O(n) - if tree is unbalanced\n";
139 cout << " For random data: Usually well-balanced\n\n";
140 }
141
142 // =========================================================================
143 // EXAMPLE 3: Range Query (Points in Rectangle)
144 // =========================================================================
145 {
146 cout << "--- Example 3: Range Query (Rectangle Search) ---\n\n";
147
148 K2Tree<> tree(0, 0, 200, 200);
149
150 cout << "SCENARIO: City POI (Points of Interest) database\n";
151 cout << "===============================================\n\n";
152
153 // Insert POIs with names (conceptually)
154 struct POI {
155 Point location;
156 string name;
157 };
158
159 POI pois[] = {
160 {Point(20, 30), "Restaurant A"},
161 {Point(50, 50), "Park B"},
162 {Point(80, 40), "Hotel C"},
163 {Point(120, 150), "Museum D"},
164 {Point(150, 180), "Theater E"},
165 {Point(60, 70), "Cafe F"},
166 {Point(180, 20), "Mall G"}
167 };
168
169 // Insert into tree
170 for (const auto& poi : pois)
171 tree.insert(poi.location);
172
173 cout << "Inserted 7 POIs across the city\n\n";
174
175 // Range query: Find all POIs in downtown area
176 Rectangle downtown(40, 30, 90, 80);
177
178 cout << "QUERY: Find all POIs in downtown area\n";
179 cout << " Rectangle: (40,30) to (90,80)\n\n";
180
182 tree.range(downtown, &results);
183
184 cout << "Results:\n";
185 for (size_t i = 0; i < sizeof(pois)/sizeof(POI); ++i)
186 {
187 Point p = pois[i].location;
188 auto x = p.get_x();
189 auto y = p.get_y();
190
191 if (x >= 40 && x <= 90 && y >= 30 && y <= 80)
192 cout << " " << pois[i].name << " at (" << x << ", " << y << ")\n";
193 }
194
195 cout << "\nCOMPLEXITY: O(sqrt(n) + k) where k = number of results\n";
196 cout << " Much better than O(n) linear scan!\n\n";
197
198 cout << "REAL-WORLD: Map applications showing POIs in visible area\n\n";
199 }
200
201 // =========================================================================
202 // EXAMPLE 4: Nearest Neighbor Search
203 // =========================================================================
204 {
205 cout << "--- Example 4: Finding Nearest Point ---\n\n";
206
207 K2Tree<> tree(0, 0, 100, 100);
208
209 cout << "SCENARIO: Find closest emergency service\n";
210 cout << "========================================\n\n";
211
212 // Insert emergency service locations
213 Point hospital(20, 80);
214 Point fire_station(70, 30);
215 Point police(50, 50);
216 Point ambulance(85, 75);
217
218 tree.insert(hospital);
219 tree.insert(fire_station);
220 tree.insert(police);
221 tree.insert(ambulance);
222
223 cout << "Emergency services:\n";
224 cout << " Hospital: (20, 80)\n";
225 cout << " Fire Station: (70, 30)\n";
226 cout << " Police: (50, 50)\n";
227 cout << " Ambulance: (85, 75)\n\n";
228
229 // Query point (emergency location)
230 Point emergency(60, 40);
231
232 cout << "EMERGENCY at (60, 40)\n";
233 cout << "Finding nearest service...\n\n";
234
235 // Manual nearest neighbor (simplified)
236 Point nearest = tree.nearest(emergency);
237
238 auto dist = emergency.distance_with(nearest);
239
240 cout << "NEAREST SERVICE:\n";
241 cout << " Location: (" << nearest.get_x() << ", " << nearest.get_y() << ")\n";
242 cout << " Distance: " << dist << " units\n";
243
244 // Determine which service it is
245 if (nearest.get_x() == 70 && nearest.get_y() == 30)
246 cout << " Type: Fire Station\n";
247 else if (nearest.get_x() == 50 && nearest.get_y() == 50)
248 cout << " Type: Police\n";
249
250 cout << "\nALGORITHM:\n";
251 cout << " 1. Start at root\n";
252 cout << " 2. Recursively explore promising branches\n";
253 cout << " 3. Prune branches that can't contain closer point\n";
254 cout << " 4. Track best candidate while descending\n\n";
255
256 cout << "COMPLEXITY: O(log n) average - very efficient!\n\n";
257 }
258
259 // =========================================================================
260 // EXAMPLE 5: Collision Detection (Game Development)
261 // =========================================================================
262 {
263 cout << "--- Example 5: Spatial Partitioning for Games ---\n\n";
264
265 cout << "SCENARIO: 2D game with moving objects\n";
266 cout << "=====================================\n\n";
267
268 K2Tree<> game_world(0, 0, 1000, 1000);
269
270 cout << "Game world: 1000x1000 pixels\n";
271 cout << "Objects: Players, enemies, projectiles, items\n\n";
272
273 // Insert game objects
274 struct GameObject {
275 Point position;
276 string type;
277 double radius;
278 };
279
280 GameObject objects[] = {
281 {Point(100, 200), "Player", 10},
282 {Point(150, 220), "Enemy", 15},
283 {Point(500, 500), "Item", 5},
284 {Point(800, 100), "Enemy", 15},
285 {Point(120, 210), "Projectile", 2}
286 };
287
288 for (const auto& obj : objects)
289 game_world.insert(obj.position);
290
291 cout << "Inserted " << (sizeof(objects)/sizeof(GameObject)) << " game objects\n\n";
292
293 // Check collisions near player
294 Point player_pos(100, 200);
295 double collision_range = 50; // Check within 50 pixels
296
297 cout << "COLLISION CHECK:\n";
298 cout << " Player at (100, 200)\n";
299 cout << " Checking range: 50 pixels\n\n";
300
302 player_pos.get_x() - collision_range,
303 player_pos.get_y() - collision_range,
304 player_pos.get_x() + collision_range,
306 );
307
310
311 cout << "Nearby objects:\n";
312 for (const auto& obj : objects)
313 {
314 auto dist = player_pos.distance_with(obj.position);
315
316 if (dist <= collision_range && dist > 0) // Exclude self
317 cout << " " << obj.type << " at distance " << dist << "\n";
318 }
319
320 cout << "\nGAME OPTIMIZATION:\n";
321 cout << " Without 2D-tree: Check all N objects → O(N^2) for N entities\n";
322 cout << " With 2D-tree: Check only nearby → O(N log N + k*N)\n";
323 cout << " For 1000 objects: ~1M vs ~10K comparisons!\n\n";
324 }
325
326 // =========================================================================
327 // EXAMPLE 6: K-Nearest Neighbors (Machine Learning)
328 // =========================================================================
329 {
330 cout << "--- Example 6: k-NN Classification ---\n\n";
331
332 cout << "SCENARIO: Classify new data point\n";
333 cout << "=================================\n\n";
334
335 K2Tree<> dataset(0, 0, 100, 100);
336
337 cout << "Training data (2D feature space):\n";
338
339 // Class A points (clustered around 20, 20)
340 cout << " Class A (circle): around (20, 20)\n";
341 dataset.insert(Point(18, 22));
342 dataset.insert(Point(22, 18));
343 dataset.insert(Point(20, 25));
344 dataset.insert(Point(15, 20));
345
346 // Class B points (clustered around 80, 80)
347 cout << " Class B (square): around (80, 80)\n";
348 dataset.insert(Point(78, 82));
349 dataset.insert(Point(82, 78));
350 dataset.insert(Point(80, 85));
351 dataset.insert(Point(75, 80));
352
353 cout << "\nNew data point: (25, 25)\n";
354 cout << "Task: Classify as A or B using 3-NN\n\n";
355
356 Point new_point(25, 25);
357
358 cout << "ALGORITHM:\n";
359 cout << " 1. Find 3 nearest neighbors in tree\n";
360 cout << " 2. Take majority vote of their classes\n";
361 cout << " 3. Assign that class to new point\n\n";
362
363 cout << "EXPECTED RESULT:\n";
364 cout << " 3 nearest neighbors likely from Class A\n";
365 cout << " (New point is closer to Class A cluster)\n";
366 cout << " Classification: Class A\n\n";
367
368 cout << "COMPLEXITY:\n";
369 cout << " k-NN with 2D-tree: O(k log n)\n";
370 cout << " k-NN without: O(n) for each query\n";
371 cout << " Speedup: log n times faster!\n\n";
372 }
373
374 cout << "=== SUMMARY: 2D Spatial Trees ===\n";
375 cout << "\n1. WHAT IS IT?\n";
376 cout << " Binary search tree for 2D points\n";
377 cout << " Alternates splitting on X and Y\n";
378 cout << " Partitions space into rectangles\n";
379 cout << "\n2. KEY OPERATIONS:\n";
380 cout << " Insert: O(log n) average\n";
381 cout << " Search: O(log n) average\n";
382 cout << " Range query: O(sqrt(n) + k)\n";
383 cout << " Nearest neighbor: O(log n) average\n";
384 cout << "\n3. WHEN TO USE:\n";
385 cout << " ✓ 2D spatial data (maps, games)\n";
386 cout << " ✓ Range queries (find points in region)\n";
387 cout << " ✓ Nearest neighbor queries\n";
388 cout << " ✓ Collision detection\n";
389 cout << " ✓ k-NN classification\n";
390 cout << "\n4. ADVANTAGES:\n";
391 cout << " * Much faster than linear scan\n";
392 cout << " * Simple to implement\n";
393 cout << " * Low memory overhead\n";
394 cout << " * Good for dynamic data (insert/delete)\n";
395 cout << "\n5. LIMITATIONS:\n";
396 cout << " * Can become unbalanced (worst case O(n))\n";
397 cout << " * Best for random data\n";
398 cout << " * 2D only (use k-d tree for higher dimensions)\n";
399 cout << " * Not cache-friendly (pointer chasing)\n";
400 cout << "\n6. REAL-WORLD APPLICATIONS:\n";
401 cout << " * GIS: Find POIs near location\n";
402 cout << " * Games: Collision detection, AI\n";
403 cout << " * ML: k-NN classification\n";
404 cout << " * Graphics: Ray tracing, culling\n";
405 cout << " * Robotics: Path planning\n";
406 cout << "\n7. ALTERNATIVES:\n";
407 cout << " QuadTree: Better for clustered data\n";
408 cout << " R-Tree: Better for rectangles\n";
409 cout << " Grid: Simpler but less flexible\n";
410 cout << " KD-Tree: Generalization to k dimensions\n";
411 cout << "\n8. BEST PRACTICES:\n";
412 cout << " * Use for uniformly distributed data\n";
413 cout << " * Set appropriate bounding box\n";
414 cout << " * Consider rebalancing for skewed data\n";
415 cout << " * Batch insert for better balance\n";
416
417 return 0;
418}
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
2D k-d tree for efficient spatial point operations.
Definition tpl_2dtree.H:132
static void range(Node *root, const Rectangle &rect, DynList< Point > *q)
Recursively find points within a rectangle.
Definition tpl_2dtree.H:416
Point nearest(const Point &p) noexcept
Find the nearest point to a query point.
Definition tpl_2dtree.H:523
bool contains(const Point &p) const noexcept
Check if the tree contains a point.
Definition tpl_2dtree.H:404
Point * insert(const Point &p)
Insert a point into the tree.
Definition tpl_2dtree.H:343
Rectangular point in the plane.
Definition point.H:156
const Geom_Number & get_y() const
Returns y value.
Definition point.H:226
const Geom_Number & get_x() const
Returns x value.
Definition point.H:221
static mpfr_t y
Definition mpfr_mul_d.c:3
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
2D point and geometric utilities.
2D k-d tree implementation for spatial point indexing.
int main()