[utils] remove_duplicate_vertices now takes a tolerance (default exact)
This commit is contained in:
parent
4d57936da8
commit
f4df8e0553
2 changed files with 40 additions and 3 deletions
|
|
@ -5,7 +5,15 @@ from numpy.testing import assert_equal, assert_allclose
|
||||||
from numpy import pi
|
from numpy import pi
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ..utils import remove_duplicate_vertices, remove_colinear_vertices, poly_contains_points, rotation_matrix_2d, apply_transforms, normalize_mirror, DeferredDict
|
from ..utils import (
|
||||||
|
DeferredDict,
|
||||||
|
apply_transforms,
|
||||||
|
normalize_mirror,
|
||||||
|
poly_contains_points,
|
||||||
|
remove_colinear_vertices,
|
||||||
|
remove_duplicate_vertices,
|
||||||
|
rotation_matrix_2d,
|
||||||
|
)
|
||||||
from ..file.utils import tmpfile
|
from ..file.utils import tmpfile
|
||||||
from ..utils.curves import bezier
|
from ..utils.curves import bezier
|
||||||
from ..error import PatternError
|
from ..error import PatternError
|
||||||
|
|
@ -23,6 +31,23 @@ def test_remove_duplicate_vertices() -> None:
|
||||||
assert_equal(v_clean_open, [[0, 0], [1, 1], [2, 2], [0, 0]])
|
assert_equal(v_clean_open, [[0, 0], [1, 1], [2, 2], [0, 0]])
|
||||||
|
|
||||||
|
|
||||||
|
def test_remove_duplicate_vertices_tolerance_defaults_to_exact_match() -> None:
|
||||||
|
v = [[0, 0], [1, 1], [1 + 1e-13, 1], [2, 2], [1e-13, 0]]
|
||||||
|
|
||||||
|
assert_allclose(remove_duplicate_vertices(v, closed_path=True), v, atol=0, rtol=0)
|
||||||
|
assert_allclose(
|
||||||
|
remove_duplicate_vertices(v, closed_path=True, tolerance=1e-12),
|
||||||
|
[[0, 0], [1 + 1e-13, 1], [2, 2]],
|
||||||
|
atol=0,
|
||||||
|
rtol=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_remove_duplicate_vertices_rejects_negative_tolerance() -> None:
|
||||||
|
with pytest.raises(ValueError, match='non-negative'):
|
||||||
|
remove_duplicate_vertices([[0, 0]], tolerance=-1)
|
||||||
|
|
||||||
|
|
||||||
def test_remove_colinear_vertices() -> None:
|
def test_remove_colinear_vertices() -> None:
|
||||||
v = [[0, 0], [1, 0], [2, 0], [2, 1], [2, 2], [1, 1], [0, 0]]
|
v = [[0, 0], [1, 0], [2, 0], [2, 1], [2, 2], [1, 1], [0, 0]]
|
||||||
v_clean = remove_colinear_vertices(v, closed_path=True)
|
v_clean = remove_colinear_vertices(v, closed_path=True)
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,11 @@ import numpy
|
||||||
from numpy.typing import NDArray, ArrayLike
|
from numpy.typing import NDArray, ArrayLike
|
||||||
|
|
||||||
|
|
||||||
def remove_duplicate_vertices(vertices: ArrayLike, closed_path: bool = True) -> NDArray[numpy.float64]:
|
def remove_duplicate_vertices(
|
||||||
|
vertices: ArrayLike,
|
||||||
|
closed_path: bool = True,
|
||||||
|
tolerance: float = 0.0,
|
||||||
|
) -> NDArray[numpy.float64]:
|
||||||
"""
|
"""
|
||||||
Given a list of vertices, remove any consecutive duplicates.
|
Given a list of vertices, remove any consecutive duplicates.
|
||||||
|
|
||||||
|
|
@ -13,14 +17,22 @@ def remove_duplicate_vertices(vertices: ArrayLike, closed_path: bool = True) ->
|
||||||
vertices: `[[x0, y0], [x1, y1], ...]`
|
vertices: `[[x0, y0], [x1, y1], ...]`
|
||||||
closed_path: If True, `vertices` is interpreted as an implicity-closed path
|
closed_path: If True, `vertices` is interpreted as an implicity-closed path
|
||||||
(i.e. the last vertex will be removed if it is the same as the first)
|
(i.e. the last vertex will be removed if it is the same as the first)
|
||||||
|
tolerance: Maximum coordinate-wise absolute difference for two vertices to
|
||||||
|
be considered duplicates. Default `0` requires exact equality.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
`vertices` with no consecutive duplicates. This may be a view into the original array.
|
`vertices` with no consecutive duplicates. This may be a view into the original array.
|
||||||
"""
|
"""
|
||||||
|
if tolerance < 0:
|
||||||
|
raise ValueError(f'tolerance must be non-negative, got {tolerance}')
|
||||||
|
|
||||||
vertices = numpy.asarray(vertices)
|
vertices = numpy.asarray(vertices)
|
||||||
if vertices.shape[0] <= 1:
|
if vertices.shape[0] <= 1:
|
||||||
return vertices
|
return vertices
|
||||||
|
if tolerance == 0:
|
||||||
duplicates = (vertices == numpy.roll(vertices, -1, axis=0)).all(axis=1)
|
duplicates = (vertices == numpy.roll(vertices, -1, axis=0)).all(axis=1)
|
||||||
|
else:
|
||||||
|
duplicates = (numpy.abs(vertices - numpy.roll(vertices, -1, axis=0)) <= tolerance).all(axis=1)
|
||||||
if not closed_path:
|
if not closed_path:
|
||||||
duplicates[-1] = False
|
duplicates[-1] = False
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue