Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
Handle MOVETO's, CLOSEPOLY's and empty paths in Path.interpolated#29919
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -667,14 +667,35 @@ def intersects_bbox(self, bbox, filled=True): | ||
def interpolated(self, steps): | ||
""" | ||
Return a new pathwith each segment divided into *steps* parts. | ||
Codes other than `LINETO`, `MOVETO`, and `CLOSEPOLY` are not handled correctly. | ||
Parameters | ||
---------- | ||
steps : int | ||
The number of segments in the new path for each in the original. | ||
Returns | ||
------- | ||
Path | ||
The interpolated path. | ||
""" | ||
if steps == 1 or len(self) == 0: | ||
return self | ||
if self.codes is not None and self.MOVETO in self.codes[1:]: | ||
return self.make_compound_path( | ||
*(p.interpolated(steps) for p in self._iter_connected_components())) | ||
if self.codes is not None and self.CLOSEPOLY in self.codes and not np.all( | ||
self.vertices[self.codes == self.CLOSEPOLY] == self.vertices[0]): | ||
vertices = self.vertices.copy() | ||
vertices[self.codes == self.CLOSEPOLY] = vertices[0] | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. I think this patch is not sufficient if you have a path with mixtures of CLOSEPOLY AND MOVETO. The MOVETO creates a new separate separate component with a starting point that is generally different from Maybe a variation of MemberAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. But if we got to here, we have no internal There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Yes, you are right. | ||
else: | ||
vertices = self.vertices | ||
vertices = simple_linear_interpolation(vertices, steps) | ||
codes = self.codes | ||
if codes is not None: | ||
new_codes = np.full((len(codes) - 1) * steps + 1, Path.LINETO, | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -541,3 +541,84 @@ def test_cleanup_closepoly(): | ||
cleaned = p.cleaned(remove_nans=True) | ||
assert len(cleaned) == 1 | ||
assert cleaned.codes[0] == Path.STOP | ||
def test_interpolated_moveto(): | ||
# Initial path has two subpaths with two LINETOs each | ||
vertices = np.array([[0, 0], | ||
[0, 1], | ||
[1, 2], | ||
[4, 4], | ||
[4, 5], | ||
[5, 5]]) | ||
codes = [Path.MOVETO, Path.LINETO, Path.LINETO] * 2 | ||
path = Path(vertices, codes) | ||
result = path.interpolated(3) | ||
# Result should have two subpaths with six LINETOs each | ||
expected_subpath_codes = [Path.MOVETO] + [Path.LINETO] * 6 | ||
np.testing.assert_array_equal(result.codes, expected_subpath_codes * 2) | ||
def test_interpolated_closepoly(): | ||
codes = [Path.MOVETO] + [Path.LINETO]*2 + [Path.CLOSEPOLY] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Test a compound path with multiple closepolys by doubling this again similar to your above test to make sure the implementation handles multiple MOVETOs and CLOSEPOLYS together? | ||
vertices = [(4, 3), (5, 4), (5, 3), (0, 0)] | ||
path = Path(vertices, codes) | ||
result = path.interpolated(2) | ||
expected_vertices = np.array([[4, 3], | ||
[4.5, 3.5], | ||
[5, 4], | ||
[5, 3.5], | ||
[5, 3], | ||
[4.5, 3], | ||
[4, 3]]) | ||
expected_codes = [Path.MOVETO] + [Path.LINETO]*5 + [Path.CLOSEPOLY] | ||
np.testing.assert_allclose(result.vertices, expected_vertices) | ||
np.testing.assert_array_equal(result.codes, expected_codes) | ||
# Usually closepoly is the last vertex but does not have to be. | ||
codes += [Path.LINETO] | ||
vertices += [(2, 1)] | ||
path = Path(vertices, codes) | ||
result = path.interpolated(2) | ||
extra_expected_vertices = np.array([[3, 2], | ||
[2, 1]]) | ||
expected_vertices = np.concatenate([expected_vertices, extra_expected_vertices]) | ||
expected_codes += [Path.LINETO] * 2 | ||
np.testing.assert_allclose(result.vertices, expected_vertices) | ||
np.testing.assert_array_equal(result.codes, expected_codes) | ||
def test_interpolated_moveto_closepoly(): | ||
# Initial path has two closed subpaths | ||
codes = ([Path.MOVETO] + [Path.LINETO]*2 + [Path.CLOSEPOLY]) * 2 | ||
vertices = [(4, 3), (5, 4), (5, 3), (0, 0), (8, 6), (10, 8), (10, 6), (0, 0)] | ||
path = Path(vertices, codes) | ||
result = path.interpolated(2) | ||
expected_vertices1 = np.array([[4, 3], | ||
[4.5, 3.5], | ||
[5, 4], | ||
[5, 3.5], | ||
[5, 3], | ||
[4.5, 3], | ||
[4, 3]]) | ||
expected_vertices = np.concatenate([expected_vertices1, expected_vertices1 * 2]) | ||
expected_codes = ([Path.MOVETO] + [Path.LINETO]*5 + [Path.CLOSEPOLY]) * 2 | ||
np.testing.assert_allclose(result.vertices, expected_vertices) | ||
np.testing.assert_array_equal(result.codes, expected_codes) | ||
def test_interpolated_empty_path(): | ||
path = Path(np.zeros((0, 2))) | ||
assert path.interpolated(42) is path |
Uh oh!
There was an error while loading.Please reload this page.