1
1
import copy
2
2
import re
3
+ from collections import namedtuple
3
4
4
5
import numpy as np
5
-
6
6
from numpy .testing import assert_array_equal
7
7
import pytest
8
8
@@ -71,25 +71,27 @@ def test_contains_points_negative_radius():
71
71
np .testing .assert_equal (result , [True , False , False ])
72
72
73
73
74
- _test_paths = [
74
+ _ExampleCurve = namedtuple ('ExampleCurve' , ['path' , 'extents' , 'area' ])
75
+ _test_curves = [
75
76
# interior extrema determine extents and degenerate derivative
76
- Path ([[0 , 0 ], [1 , 0 ], [1 , 1 ], [0 , 1 ]],
77
- [Path .MOVETO , Path .CURVE4 , Path .CURVE4 , Path .CURVE4 ]),
78
- # a quadratic curve
79
- Path ([[0 , 0 ], [0 , 1 ], [1 , 0 ]], [Path .MOVETO , Path .CURVE3 , Path .CURVE3 ]),
77
+ _ExampleCurve (Path ([[0 , 0 ], [1 , 0 ], [1 , 1 ], [0 , 1 ]],
78
+ [Path .MOVETO , Path .CURVE4 , Path .CURVE4 , Path .CURVE4 ]),
79
+ extents = (0. , 0. , 0.75 , 1. ), area = 0.6 ),
80
+ # a quadratic curve, clockwise
81
+ _ExampleCurve (Path ([[0 , 0 ], [0 , 1 ], [1 , 0 ]],
82
+ [Path .MOVETO , Path .CURVE3 , Path .CURVE3 ]),
83
+ extents = (0. , 0. , 1. , 0.5 ), area = - 1 / 3 ),
80
84
# a linear curve, degenerate vertically
81
- Path ([[0 , 1 ], [1 , 1 ]], [Path .MOVETO , Path .LINETO ]),
85
+ _ExampleCurve (Path ([[0 , 1 ], [1 , 1 ]], [Path .MOVETO , Path .LINETO ]),
86
+ extents = (0. , 1. , 1. , 1. ), area = 0. ),
82
87
# a point
83
- Path ([[1 , 2 ]], [Path .MOVETO ]),
88
+ _ExampleCurve (Path ([[1 , 2 ]], [Path .MOVETO ]), extents = (1. , 2. , 1. , 2. ),
89
+ area = 0. ),
84
90
]
85
91
86
92
87
- _test_path_extents = [(0. , 0. , 0.75 , 1. ), (0. , 0. , 1. , 0.5 ), (0. , 1. , 1. , 1. ),
88
- (1. , 2. , 1. , 2. )]
89
-
90
-
91
- @pytest .mark .parametrize ('path, extents' , zip (_test_paths , _test_path_extents ))
92
- def test_exact_extents (path , extents ):
93
+ @pytest .mark .parametrize ('precomputed_curve' , _test_curves )
94
+ def test_exact_extents (precomputed_curve ):
93
95
# notice that if we just looked at the control points to get the bounding
94
96
# box of each curve, we would get the wrong answers. For example, for
95
97
# hard_curve = Path([[0, 0], [1, 0], [1, 1], [0, 1]],
@@ -99,9 +101,32 @@ def test_exact_extents(path, extents):
99
101
# the way out to the control points.
100
102
# Note that counterintuitively, path.get_extents() returns a Bbox, so we
101
103
# have to get that Bbox's `.extents`.
104
+ path , extents = precomputed_curve .path , precomputed_curve .extents
102
105
assert np .all (path .get_extents ().extents == extents )
103
106
104
107
108
+ @pytest .mark .parametrize ('precomputed_curve' , _test_curves )
109
+ def test_signed_area (precomputed_curve ):
110
+ path , area = precomputed_curve .path , precomputed_curve .area
111
+ assert np .isclose (path .signed_area (), area )
112
+ # now flip direction, sign of *signed_area* should flip
113
+ rcurve = Path (path .vertices [::- 1 ], path .codes )
114
+ assert np .isclose (rcurve .signed_area (), - area )
115
+
116
+
117
+ def test_signed_area_unit_rectangle ():
118
+ rect = Path .unit_rectangle ()
119
+ assert np .isclose (rect .signed_area (), 1 )
120
+
121
+
122
+ def test_signed_area_unit_circle ():
123
+ circ = Path .unit_circle ()
124
+ # Not a "real" circle, just an approximation of a circle made out of bezier
125
+ # curves. The actual value is 3.1415935732517166, which is close enough to
126
+ # pass here.
127
+ assert np .isclose (circ .signed_area (), np .pi )
128
+
129
+
105
130
def test_point_in_path_nan ():
106
131
box = np .array ([[0 , 0 ], [1 , 0 ], [1 , 1 ], [0 , 1 ], [0 , 0 ]])
107
132
p = Path (box )
0 commit comments