|
3 | 3 | Method for polygon
|
4 | 4 | """
|
5 | 5 |
|
| 6 | +import heapq |
| 7 | + |
6 | 8 | from numba import njit, prange
|
7 | 9 | from numba import types as numba_types
|
8 | 10 | 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):
|
647 | 649 | y_start,
|
648 | 650 | vertices,
|
649 | 651 | )
|
| 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