Add comprehensive tests for edge depth extension, empty image edits, and material view adaptation
- Introduced `test_edge_depth.py` to validate the functionality of edge depth extension, ensuring core alpha preservation, proper depth handling, and edge padding behavior. - Created `test_empty_image_edits.py` to verify the behavior of image edits in Blender, focusing on shared edits, preservation of image properties, and handling of failed operations. - Developed `test_material_view_adaptation.py` to test material adaptation preferences, ensuring color space and alpha settings are correctly applied and preserved across various scenarios.
This commit is contained in:
94
src/anyimage/operators/cutout_tool/polygon.py
Normal file
94
src/anyimage/operators/cutout_tool/polygon.py
Normal file
@@ -0,0 +1,94 @@
|
||||
"""Polygonal chain simplification using NumPy."""
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
# approximate_polygon: scikit-image 0.25.2, copyright 2009-2022 the scikit-image team.
|
||||
# BSD-3-Clause; see ../../licenses/scikit-image.txt.
|
||||
def approximate_polygon(coords, tolerance):
|
||||
"""Approximate a polygonal chain with the specified tolerance.
|
||||
|
||||
It is based on the Douglas-Peucker algorithm.
|
||||
|
||||
Note that the approximated polygon is always within the convex hull of the
|
||||
original polygon.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coords : (K, 2) array
|
||||
Coordinate array.
|
||||
tolerance : float
|
||||
Maximum distance from original points of polygon to approximated
|
||||
polygonal chain. If tolerance is 0, the original coordinate array
|
||||
is returned.
|
||||
|
||||
Returns
|
||||
-------
|
||||
coords : (L, 2) array
|
||||
Approximated polygonal chain where L <= K.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
|
||||
"""
|
||||
if tolerance <= 0:
|
||||
return coords
|
||||
|
||||
chain = np.zeros(coords.shape[0], "bool")
|
||||
# pre-allocate distance array for all points
|
||||
dists = np.zeros(coords.shape[0])
|
||||
chain[0] = True
|
||||
chain[-1] = True
|
||||
pos_stack = [(0, chain.shape[0] - 1)]
|
||||
end_of_chain = False
|
||||
|
||||
while not end_of_chain:
|
||||
start, end = pos_stack.pop()
|
||||
# determine properties of current line segment
|
||||
r0, c0 = coords[start, :]
|
||||
r1, c1 = coords[end, :]
|
||||
dr = r1 - r0
|
||||
dc = c1 - c0
|
||||
segment_angle = -np.arctan2(dr, dc)
|
||||
segment_dist = c0 * np.sin(segment_angle) + r0 * np.cos(segment_angle)
|
||||
|
||||
# select points in-between line segment
|
||||
segment_coords = coords[start + 1 : end, :]
|
||||
segment_dists = dists[start + 1 : end]
|
||||
|
||||
# check whether to take perpendicular or euclidean distance with
|
||||
# inner product of vectors
|
||||
|
||||
# vectors from points -> start and end
|
||||
dr0 = segment_coords[:, 0] - r0
|
||||
dc0 = segment_coords[:, 1] - c0
|
||||
dr1 = segment_coords[:, 0] - r1
|
||||
dc1 = segment_coords[:, 1] - c1
|
||||
# vectors points -> start and end projected on start -> end vector
|
||||
projected_lengths0 = dr0 * dr + dc0 * dc
|
||||
projected_lengths1 = -dr1 * dr - dc1 * dc
|
||||
perp = np.logical_and(projected_lengths0 > 0, projected_lengths1 > 0)
|
||||
eucl = np.logical_not(perp)
|
||||
segment_dists[perp] = np.abs(
|
||||
segment_coords[perp, 0] * np.cos(segment_angle)
|
||||
+ segment_coords[perp, 1] * np.sin(segment_angle)
|
||||
- segment_dist
|
||||
)
|
||||
segment_dists[eucl] = np.minimum(
|
||||
# distance to start point
|
||||
np.sqrt(dc0[eucl] ** 2 + dr0[eucl] ** 2),
|
||||
# distance to end point
|
||||
np.sqrt(dc1[eucl] ** 2 + dr1[eucl] ** 2),
|
||||
)
|
||||
|
||||
if np.any(segment_dists > tolerance):
|
||||
# select point with maximum distance to line
|
||||
new_end = start + np.argmax(segment_dists) + 1
|
||||
pos_stack.append((new_end, end))
|
||||
pos_stack.append((start, new_end))
|
||||
chain[new_end] = True
|
||||
|
||||
if len(pos_stack) == 0:
|
||||
end_of_chain = True
|
||||
|
||||
return coords[chain, :]
|
||||
Reference in New Issue
Block a user