@@ -716,50 +716,85 @@ def tri_area2(x, y, i0, i1, i2):
716
716
def visvalingam (x , y , fixed_size = 18 ):
717
717
"""Polygon simplification with visvalingam algorithm
718
718
719
+ X, Y are considered like a polygon, the next point after the last one is the first one
719
720
:param array x:
720
721
:param array y:
721
722
:param int fixed_size: array size of out
722
- :return: New (x, y) array
723
+ :return:
724
+ New (x, y) array, last position will be equal to first one, if array size is 6,
725
+ there is only 5 point.
723
726
:rtype: array,array
727
+
728
+ .. plot::
729
+
730
+ import matplotlib.pyplot as plt
731
+ import numpy as np
732
+ from py_eddy_tracker.poly import visvalingam
733
+
734
+ x = np.array([1, 2, 3, 4, 5, 6.75, 6, 1])
735
+ y = np.array([-0.5, -1.5, -1, -1.75, -1, -1, -0.5, -0.5])
736
+ ax = plt.subplot(111)
737
+ ax.set_aspect("equal")
738
+ ax.grid(True), ax.set_ylim(-2, -.2)
739
+ ax.plot(x, y, "r", lw=5)
740
+ ax.plot(*visvalingam(x,y,6), "b", lw=2)
741
+ plt.show()
724
742
"""
743
+ # TODO : in case of original size lesser than fixed size, jump at the end
725
744
nb = x .shape [0 ]
726
- i0 , i1 = nb - 3 , nb - 2
745
+ nb_ori = nb
746
+ # Get indice of first triangle
747
+ i0 , i1 = nb - 2 , nb - 1
748
+ # Init heap with first area and tiangle
727
749
h = [(tri_area2 (x , y , i0 , i1 , 0 ), (i0 , i1 , 0 ))]
750
+ # Roll index for next one
728
751
i0 = i1
729
752
i1 = 0
730
- i_previous = empty (nb - 1 , dtype = numba_types .int32 )
731
- i_next = empty (nb - 1 , dtype = numba_types .int32 )
753
+ # Index of previous valid point
754
+ i_previous = empty (nb , dtype = numba_types .int64 )
755
+ # Index of next valid point
756
+ i_next = empty (nb , dtype = numba_types .int64 )
757
+ # Mask of removed
758
+ removed = zeros (nb , dtype = numba_types .bool_ )
732
759
i_previous [0 ] = - 1
733
760
i_next [0 ] = - 1
734
- for i in range (1 , nb - 1 ):
761
+ for i in range (1 , nb ):
735
762
i_previous [i ] = - 1
736
763
i_next [i ] = - 1
764
+ # We add triangle area for all triangle
737
765
heapq .heappush (h , (tri_area2 (x , y , i0 , i1 , i ), (i0 , i1 , i )))
738
766
i0 = i1
739
767
i1 = i
740
768
# we continue until we are equal to nb_pt
741
- while len ( h ) >= fixed_size :
769
+ while nb >= fixed_size :
742
770
# We pop lower area
743
771
_ , (i0 , i1 , i2 ) = heapq .heappop (h )
744
772
# We check if triangle is valid(i0 or i2 not removed)
745
- i_p , i_n = i_previous [i0 ], i_next [i2 ]
746
- if i_p == - 1 and i_n == - 1 :
747
- # We store reference of delete point
748
- i_previous [i1 ] = i0
749
- i_next [i1 ] = i2
773
+ if removed [i0 ] or removed [i2 ]:
774
+ # In this cas nothing to do
750
775
continue
751
- elif i_p == - 1 :
752
- i2 = i_n
753
- elif i_n == - 1 :
754
- i0 = i_p
755
- else :
756
- # in this case we replace two point
757
- i0 , i2 = i_p , i_n
758
- heapq .heappush (h , (tri_area2 (x , y , i0 , i1 , i2 ), (i0 , i1 , i2 )))
776
+ # Flag obs like removed
777
+ removed [i1 ] = True
778
+ # We count point still valid
779
+ nb -= 1
780
+ # Modify index for the next and previous, we jump over i1
781
+ i_previous [i2 ] = i0
782
+ i_next [i0 ] = i2
783
+ # We insert 2 triangles which are modified by the deleted point
784
+ # Previous triangle
785
+ i_1 = i_previous [i0 ]
786
+ if i_1 == - 1 :
787
+ i_1 = (i0 - 1 ) % nb_ori
788
+ heapq .heappush (h , (tri_area2 (x , y , i_1 , i0 , i2 ), (i_1 , i0 , i2 )))
789
+ # Previous triangle
790
+ i3 = i_next [i2 ]
791
+ if i3 == - 1 :
792
+ i3 = (i2 + 1 ) % nb_ori
793
+ heapq .heappush (h , (tri_area2 (x , y , i0 , i2 , i3 ), (i0 , i2 , i3 )))
759
794
x_new , y_new = empty (fixed_size , dtype = x .dtype ), empty (fixed_size , dtype = y .dtype )
760
795
j = 0
761
- for i , i_n in enumerate (i_next ):
762
- if i_n == - 1 :
796
+ for i , flag in enumerate (removed ):
797
+ if not flag :
763
798
x_new [j ] = x [i ]
764
799
y_new [j ] = y [i ]
765
800
j += 1
@@ -872,34 +907,6 @@ def poly_indexs(x_p, y_p, x_c, y_c):
872
907
return indexs
873
908
874
909
875
- @njit (cache = True )
876
- def poly_indexs_old (x_p , y_p , x_c , y_c ):
877
- """
878
- index of contour for each postion inside a contour, -1 in case of no contour
879
-
880
- :param array x_p: longitude to test
881
- :param array y_p: latitude to test
882
- :param array x_c: longitude of contours
883
- :param array y_c: latitude of contours
884
- """
885
- nb_p = x_p .shape [0 ]
886
- nb_c = x_c .shape [0 ]
887
- indexs = - ones (nb_p , dtype = numba_types .int32 )
888
- for i in range (nb_c ):
889
- x_ , y_ = reduce_size (x_c [i ], y_c [i ])
890
- x_c_min , y_c_min = x_ .min (), y_ .min ()
891
- x_c_max , y_c_max = x_ .max (), y_ .max ()
892
- v = create_vertice (x_ , y_ )
893
- for j in range (nb_p ):
894
- if indexs [j ] != - 1 :
895
- continue
896
- x , y = x_p [j ], y_p [j ]
897
- if x > x_c_min and x < x_c_max and y > y_c_min and y < y_c_max :
898
- if winding_number_poly (x , y , v ) != 0 :
899
- indexs [j ] = i
900
- return indexs
901
-
902
-
903
910
@njit (cache = True )
904
911
def insidepoly (x_p , y_p , x_c , y_c ):
905
912
"""
0 commit comments