Skip to content

Commit 22f8818

Browse files
committed
Add implementation of visvalingam algorithm to simplify polygon
1 parent 4fc1960 commit 22f8818

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [Unreleased]
99

1010
### Added
11+
- Add an implementation of visvalingam algorithm to simplify polygons with low modification
1112
- Add method to found close tracks in an other atlas
1213
- Allow to give a x reference when we display grid to be able to change xlim
1314
- Add option to EddyId to select data index like `--indexs time=5 depth=2`

src/py_eddy_tracker/poly.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
Method for polygon
44
"""
55

6+
import heapq
7+
68
from numba import njit, prange
79
from numba import types as numba_types
810
from numpy import array, concatenate, empty, nan, ones, pi, where
@@ -647,3 +649,83 @@ def get_pixel_in_regular(vertices, x_c, y_c, x_start, x_stop, y_start, y_stop):
647649
y_start,
648650
vertices,
649651
)
652+
653+
654+
@njit(cache=True)
655+
def tri_area2(x, y, i0, i1, i2):
656+
"""Double area of triangle
657+
658+
:param array x:
659+
:param array y:
660+
:param int i0: indice of first point
661+
:param int i1: indice of second point
662+
:param int i2: indice of third point
663+
:return: area
664+
:rtype: float
665+
"""
666+
x0, y0 = x[i0], y[i0]
667+
x1, y1 = x[i1], y[i1]
668+
x2, y2 = x[i2], y[i2]
669+
p_area2 = (x0 - x2) * (y1 - y0) - (x0 - x1) * (y2 - y0)
670+
return abs(p_area2)
671+
672+
673+
@njit(cache=True)
674+
def visvalingam(x, y, nb_pt=18):
675+
"""Polygon simplification with visvalingam algorithm
676+
677+
:param array x:
678+
:param array y:
679+
:param int nb_pt: array size of out
680+
:return: New (x, y) array
681+
:rtype: array,array
682+
"""
683+
nb = x.shape[0]
684+
i0, i1 = nb - 3, nb - 2
685+
h = [(tri_area2(x, y, i0, i1, 0), (i0, i1, 0))]
686+
i0 = i1
687+
i1 = 0
688+
i_previous = empty(nb - 1, dtype=numba_types.int32)
689+
i_next = empty(nb - 1, dtype=numba_types.int32)
690+
i_previous[0] = -1
691+
i_next[0] = -1
692+
for i in range(1, nb - 1):
693+
i_previous[i] = -1
694+
i_next[i] = -1
695+
heapq.heappush(h, (tri_area2(x, y, i0, i1, i), (i0, i1, i)))
696+
i0 = i1
697+
i1 = i
698+
# we continue until we are equal to nb_pt
699+
while len(h) >= nb_pt:
700+
# We pop lower area
701+
_, (i0, i1, i2) = heapq.heappop(h)
702+
# We check if triangle is valid(i0 or i2 not removed)
703+
i_p, i_n = i_previous[i0], i_next[i2]
704+
if i_p == -1 and i_n == -1:
705+
# We store reference of delete point
706+
i_previous[i1] = i0
707+
i_next[i1] = i2
708+
continue
709+
elif i_p == -1:
710+
i2 = i_n
711+
elif i_n == -1:
712+
i0 = i_p
713+
else:
714+
# in this case we replace two point
715+
i0, i2 = i_p, i_n
716+
heapq.heappush(h, (tri_area2(x, y, i0, i1, i2), (i0, i1, i2)))
717+
nb_out = 0
718+
for i in i_next:
719+
if i == -1:
720+
nb_out += 1
721+
nb_out += 1
722+
x_new, y_new = empty(nb_out, dtype=x.dtype), empty(nb_out, dtype=y.dtype)
723+
j = 0
724+
for i, i_n in enumerate(i_next):
725+
if i_n == -1:
726+
x_new[j] = x[i]
727+
y_new[j] = y[i]
728+
j += 1
729+
x_new[j] = x_new[0]
730+
y_new[j] = y_new[0]
731+
return x_new, y_new

0 commit comments

Comments
 (0)