2Spatial indexing structures for efficient geometric queries.
5from typing
import List, Set, Optional, Union, Tuple, Any
6from .geometry
import Point, Rectangle, Polygon
10 """A node in the quadtree structure."""
12 def __init__(self, boundary: Rectangle, capacity: int = 10, max_depth: int = 8):
16 self.
objects: List[Tuple[Any, Rectangle]] = []
20 def subdivide(self) -> None:
21 """Divide this node into four quadrants."""
37 def insert(self, obj: Any, bbox: Rectangle) -> bool:
38 """Insert an object with its bounding box."""
45 self.
objects.append((obj, bbox))
55 if child.insert(obj, bbox):
58 self.
objects.append((obj, bbox))
62 self.
objects.append((obj, bbox))
66 """Query all objects that intersect with the given range."""
70 if not self.
boundary.intersects(range_bbox):
75 if bbox.intersects(range_bbox):
81 result.extend(child.query_range(range_bbox))
86 """Query all objects that contain the given point."""
90 if not self.
boundary.contains_point(point):
95 if bbox.contains_point(point):
101 result.extend(child.query_point(point))
106 """Check if bounding box intersects with this node's boundary."""
107 return self.
boundary.intersects(bbox)
110 """Get all objects in this subtree."""
111 result = [obj
for obj, _
in self.
objects]
115 result.extend(child.get_all_objects())
120 """Get total number of objects in this subtree."""
124 count += child.size()
129 """Quadtree spatial index for efficient range and intersection queries."""
131 def __init__(self, boundary: Rectangle, capacity: int = 10, max_depth: int = 8):
135 def insert(self, obj: Any, bbox: Optional[Rectangle] =
None) -> bool:
136 """Insert an object. If bbox is not provided, try to get it from the object."""
138 if hasattr(obj,
'bounding_box'):
139 bbox = obj.bounding_box()
140 elif hasattr(obj,
'boundary'):
142 elif isinstance(obj, Rectangle):
145 raise ValueError(
"Cannot determine bounding box for object")
149 raise ValueError(
"Could not determine bounding box")
157 """Find all objects that intersect with the given range."""
161 """Find all objects that contain the given point."""
165 """Find all pairs of objects that potentially intersect."""
170 for i, (obj1, bbox1)
in enumerate(all_objects):
174 for obj2
in candidates:
175 if obj1 != obj2
and id(obj1) < id(obj2):
176 intersections.append((obj1, obj2))
181 """Find objects within a certain distance of the given object."""
182 if hasattr(obj,
'bounding_box'):
183 bbox = obj.bounding_box()
184 elif isinstance(obj, Rectangle):
187 raise ValueError(
"Cannot determine bounding box for object")
193 bbox.width + 2 * distance,
194 bbox.height + 2 * distance
198 return [candidate
for candidate
in candidates
if candidate != obj]
201 """Get all (object, bbox) pairs from the tree."""
205 """Recursively collect all object-bbox pairs."""
206 pairs = node.objects.copy()
209 for child
in node.children:
215 """Get total number of objects in the tree."""
219 """Remove all objects from the tree."""
220 boundary = self.
root.boundary
221 capacity = self.
root.capacity
222 max_depth = self.
root.max_depth
228 """High-level spatial indexing interface."""
230 def __init__(self, world_bounds: Rectangle, capacity: int = 10, max_depth: int = 8):
236 """Add a polygon to the spatial index."""
245 """Add a rectangle to the spatial index."""
249 self.
objects[obj_id] = rectangle
254 """Remove an object by ID. Note: QuadTree doesn't support efficient removal."""
263 """Find all pairs of polygons with potentially intersecting edges."""
265 all_polygons = [(obj_id, obj)
for obj_id, obj
in self.
objects.items()
266 if isinstance(obj, Polygon)]
268 for i, (id1, poly1)
in enumerate(all_polygons):
269 bbox1 = poly1.bounding_box()
270 candidates = self.
quadtree.query_range(bbox1)
272 for candidate
in candidates:
273 if isinstance(candidate, Polygon):
276 for oid, obj
in self.
objects.items():
281 if id2
is not None and id1 < id2:
282 intersections.append((id1, id2))
287 """Find objects within distance of the given object."""
296 for nearby_obj
in nearby:
297 for oid, stored_obj
in self.
objects.items():
298 if stored_obj
is nearby_obj:
299 nearby_ids.append(oid)
305 """Find all objects that intersect with the given region."""
306 objects_in_region = self.
quadtree.query_range(region)
310 for obj
in objects_in_region:
311 for oid, stored_obj
in self.
objects.items():
312 if stored_obj
is obj:
313 object_ids.append(oid)
Axis-aligned rectangle for bounding boxes and simple EDA components.
Quadtree spatial index for efficient range and intersection queries.
bool insert(const geometry::Rectangle &object)
List[Tuple[Any, Rectangle]] _get_all_object_bbox_pairs(self)
List[Any] find_nearby_objects(self, Any obj, float distance)
std::vector< geometry::Rectangle > query_range(const geometry::Rectangle &range) const
std::unique_ptr< QuadTreeNode< geometry::Rectangle > > root
List[Tuple[Any, Rectangle]] _collect_object_bbox_pairs(self, QuadTreeNode node)
std::vector< std::pair< geometry::Rectangle, geometry::Rectangle > > find_intersections(std::function< bool(const geometry::Rectangle &, const geometry::Rectangle &)> collision_func) const
std::vector< geometry::Rectangle > query_point(const geometry::Point &point) const
__init__(self, Rectangle boundary, int capacity=10, int max_depth=8)
A node in the quadtree structure.
std::vector< T > objects
Objects stored in this node.
std::unique_ptr< QuadTreeNode > children[4]
Child nodes (NW, NE, SW, SE)
std::vector< T > query_range(const geometry::Rectangle &range, const BoundingBoxFunc &get_bbox) const
Query objects in a rectangular range.
__init__(self, Rectangle boundary, int capacity=10, int max_depth=8)
bool _intersects_boundary(self, Rectangle bbox)
size_t size() const
Get total number of objects in this subtree.
bool divided
Whether this node has been subdivided.
size_t max_depth
Maximum subdivision depth.
std::vector< T > query_point(const geometry::Point &point, const BoundingBoxFunc &get_bbox) const
Query objects containing a specific point.
geometry::Rectangle boundary
Spatial boundary of this node.
std::vector< T > get_all_objects() const
Get all objects in this subtree.
size_t capacity
Maximum objects before subdivision.
bool insert(const T &object, const BoundingBoxFunc &get_bbox)
Insert object into this node or appropriate child.
List[int] find_nearby_objects(self, int obj_id, float distance)
__init__(self, Rectangle world_bounds, int capacity=10, int max_depth=8)
List[Tuple[int, int]] find_intersecting_edges(self)
int add_rectangle(self, Rectangle rectangle)
int add_polygon(self, Polygon polygon)
List[int] query_region(self, Rectangle region)
bool remove_object(self, int obj_id)