Function to output the extrema of a 2D array, as peaks, valleys or saddles.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
real(kind=R8), | intent(in), | dimension(1:nx, 1:ny) | :: | tab |
input 2D array |
|
integer(kind=I4), | intent(in) | :: | nx |
number of pixels along x |
||
integer(kind=I4), | intent(in) | :: | ny |
number of pixels along y |
||
integer(kind=I4), | intent(out), | dimension(:,:), allocatable | :: | valleys |
list of valley coordinates |
|
integer(kind=I4), | intent(out), | dimension(:,:), allocatable | :: | peaks |
list of peaks coordinates |
|
integer(kind=I4), | intent(out), | dimension(:,:), allocatable | :: | saddles |
list of saddles coordinates |
|
integer(kind=I4), | intent(out), | dimension(1:3) | :: | nb_summits |
number of extrema of each kind |
subroutine label_surf_summits(tab, nx, ny, valleys, peaks, saddles, nb_summits) !================================================================================================ !! Function to output the extrema of a 2D array, as peaks, valleys or saddles. implicit none integer(kind=I4), intent(in ) :: nx !! *number of pixels along x* integer(kind=I4), intent(in ) :: ny !! *number of pixels along y* real (kind=R8), intent(in ), dimension(1:nx, 1:ny) :: tab !! *input 2D array* integer(kind=I4), intent(out), dimension(1:3) :: nb_summits !! *number of extrema of each kind* integer(kind=I4), intent(out), dimension(:,:), allocatable :: valleys !! *list of valley coordinates* integer(kind=I4), intent(out), dimension(:,:), allocatable :: peaks !! *list of peaks coordinates* integer(kind=I4), intent(out), dimension(:,:), allocatable :: saddles !! *list of saddles coordinates* integer(kind=I4) :: i, j integer(kind=I4) :: ip ! peak counter integer(kind=I4) :: iv ! valley counter integer(kind=I4) :: is ! saddle counter character(len=1) :: label integer(kind=I4), dimension(1:3, 1:3) :: tp integer(kind=I4), dimension(:,:), allocatable :: topo ! point kind 2D array real(kind=R8), dimension(1:3, 1:3) :: ht real(kind=R8), dimension(1:3) :: gdx, gdy ! gradient vectors allocate( topo(1:nx, 1:ny) ) topo(1:nx, 1:ny) = 0 ! Loop through each point in the surface ip = 1 ; iv = 1 ; is = 1 do i = 1 + 1, nx - 1 do j = 1 + 1, ny - 1 tp(1:3, 1:3) = topo(i-1:i+1, j-1:j+1) ht(1:3, 1:3) = tab(i-1:i+1, j-1:j+1) ! if the gradients along x (resp. y) have the same sign, there is no extremum in the middle node call gradient_corner( hgt = ht(1:3, 1:3), & ! in gdx = gdx(1:3), & ! out gdy = gdy(1:3) ) ! out !~ if ( all( [gdx(6) > 0, gdx(8) > 0, gdx(9) > 0] ) .or. all( [gdy(5) > 0, gdy(7) > 0, gdy(9) > 0] ) ) cycle !~ if ( all( [gdx(6) > 0, gdx(8) > 0, gdx(9) > 0] ) .or. all( [gdy(5) < 0, gdy(7) < 0, gdy(9) < 0] ) ) cycle !~ if ( all( [gdx(6) < 0, gdx(8) < 0, gdx(9) < 0] ) .or. all( [gdy(5) < 0, gdy(7) < 0, gdy(9) < 0] ) ) cycle !~ if ( all( [gdx(6) < 0, gdx(8) < 0, gdx(9) < 0] ) .or. all( [gdy(5) > 0, gdy(7) > 0, gdy(9) > 0] ) ) cycle if ( all( gdx(1:3) > 0 ) .or. all( gdy(1:3) > 0 ) ) cycle if ( all( gdx(1:3) > 0 ) .or. all( gdy(1:3) < 0 ) ) cycle if ( all( gdx(1:3) < 0 ) .or. all( gdy(1:3) < 0 ) ) cycle if ( all( gdx(1:3) < 0 ) .or. all( gdy(1:3) > 0 ) ) cycle ! condition to avoid summits glued to each other: if a summit has been found in the neighborhood, cycle. if ( any( [tp(1, 1) > 0, & ! tp(1, 2) > 0, & ! tp(1, 3) > 0, & ! tp(2, 1) > 0] ) ) cycle call labelize_point( height = ht(1:3, 1:3), & ! in label = label ) ! out selectcase(label) case('V') ; topo(i, j) = 1 ; iv = iv + 1 ! one valley more detected case('S') ; topo(i, j) = 2 ; is = is + 1 ! one saddle more detected case('P') ; topo(i, j) = 3 ; ip = ip + 1 ! one peak more detected endselect enddo enddo nb_summits = [iv - 1, is - 1, ip - 1] ! now the number of extrema is known allocate( valleys(1:nb_summits(1), 1:2) ) allocate( saddles(1:nb_summits(2), 1:2) ) allocate( peaks (1:nb_summits(3), 1:2) ) ip = 1 ; iv = 1 ; is = 1 do i = 1 + 1, nx - 1 do j = 1 + 1, ny - 1 selectcase( topo(i, j) ) case(1) ; valleys(iv, 1) = i ; valleys(iv, 2) = j ; iv = iv + 1 case(2) ; saddles(is, 1) = i ; saddles(is, 2) = j ; is = is + 1 case(3) ; peaks (ip, 1) = i ; peaks (ip, 2) = j ; ip = ip + 1 endselect enddo enddo deallocate( topo ) return endsubroutine label_surf_summits