Skip to content

Commit e6b4506

Browse files
committed
Changed Query info shape properties to never have a None. #279
1 parent 5e99b08 commit e6b4506

File tree

6 files changed

+22
-25
lines changed

6 files changed

+22
-25
lines changed

CHANGELOG.rst

+2
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ Changelog
1212
Changed body.constraints to return a KeysView of the Constraints attached to the body. Note that its still weak references to the Constraints.
1313
Reversed the dependency between bodies and shapes. Now the Body owns the connection, and the Shape only keeps a weak ref to the Body. That means that if you remove a Body, then any shapes not referenced anywhere else will also be removed.
1414
Changed body.shapes to return a KeysView instead of a set of the shapes.
15+
Changed Space.segment_query to return None in case the query did not hit the shape.
1516
1617
Added default do_nothing and always_collide callback functions to the CollisionHandler, so that its clear how to reset and align with other callbacks.
1718
If in old code you did handler.begin = None, you should now instead to handler.begin = CollisionHandler.always_collide etc.
1819
20+
Changed type of PointQueryInfo.shape, SegmentQueryInfo.shape and ShapeQueryInfo.shape to not be Optional, they will always have a shape.
1921
New feature: ShapeFilter.rejects_collision()
2022
New feature: Added Vec2d.polar_tuple
2123
Optimized Vec2d.angle and Vec2d.angle_degrees (note that the optimized versions treat 0 length vectors with x and/or y equal to -0 slightly differently.)

pymunk/_callbacks.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ def ext_cpSpacePointQueryFunc(
2222
gradient: ffi.CData,
2323
data: ffi.CData,
2424
) -> None:
25-
self, query_hits = ffi.from_handle(data)
25+
_, query_hits = ffi.from_handle(data)
2626
shape = Shape._from_cp_shape(_shape)
27+
assert shape != None
2728
p = PointQueryInfo(
2829
shape, Vec2d(point.x, point.y), distance, Vec2d(gradient.x, gradient.y)
2930
)
@@ -38,8 +39,9 @@ def ext_cpSpaceSegmentQueryFunc(
3839
alpha: float,
3940
data: ffi.CData,
4041
) -> None:
41-
self, query_hits = ffi.from_handle(data)
42+
_, query_hits = ffi.from_handle(data)
4243
shape = Shape._from_cp_shape(_shape)
44+
assert shape != None
4345
p = SegmentQueryInfo(
4446
shape, Vec2d(point.x, point.y), Vec2d(normal.x, normal.y), alpha
4547
)
@@ -58,8 +60,9 @@ def ext_cpSpaceBBQueryFunc(_shape: ffi.CData, data: ffi.CData) -> None:
5860
def ext_cpSpaceShapeQueryFunc(
5961
_shape: ffi.CData, _points: ffi.CData, data: ffi.CData
6062
) -> None:
61-
self, query_hits = ffi.from_handle(data)
63+
_, query_hits = ffi.from_handle(data)
6264
found_shape = Shape._from_cp_shape(_shape)
65+
assert found_shape != None
6366
point_set = ContactPointSet._from_cp(_points)
6467
info = ShapeQueryInfo(found_shape, point_set)
6568
query_hits.append(info)

pymunk/query_info.py

+5-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
__docformat__ = "reStructuredText"
22

3-
from typing import TYPE_CHECKING, NamedTuple, Optional
3+
from typing import TYPE_CHECKING, NamedTuple
44

55
if TYPE_CHECKING:
66
from .contact_point_set import ContactPointSet
@@ -13,8 +13,8 @@ class PointQueryInfo(NamedTuple):
1313
Space.
1414
"""
1515

16-
shape: Optional["Shape"]
17-
"""The nearest shape, None if no shape was within range."""
16+
shape: "Shape"
17+
"""The nearest shape"""
1818

1919
point: "Vec2d"
2020
"""The closest point on the shape's surface. (in world space
@@ -40,18 +40,14 @@ class SegmentQueryInfo(NamedTuple):
4040
they also return where a shape was hit and it's surface normal at the hit
4141
point. This object hold that information.
4242
43-
To test if the query hit something, check if
44-
SegmentQueryInfo.shape == None or not.
45-
4643
Segment queries are like ray casting, but because not all spatial indexes
4744
allow processing infinitely long ray queries it is limited to segments.
4845
In practice this is still very fast and you don't need to worry too much
4946
about the performance as long as you aren't using extremely long segments
5047
for your queries.
51-
5248
"""
5349

54-
shape: Optional["Shape"]
50+
shape: "Shape"
5551
"""Shape that was hit, or None if no collision occured"""
5652

5753
point: "Vec2d"
@@ -69,7 +65,7 @@ class ShapeQueryInfo(NamedTuple):
6965
they also return where a shape was hit. This object hold that information.
7066
"""
7167

72-
shape: Optional["Shape"]
68+
shape: "Shape"
7369
"""Shape that was hit, or None if no collision occured"""
7470

7571
contact_point_set: "ContactPointSet"

pymunk/shapes.py

+4-7
Original file line numberDiff line numberDiff line change
@@ -299,9 +299,11 @@ def point_query(self, p: Tuple[float, float]) -> PointQueryInfo:
299299

300300
def segment_query(
301301
self, start: Tuple[float, float], end: Tuple[float, float], radius: float = 0
302-
) -> SegmentQueryInfo:
302+
) -> Optional[SegmentQueryInfo]:
303303
"""Check if the line segment from start to end intersects the shape.
304304
305+
Returns None if it does not intersect
306+
305307
:rtype: :py:class:`SegmentQueryInfo`
306308
"""
307309
assert len(start) == 2
@@ -318,12 +320,7 @@ def segment_query(
318320
info.alpha,
319321
)
320322
else:
321-
return SegmentQueryInfo(
322-
None,
323-
Vec2d(info.point.x, info.point.y),
324-
Vec2d(info.normal.x, info.normal.y),
325-
info.alpha,
326-
)
323+
return None
327324

328325
def shapes_collide(self, b: "Shape") -> ContactPointSet:
329326
"""Get contact information about this shape and shape b.

pymunk/space.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,7 @@ def point_query_nearest(
772772
self._space, point, max_distance, shape_filter, info
773773
)
774774

775-
shape = shape = Shape._from_cp_shape(_shape)
775+
shape = Shape._from_cp_shape(_shape)
776776

777777
if shape != None:
778778
return PointQueryInfo(
@@ -857,7 +857,7 @@ def segment_query_first(
857857
self._space, start, end, radius, shape_filter, info
858858
)
859859

860-
shape = shape = Shape._from_cp_shape(_shape)
860+
shape = Shape._from_cp_shape(_shape)
861861
if shape != None:
862862
return SegmentQueryInfo(
863863
shape,

pymunk/tests/test_shape.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,14 @@ def testSegmentQuery(self) -> None:
3232
c.cache_bb()
3333

3434
info = c.segment_query((10, -50), (10, 50))
35-
self.assertEqual(info.shape, None)
36-
self.assertEqual(info.point, (10, 50))
37-
self.assertEqual(info.normal, (0, 0))
38-
self.assertEqual(info.alpha, 1.0)
35+
self.assertEqual(info, None)
3936

4037
info = c.segment_query((10, -50), (10, 50), 6)
38+
assert info != None
4139
self.assertEqual(info.shape, c)
4240

4341
info = c.segment_query((0, -50), (0, 50))
42+
assert info != None
4443
self.assertEqual(info.shape, c)
4544
self.assertAlmostEqual(info.point.x, 0)
4645
self.assertAlmostEqual(info.point.y, -5)

0 commit comments

Comments
 (0)