Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
quadtree_example.C
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
182#include <iostream>
183#include <iomanip>
184#include <string>
185#include <vector>
186#include <random>
187#include <chrono>
188#include <quadtree.H>
189#include <tclap/CmdLine.h>
190
191using namespace std;
192
196ostream& operator<<(ostream& os, const Point& p)
197{
198 return os << "(" << p.get_x() << ", " << p.get_y() << ")";
199}
200
205{
206 cout << "\n" << string(60, '=') << endl;
207 cout << "QuadTree: Basic Operations" << endl;
208 cout << string(60, '=') << endl;
209
210 // Create quadtree for region [0, 100] x [0, 100]
211 // with max 4 points per node before splitting
212 QuadTree tree(0, 100, 0, 100, 4);
213
214 cout << "\nCreated QuadTree for region [0, 100] x [0, 100]" << endl;
215 cout << "Max points per node before split: 4" << endl;
216
217 cout << "\n--- Insertion ---" << endl;
218
219 vector<Point> points = {
220 Point(25, 25), Point(75, 25), Point(25, 75), Point(75, 75),
221 Point(50, 50), Point(10, 10), Point(90, 90), Point(30, 70)
222 };
223
224 cout << "Inserting points:" << endl;
225 for (const auto& p : points)
226 {
227 tree.insert(p);
228 cout << " Inserted " << p << endl;
229 }
230
231 cout << "\n--- Search ---" << endl;
232
234 Point(25, 25), Point(50, 50), Point(99, 99), Point(0, 0)
235 };
236
237 for (const auto& p : to_search)
238 {
239 Point* found = tree.search(p);
240 cout << " Search " << p << ": "
241 << (found ? "FOUND" : "not found") << endl;
242 }
243
244 cout << "\n--- Contains ---" << endl;
245 cout << " Contains (25, 25): " << (tree.contains(Point(25, 25)) ? "yes" : "no") << endl;
246 cout << " Contains (99, 99): " << (tree.contains(Point(99, 99)) ? "yes" : "no") << endl;
247
248 cout << "\n--- Removal ---" << endl;
249
250 cout << " Removing (50, 50)..." << endl;
251 tree.remove(Point(50, 50));
252 cout << " Contains (50, 50) after removal: "
253 << (tree.contains(Point(50, 50)) ? "yes" : "no") << endl;
254}
255
260{
261 cout << "\n" << string(60, '=') << endl;
262 cout << "QuadTree Structure and Subdivision" << endl;
263 cout << string(60, '=') << endl;
264
265 QuadTree tree(0, 100, 0, 100, 2); // Max 2 points per node
266
267 cout << "\nCreated QuadTree with max 2 points per node" << endl;
268 cout << "This will force subdivision earlier." << endl;
269
270 cout << "\n--- Step-by-step insertion ---" << endl;
271
272 // Insert first two points (no split yet)
273 tree.insert(Point(25, 25));
274 cout << "After inserting (25, 25): root has 1 point" << endl;
275
276 tree.insert(Point(75, 25));
277 cout << "After inserting (75, 25): root has 2 points" << endl;
278
279 // Third point triggers split
280 cout << "\nInserting (25, 75) - will trigger subdivision..." << endl;
281 tree.insert(Point(25, 75));
282 cout << "Root split into 4 quadrants:" << endl;
283 cout << " NW: [0, 50] x [0, 50] - contains (25, 25)" << endl;
284 cout << " NE: [50, 100] x [0, 50] - contains (75, 25)" << endl;
285 cout << " SW: [0, 50] x [50, 100] - contains (25, 75)" << endl;
286 cout << " SE: [50, 100] x [50, 100] - empty" << endl;
287
288 cout << "\n--- Visualization ---" << endl;
289 cout << "+----------+----------+" << endl;
290 cout << "| * | * |" << endl;
291 cout << "| (25,25) | (75,25) |" << endl;
292 cout << "+----------+----------+" << endl;
293 cout << "| * | |" << endl;
294 cout << "| (25,75) | (empty) |" << endl;
295 cout << "+----------+----------+" << endl;
296 cout << "NW=*, NE=*, SW=*, SE=empty" << endl;
297}
298
303{
304 cout << "\n" << string(60, '=') << endl;
305 cout << "Practical Example: Geographic Points (Cities)" << endl;
306 cout << string(60, '=') << endl;
307
308 // Simplified coordinate system (not real lat/lon)
309 QuadTree tree(0, 1000, 0, 1000, 5);
310
311 // City locations (simplified)
312 struct City { string name; double x, y; };
314 {"New York", 800, 400},
315 {"Los Angeles", 100, 300},
316 {"Chicago", 600, 420},
317 {"Houston", 400, 200},
318 {"Phoenix", 200, 250},
319 {"Philadelphia", 780, 410},
320 {"San Antonio", 350, 180},
321 {"San Diego", 80, 280},
322 {"Dallas", 420, 220},
323 {"San Jose", 60, 370}
324 };
325
326 cout << "\nInserting " << cities.size() << " cities..." << endl;
327 for (const auto& city : cities)
328 {
329 tree.insert(Point(city.x, city.y));
330 cout << " " << city.name << " at (" << city.x << ", " << city.y << ")" << endl;
331 }
332
333 cout << "\n--- Spatial Queries ---" << endl;
334
335 // Check if point exists
336 Point nyc(800, 400);
337 cout << "\nLooking for a city at (800, 400)..." << endl;
338 if (tree.contains(nyc))
339 cout << " Found! (This is New York)" << endl;
340 else
341 cout << " Not found" << endl;
342
343 // Search for nearby city
344 Point unknown(795, 408);
345 cout << "\nSearching for exact point (795, 408)..." << endl;
346 Point* result = tree.search(unknown);
347 cout << " Result: " << (result ? "found" : "not found (needs exact match)") << endl;
348}
349
354{
355 cout << "\n" << string(60, '=') << endl;
356 cout << "Practical Example: Game Collision Detection" << endl;
357 cout << string(60, '=') << endl;
358
359 cout << "\nScenario: 2D game with objects in a 800x600 screen" << endl;
360
361 QuadTree tree(0, 800, 0, 600, 4);
362
363 // Game objects (enemies, power-ups, etc.)
365 Point(100, 100), Point(150, 120), // Cluster 1
366 Point(700, 500), Point(720, 480), // Cluster 2
367 Point(400, 300), Point(420, 310), // Center
368 Point(50, 550), Point(750, 50) // Corners
369 };
370
371 cout << "\nPlacing " << objects.size() << " game objects..." << endl;
372 for (const auto& obj : objects)
373 tree.insert(obj);
374
375 cout << "\n--- Collision Query ---" << endl;
376
377 Point player(410, 305);
378 cout << "Player at " << player << endl;
379
380 cout << "\nChecking for collision with exact position..." << endl;
381 if (tree.contains(player))
382 cout << " COLLISION! Object at player position." << endl;
383 else
384 cout << " No collision at exact position." << endl;
385
386 // Check nearby positions
387 cout << "\nChecking nearby positions for objects:" << endl;
389 Point(400, 300), Point(420, 310), Point(405, 308)
390 };
391 for (const auto& pos : nearby)
392 {
393 bool collision = tree.contains(pos);
394 cout << " " << pos << ": " << (collision ? "COLLISION" : "clear") << endl;
395 }
396
397 cout << "\n--- Benefits of QuadTree for Games ---" << endl;
398 cout << "1. Only check objects in player's quadrant region" << endl;
399 cout << "2. O(log n) average lookup instead of O(n)" << endl;
400 cout << "3. Scales well with large numbers of objects" << endl;
401}
402
407{
408 cout << "\n" << string(60, '=') << endl;
409 cout << "Performance Analysis (n = " << n << ")" << endl;
410 cout << string(60, '=') << endl;
411
412 QuadTree tree(0, 10000, 0, 10000, 10);
413
414 // Generate random points
415 random_device rd;
416 mt19937 gen(rd());
418
419 vector<Point> points;
420 points.reserve(n);
421 for (int i = 0; i < n; ++i)
422 points.emplace_back(dis(gen), dis(gen));
423
424 cout << "\nGenerated " << n << " random points" << endl;
425
426 // Insertion benchmark
427 auto start = chrono::high_resolution_clock::now();
428
429 for (const auto& p : points)
430 tree.insert(p);
431
432 auto mid = chrono::high_resolution_clock::now();
433
434 // Search benchmark
435 int found = 0;
436 for (const auto& p : points)
437 if (tree.contains(p)) ++found;
438
439 auto end = chrono::high_resolution_clock::now();
440
441 auto insert_us = chrono::duration_cast<chrono::microseconds>(mid - start).count();
442 auto search_us = chrono::duration_cast<chrono::microseconds>(end - mid).count();
443
444 cout << "\nResults:" << endl;
445 cout << " Insert " << n << " points: " << insert_us << " us" << endl;
446 cout << " Search " << n << " points: " << search_us << " us" << endl;
447 cout << " Found: " << found << "/" << n << " points" << endl;
448 cout << " Avg insert: " << (insert_us * 1000.0 / n) << " ns/point" << endl;
449 cout << " Avg search: " << (search_us * 1000.0 / n) << " ns/point" << endl;
450
451 // Comparison note
452 cout << "\n--- Comparison Note ---" << endl;
453 cout << "Linear search would require O(" << n << ") comparisons per query" << endl;
454 cout << "QuadTree reduces this to O(log n) ~= O(" << log2(n) << ") on average" << endl;
455}
456
461{
462 cout << "\n" << string(60, '=') << endl;
463 cout << "Tree Traversal" << endl;
464 cout << string(60, '=') << endl;
465
466 QuadTree tree(0, 100, 0, 100, 2);
467
468 // Insert points to create structure
469 vector<Point> points = {
470 Point(25, 25), Point(75, 25), Point(25, 75), Point(75, 75),
471 Point(12, 12), Point(37, 37)
472 };
473
474 cout << "\nBuilding tree with " << points.size() << " points..." << endl;
475 for (const auto& p : points)
476 tree.insert(p);
477
478 cout << "\n--- Traversing all nodes ---" << endl;
479
480 int node_count = 0;
481 int leaf_count = 0;
482 int point_count = 0;
483
484 tree.for_each([&](QuadNode* node) {
485 ++node_count;
486 if (node->is_leaf())
487 {
488 ++leaf_count;
489 point_count += node->get_points_set().size();
490 }
491
492 string type = node->is_leaf() ? "LEAF" : "INTERNAL";
493 size_t points_in_node = node->is_leaf() ? node->get_points_set().size() : 0;
494
495 cout << " Node (level " << LEVEL(node) << ", " << type;
496 if (node->is_leaf())
497 cout << ", " << points_in_node << " points";
498 cout << ")" << endl;
499 });
500
501 cout << "\nTree statistics:" << endl;
502 cout << " Total nodes: " << node_count << endl;
503 cout << " Leaf nodes: " << leaf_count << endl;
504 cout << " Total points: " << point_count << endl;
505}
506
507int main(int argc, char* argv[])
508{
509 try
510 {
511 TCLAP::CmdLine cmd("QuadTree Spatial Data Structure Example", ' ', "1.0");
512
513 TCLAP::ValueArg<int> nArg("n", "count",
514 "Number of points for performance test", false, 10000, "int");
515 TCLAP::SwitchArg basicArg("b", "basic",
516 "Show basic operations", false);
517 TCLAP::SwitchArg structArg("s", "structure",
518 "Show tree structure", false);
519 TCLAP::SwitchArg geoArg("g", "geographic",
520 "Show geographic points example", false);
521 TCLAP::SwitchArg gameArg("c", "collision",
522 "Show collision detection example", false);
523 TCLAP::SwitchArg perfArg("p", "performance",
524 "Run performance analysis", false);
525 TCLAP::SwitchArg travArg("t", "traversal",
526 "Show tree traversal", false);
527 TCLAP::SwitchArg allArg("a", "all",
528 "Run all demos", false);
529
530 cmd.add(nArg);
531 cmd.add(basicArg);
532 cmd.add(structArg);
533 cmd.add(geoArg);
534 cmd.add(gameArg);
535 cmd.add(perfArg);
536 cmd.add(travArg);
537 cmd.add(allArg);
538
539 cmd.parse(argc, argv);
540
541 int n = nArg.getValue();
542 bool runBasic = basicArg.getValue();
543 bool runStruct = structArg.getValue();
544 bool runGeo = geoArg.getValue();
545 bool runGame = gameArg.getValue();
546 bool runPerf = perfArg.getValue();
547 bool runTrav = travArg.getValue();
548 bool runAll = allArg.getValue();
549
552 runAll = true;
553
554 cout << "=== QuadTree: 2D Spatial Data Structure ===" << endl;
555 cout << "Hierarchical space partitioning into quadrants" << endl;
556
557 if (runAll or runBasic)
559
560 if (runAll or runStruct)
562
563 if (runAll or runGeo)
565
566 if (runAll or runGame)
568
569 if (runAll or runTrav)
571
572 if (runAll or runPerf)
574
575 cout << "\n=== Summary ===" << endl;
576 cout << "QuadTree: Efficient 2D spatial indexing" << endl;
577 cout << "Operations: O(log n) average, O(depth) worst" << endl;
578 cout << "Use cases: GIS, games, graphics, simulations" << endl;
579
580 return 0;
581 }
582 catch (TCLAP::ArgException& e)
583 {
584 cerr << "Error: " << e.error() << " for arg " << e.argId() << endl;
585 return 1;
586 }
587}
588
int main()
void demo_performance()
#define LEVEL(p)
Definition btreepic.C:373
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
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
Node for QuadTree spatial data structure.
Definition quadnode.H:94
DynList< Point > & get_points_set() noexcept
Get reference to the points list (for direct manipulation).
Definition quadnode.H:572
bool is_leaf() const noexcept
Check if this node is a leaf (has no children).
Definition quadnode.H:375
QuadTree - Hierarchical spatial index for 2D points.
Definition quadtree.H:126
void for_each(Op &op)
Apply an operation to each node in the tree.
Definition quadtree.H:542
void remove(const Point &p)
Remove a point from the tree.
Definition quadtree.H:502
Point * search(const Point &p) noexcept
Search for a point in the tree.
Definition quadtree.H:461
bool contains(const Point &p) const noexcept
Check if a point is within the tree's region.
Definition quadtree.H:424
Point * insert(Node *&r, const Point &p)
Recursive insert helper.
Definition quadtree.H:237
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_log2_function > > log2(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4064
static mpfr_t y
Definition mpfr_mul_d.c:3
std::ostream & operator<<(std::ostream &osObject, const Field< T > &rightOp)
Definition ahField.H:121
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
QuadTree spatial data structure for efficient 2D point indexing.
void demo_basic_operations()
Demonstrate basic QuadTree operations.
void demo_geographic_points()
Practical example: Geographic Points.
void demo_traversal()
Demonstrate node traversal.
void demo_collision_detection()
Practical example: Game Collision Detection.
void demo_tree_structure()
Demonstrate tree structure.