further performance improvements
This commit is contained in:
parent
8bf0ff279f
commit
c36bce9978
8 changed files with 168 additions and 58 deletions
|
|
@ -17,7 +17,7 @@ class CollisionEngine:
|
|||
__slots__ = (
|
||||
'clearance', 'max_net_width', 'safety_zone_radius',
|
||||
'static_index', 'static_geometries', 'static_dilated', 'static_prepared', '_static_id_counter',
|
||||
'dynamic_index', 'dynamic_geometries', 'dynamic_dilated', '_dynamic_id_counter'
|
||||
'dynamic_index', 'dynamic_geometries', 'dynamic_dilated', 'dynamic_prepared', '_dynamic_id_counter'
|
||||
)
|
||||
|
||||
clearance: float
|
||||
|
|
@ -60,6 +60,7 @@ class CollisionEngine:
|
|||
self.dynamic_geometries: dict[int, tuple[str, Polygon]] = {}
|
||||
# obj_id -> dilated_geometry (by clearance/2)
|
||||
self.dynamic_dilated: dict[int, Polygon] = {}
|
||||
self.dynamic_prepared: dict[int, PreparedGeometry] = {}
|
||||
self._dynamic_id_counter = 0
|
||||
|
||||
def add_static_obstacle(self, polygon: Polygon) -> None:
|
||||
|
|
@ -96,6 +97,7 @@ class CollisionEngine:
|
|||
|
||||
self.dynamic_geometries[obj_id] = (net_id, poly)
|
||||
self.dynamic_dilated[obj_id] = dil
|
||||
self.dynamic_prepared[obj_id] = prep(dil)
|
||||
self.dynamic_index.insert(obj_id, dil.bounds)
|
||||
|
||||
def remove_path(self, net_id: str) -> None:
|
||||
|
|
@ -109,6 +111,7 @@ class CollisionEngine:
|
|||
for obj_id in to_remove:
|
||||
nid, poly = self.dynamic_geometries.pop(obj_id)
|
||||
dilated = self.dynamic_dilated.pop(obj_id)
|
||||
self.dynamic_prepared.pop(obj_id)
|
||||
self.dynamic_index.delete(obj_id, dilated.bounds)
|
||||
|
||||
def lock_net(self, net_id: str) -> None:
|
||||
|
|
@ -122,6 +125,7 @@ class CollisionEngine:
|
|||
for obj_id in to_move:
|
||||
nid, poly = self.dynamic_geometries.pop(obj_id)
|
||||
dilated = self.dynamic_dilated.pop(obj_id)
|
||||
self.dynamic_prepared.pop(obj_id)
|
||||
self.dynamic_index.delete(obj_id, dilated.bounds)
|
||||
# Re-buffer for static clearance if necessary.
|
||||
# Note: dynamic is clearance/2, static is clearance.
|
||||
|
|
@ -178,20 +182,28 @@ class CollisionEngine:
|
|||
for obj_id in candidates:
|
||||
if self.static_prepared[obj_id].intersects(geometry):
|
||||
if start_port or end_port:
|
||||
# Optimization: Instead of expensive buffer + intersection,
|
||||
# use distance() and check if it's within clearance only near ports.
|
||||
raw_obstacle = self.static_geometries[obj_id]
|
||||
# If the intersection is within clearance, distance will be < clearance.
|
||||
# We already know it intersects the dilated obstacle, so distance < clearance.
|
||||
|
||||
is_safe = False
|
||||
# Optimization: Skip expensive intersection if neither port is near the obstacle's bounds
|
||||
# (Plus a small margin for safety zone)
|
||||
sz = self.safety_zone_radius
|
||||
is_near_port = False
|
||||
for p in [start_port, end_port]:
|
||||
if p:
|
||||
# Quick bounds check
|
||||
b = self.static_dilated[obj_id].bounds
|
||||
if (b[0] - sz <= p.x <= b[2] + sz and
|
||||
b[1] - sz <= p.y <= b[3] + sz):
|
||||
is_near_port = True
|
||||
break
|
||||
|
||||
# Use intersection bounds to check proximity to ports
|
||||
# We need the intersection of the geometry and the RAW obstacle
|
||||
if not is_near_port:
|
||||
return True # Collision, and not near any port safety zone
|
||||
|
||||
# Only if near port, do the expensive check
|
||||
raw_obstacle = self.static_geometries[obj_id]
|
||||
intersection = geometry.intersection(raw_obstacle)
|
||||
if not intersection.is_empty:
|
||||
ix_minx, ix_miny, ix_maxx, ix_maxy = intersection.bounds
|
||||
is_safe = False
|
||||
for p in [start_port, end_port]:
|
||||
if p and (abs(ix_minx - p.x) < sz and
|
||||
abs(ix_maxx - p.x) < sz and
|
||||
|
|
@ -199,9 +211,9 @@ class CollisionEngine:
|
|||
abs(ix_maxy - p.y) < sz):
|
||||
is_safe = True
|
||||
break
|
||||
|
||||
if is_safe:
|
||||
continue
|
||||
|
||||
if is_safe:
|
||||
continue
|
||||
return True
|
||||
return False
|
||||
|
||||
|
|
@ -213,6 +225,6 @@ class CollisionEngine:
|
|||
count = 0
|
||||
for obj_id in candidates:
|
||||
other_net_id, _ = self.dynamic_geometries[obj_id]
|
||||
if other_net_id != net_id and test_poly.intersects(self.dynamic_dilated[obj_id]):
|
||||
if other_net_id != net_id and self.dynamic_prepared[obj_id].intersects(test_poly):
|
||||
count += 1
|
||||
return count
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue