From 8fc2c7c67b86851a5ae3718f377b45ce5495fdcd Mon Sep 17 00:00:00 2001 From: Eric Vin Date: Thu, 11 Jul 2024 12:46:27 +0200 Subject: [PATCH 1/6] Minor tweaks to PolygonalRegion. --- src/scenic/core/regions.py | 9 ++++++++- tests/core/test_regions.py | 9 +++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/scenic/core/regions.py b/src/scenic/core/regions.py index 529b516a9..e9c0f27f0 100644 --- a/src/scenic/core/regions.py +++ b/src/scenic/core/regions.py @@ -3049,7 +3049,14 @@ def __eq__(self, other): @cached def __hash__(self): - return hash((self.polygons, self.orientation, self.z)) + return hash( + ( + tuple(self._points) if self._points else None, + self._polygon, + self.orientation, + self.z, + ) + ) class CircularRegion(PolygonalRegion): diff --git a/tests/core/test_regions.py b/tests/core/test_regions.py index ea48796b2..07c84d3cc 100644 --- a/tests/core/test_regions.py +++ b/tests/core/test_regions.py @@ -5,6 +5,7 @@ import shapely.geometry import trimesh.voxel +from scenic.core.distributions import RandomControlFlowError, Range from scenic.core.object_types import Object, OrientedPoint from scenic.core.regions import * from scenic.core.vectors import VectorField @@ -222,6 +223,14 @@ def test_polygon_region(): PolygonalRegion([(1, 1), (3, 1), (2, 2), (1.3, 1.15)], z=3).uniformPointInner().z == 3 ) + assert i != d + hash(i) + e = CircularRegion((0, 0), Range(1, 3)) + with pytest.raises(RandomControlFlowError): + i == e + with pytest.raises(RandomControlFlowError): + e == i + hash(e) def test_polygon_unionAll(): From 6b7f3ab5041aff7062e25239d5c93f644015fd1a Mon Sep 17 00:00:00 2001 From: Eric Vin Date: Fri, 12 Jul 2024 19:33:24 +0200 Subject: [PATCH 2/6] Fixed PolygonalRegion points normalization --- src/scenic/core/regions.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/scenic/core/regions.py b/src/scenic/core/regions.py index e9c0f27f0..18bc5884f 100644 --- a/src/scenic/core/regions.py +++ b/src/scenic/core/regions.py @@ -2748,7 +2748,7 @@ class PolygonalRegion(Region): def __init__( self, - points=None, + points=tuple(), polygon=None, z=0, orientation=None, @@ -2759,8 +2759,8 @@ def __init__( name, points, polygon, z, *additionalDeps, orientation=orientation ) - # Store main parameter - self._points = points + # Normalize and store main parameters + self._points = tuple() if points is None else tuple(points) self._polygon = polygon self.z = z @@ -3051,7 +3051,7 @@ def __eq__(self, other): def __hash__(self): return hash( ( - tuple(self._points) if self._points else None, + self._points, self._polygon, self.orientation, self.z, From b4a3b044839ca9603c0b5b7b181241b857382b97 Mon Sep 17 00:00:00 2001 From: Eric Vin Date: Wed, 17 Jul 2024 17:20:06 -0700 Subject: [PATCH 3/6] Deprecated PolygonalRegion points method. --- src/scenic/core/regions.py | 18 ++++++++++-------- src/scenic/simulators/webots/road/interface.py | 11 +++++++---- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/scenic/core/regions.py b/src/scenic/core/regions.py index 18bc5884f..57b5ccad8 100644 --- a/src/scenic/core/regions.py +++ b/src/scenic/core/regions.py @@ -2774,7 +2774,6 @@ def __init__( points = tuple(pt[:2] for pt in points) if len(points) == 0: raise ValueError("tried to create PolygonalRegion from empty point list!") - self.points = points polygon = shapely.geometry.Polygon(points) if isinstance(polygon, shapely.geometry.Polygon): @@ -2791,13 +2790,6 @@ def __init__( "tried to create PolygonalRegion with " f"invalid polygon {self.polygons}" ) - if ( - points is None - and len(self.polygons.geoms) == 1 - and len(self.polygons.geoms[0].interiors) == 0 - ): - self.points = tuple(self.polygons.geoms[0].exterior.coords[:-1]) - if self.polygons.is_empty: raise ValueError("tried to create empty PolygonalRegion") shapely.prepare(self.polygons) @@ -2972,6 +2964,16 @@ def unionAll(regions, buf=0): z = 0 if z is None else z return PolygonalRegion(polygon=union, orientation=orientation, z=z) + @property + @distributionFunction + def points(self): + warnings.warn( + "The `points` method is deprecated and will be removed in Scenic 3.3.0." + "Users should use the `boundary` method instead.", + DeprecationWarning, + ) + return self.boundary.points + @property @distributionFunction def boundary(self) -> "PolylineRegion": diff --git a/src/scenic/simulators/webots/road/interface.py b/src/scenic/simulators/webots/road/interface.py index 661d460bf..f9eed5356 100644 --- a/src/scenic/simulators/webots/road/interface.py +++ b/src/scenic/simulators/webots/road/interface.py @@ -210,13 +210,13 @@ def computeGeometry(self, crossroads, snapTolerance=0.05): def show(self, plt): if self.hasLeftSidewalk: - x, y = zip(*self.leftSidewalk.points) + x, y = zip(*[p[:2] for p in self.leftSidewalk.boundary.points]) plt.fill(x, y, "#A0A0FF") if self.hasRightSidewalk: - x, y = zip(*self.rightSidewalk.points) + x, y = zip(*[p[:2] for p in self.rightSidewalk.boundary.points]) plt.fill(x, y, "#A0A0FF") self.region.show(plt, style="r:") - x, y = zip(*self.lanes[0].points) + x, y = zip(*[p[:2] for p in self.lanes[0].boundary.points]) plt.fill(x, y, color=(0.8, 1.0, 0.8)) for lane, markers in enumerate(self.laneMarkers): x, y = zip(*markers) @@ -296,7 +296,10 @@ def __init__(self, world): allCells = [] drivableAreas = [] for road in self.roads: - assert road.region.polygons.is_valid, (road.waypoints, road.region.points) + assert road.region.polygons.is_valid, ( + road.waypoints, + road.region.boundary.points, + ) allCells.extend(road.cells) for crossroad in self.crossroads: if crossroad.region is not None: From 0770db3ae424029d56cb46b5ddc43b0295670518 Mon Sep 17 00:00:00 2001 From: Eric Vin Date: Sat, 20 Jul 2024 09:15:22 -0700 Subject: [PATCH 4/6] Added deprecation test for points. --- tests/core/test_regions.py | 11 ++++++++++- tests/utils.py | 9 +++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/core/test_regions.py b/tests/core/test_regions.py index 07c84d3cc..0a5861efa 100644 --- a/tests/core/test_regions.py +++ b/tests/core/test_regions.py @@ -9,7 +9,7 @@ from scenic.core.object_types import Object, OrientedPoint from scenic.core.regions import * from scenic.core.vectors import VectorField -from tests.utils import sampleSceneFrom +from tests.utils import maxVersion, sampleSceneFrom def sample_ignoring_rejections(region, num_samples): @@ -817,3 +817,12 @@ def test_region_combinations(A, B): # difference() difference_out = region_a.difference(region_b) assert isinstance(difference_out, Region) + + +## Deprecation Tests +def test_polygons_points(): + assert maxVersion("3.3.0") + + points = ((1, 0, 0), (1, 1, 0), (2, 1, 0), (2, 0, 0)) + poly = PolygonalRegion(points) + assert set(poly.points) == set(points) diff --git a/tests/utils.py b/tests/utils.py index 9f4816ad2..817d1e5f7 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,9 +1,11 @@ """Utilities used throughout the test suite.""" from importlib import metadata +import importlib.metadata import inspect import math import multiprocessing +import re import sys import types import weakref @@ -576,3 +578,10 @@ def ignorable(attr): fail() return False return True + + +def maxVersion(max_version): + m_ver = tuple(re.split(r"\D+", max_version)[:3]) + c_ver = tuple(re.split(r"\D+", importlib.metadata.version("scenic"))[:3]) + + return m_ver > c_ver From cd2e219e20229e54c7c9b94d205a3ecd5d3a3485 Mon Sep 17 00:00:00 2001 From: Eric Vin Date: Mon, 29 Jul 2024 12:15:16 -0700 Subject: [PATCH 5/6] Minor tweaks. --- src/scenic/core/regions.py | 4 ++-- tests/core/test_regions.py | 5 ++--- tests/utils.py | 20 ++++++++++++++++---- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/scenic/core/regions.py b/src/scenic/core/regions.py index 57b5ccad8..fd5ca7b36 100644 --- a/src/scenic/core/regions.py +++ b/src/scenic/core/regions.py @@ -2748,7 +2748,7 @@ class PolygonalRegion(Region): def __init__( self, - points=tuple(), + points=(), polygon=None, z=0, orientation=None, @@ -2760,7 +2760,7 @@ def __init__( ) # Normalize and store main parameters - self._points = tuple() if points is None else tuple(points) + self._points = () if points is None else tuple(points) self._polygon = polygon self.z = z diff --git a/tests/core/test_regions.py b/tests/core/test_regions.py index 0a5861efa..35b5077b0 100644 --- a/tests/core/test_regions.py +++ b/tests/core/test_regions.py @@ -9,7 +9,7 @@ from scenic.core.object_types import Object, OrientedPoint from scenic.core.regions import * from scenic.core.vectors import VectorField -from tests.utils import maxVersion, sampleSceneFrom +from tests.utils import deprecationTest, sampleSceneFrom def sample_ignoring_rejections(region, num_samples): @@ -820,9 +820,8 @@ def test_region_combinations(A, B): ## Deprecation Tests +@deprecationTest("3.3.0") def test_polygons_points(): - assert maxVersion("3.3.0") - points = ((1, 0, 0), (1, 1, 0), (2, 1, 0), (2, 0, 0)) poly = PolygonalRegion(points) assert set(poly.points) == set(points) diff --git a/tests/utils.py b/tests/utils.py index 817d1e5f7..cde311ab4 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,5 +1,6 @@ """Utilities used throughout the test suite.""" +import functools from importlib import metadata import importlib.metadata import inspect @@ -580,8 +581,19 @@ def ignorable(attr): return True -def maxVersion(max_version): - m_ver = tuple(re.split(r"\D+", max_version)[:3]) - c_ver = tuple(re.split(r"\D+", importlib.metadata.version("scenic"))[:3]) +def deprecationTest(max_version): + def decorator(function): + @functools.wraps(function) + def wrapper(*args, **kwargs): + m_ver = tuple(re.split(r"\D+", max_version)[:3]) + c_ver = tuple(re.split(r"\D+", importlib.metadata.version("scenic"))[:3]) + assert ( + m_ver > c_ver + ), "Maximum version exceeded. This functionality should be deprecated and this test removed." - return m_ver > c_ver + with pytest.deprecated_call(): + return function(*args, **kwargs) + + return wrapper + + return decorator From 7950040d630f49e025cef3ce147271ca602d16cb Mon Sep 17 00:00:00 2001 From: Eric Vin Date: Mon, 29 Jul 2024 13:22:16 -0700 Subject: [PATCH 6/6] Clarified deprecationTest wrapper message and param. --- tests/utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/utils.py b/tests/utils.py index cde311ab4..3ae1cf8c1 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -581,15 +581,15 @@ def ignorable(attr): return True -def deprecationTest(max_version): +def deprecationTest(removalVersion): def decorator(function): @functools.wraps(function) def wrapper(*args, **kwargs): - m_ver = tuple(re.split(r"\D+", max_version)[:3]) + m_ver = tuple(re.split(r"\D+", removalVersion)[:3]) c_ver = tuple(re.split(r"\D+", importlib.metadata.version("scenic"))[:3]) assert ( m_ver > c_ver - ), "Maximum version exceeded. This functionality should be deprecated and this test removed." + ), "Maximum version exceeded. The tested functionality and the test itself should be removed." with pytest.deprecated_call(): return function(*args, **kwargs)