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