Note
The subroutine generates a composite mask based on specified parameters. The mask is filled with a number of shapes (in this case, ellipses) placed randomly within a defined area, while ensuring that the shapes do not overlap.
locus
is set to ‘center’, the subroutine immediately centers a single shape in the mask.n_cells
) within the mask.
The algorithm limits attempts to place shapes to avoid overlaps.msk_quad
) is used to track where shapes have already been placed, preventing overlaps.Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
integer(kind=I4), | intent(out), | dimension(1:long, 1:larg) | :: | msk |
Output mask that will be filled with shapes |
|
integer(kind=I4), | intent(in) | :: | n_cells |
Number of cells to create in the composite mask |
||
character(len=6), | intent(in) | :: | locus |
Position of the shape (e.g., ‘center’ for centering) |
||
integer(kind=I4), | intent(in) | :: | a |
ellipsis first parameter |
||
integer(kind=I4), | intent(in) | :: | b |
ellipsis second parameter |
||
integer(kind=I4), | intent(in) | :: | width |
Width of each shape to be drawn in the mask |
||
integer(kind=I4), | intent(in) | :: | height |
Height of each shape to be drawn in the mask |
||
character(len=8), | intent(in) | :: | shap |
Type of shape to be drawn (here, ‘ellipsis’ is used) |
||
integer(kind=I4), | intent(in) | :: | long |
Length (dimensions) of the mask |
||
integer(kind=I4), | intent(in) | :: | larg |
Width (dimensions) of the mask |
subroutine make_composite_mask(msk, n_cells, locus, a, b, width, height, shap, long, larg) !================================================================================================ !< @note !< !< The subroutine generates a composite mask based on specified parameters. !< The mask is filled with a number of shapes (in this case, ellipses) placed randomly within a defined area, while ensuring that the shapes do not overlap. !< !< + If the `locus` is set to 'center', the subroutine immediately centers a single shape in the mask. !< + If not centered, it attempts to randomly place the specified number of shapes (`n_cells`) within the mask. !< The algorithm limits attempts to place shapes to avoid overlaps. !< + The routine uses random numbers to determine the position of each shape, ensuring that they fit within the given dimensions and do not exceed the boundaries of the mask. !< + A separate temporary mask (`msk_quad`) is used to track where shapes have already been placed, preventing overlaps. !< + The process continues until the desired number of shapes is successfully placed or until a maximum number of attempts is reached (to avoid infinite loops). !< !< @endnote !------------------------------------------------------------------------------------------------ implicit none integer (kind=I4), intent(in) :: n_cells !! *Number of cells to create in the composite mask* integer (kind=I4), intent(in) :: long !! *Length (dimensions) of the mask* integer (kind=I4), intent(in) :: larg !! *Width (dimensions) of the mask* integer (kind=I4), intent(in) :: width !! *Width of each shape to be drawn in the mask* integer (kind=I4), intent(in) :: height !! *Height of each shape to be drawn in the mask* integer (kind=I4), intent(in) :: a !! *ellipsis first parameter* integer (kind=I4), intent(in) :: b !! *ellipsis second parameter* character(len = 8), intent(in) :: shap !! *Type of shape to be drawn (here, 'ellipsis' is used)* character(len = 6), intent(in) :: locus !! *Position of the shape (e.g., 'center' for centering)* integer (kind=I4), intent(out), dimension(1:long, 1:larg) :: msk !! *Output mask that will be filled with shapes* ! Declaration of local variables integer(kind=I4) :: icells, x0, y0, iter, itry real (kind=R8) :: x, y ! Temporary masks to manage the shapes integer(kind=I4), dimension(1:long, 1:larg) :: msk_quad, msk_shap ! Initialize the output mask to zero msk(1:long, 1:larg) = 0 ! If the position is centered, calculate the central coordinates if (locus == 'center') then x0 = long / 2 + 1 ! x-coordinate of the center y0 = larg / 2 + 1 ! y-coordinate of the center ! Call the subroutine to create a centered ellipse mask call make_mask(x0 = x0, & ! y0 = y0, & ! a = a, & ! b = b, & ! shap = 'ellipsis', & ! msk = msk, & ! long = long, & ! larg = larg) ! return endif ! Initialize the attempt counter for placing cells itry = 0 l1: do itry = itry + 1 ! Increment the attempt counter if (itry > 100) exit l1 ! Limit the number of tries to 100 msk_quad(1:long, 1:larg) = 0 ! Reset the quadrilateral mask msk(1:long, 1:larg) = 0 ! Reset the final mask icells = 0 ! Cell placement counter iter = 0 ! Iteration counter for placement l2: do iter = iter + 1 ! Increment the iteration counter if (iter > 200) cycle l1 ! Limit the number of iterations to 200 ! Display the current state of the iteration and the number of cells write(*,*) iter, icells call random_number(x) ! Generate a random number for x x0 = width / 2 + 1 + x * (long - width - 1) ! Calculate the x-coordinate of the center of the shape call random_number(y) ! Generate a random number for y y0 = height / 2 + 1 + y * (larg - height - 1) ! Calculate the y-coordinate of the center of the shape msk_shap(1:long, 1:larg) = 0 ! Reset the temporary shape mask ! Define the shape mask over a square area centered on (x0, y0) msk_shap(x0 - width / 2:x0 + width / 2, & ! y0 - height / 2:y0 + height / 2) = 1 ! ! Check if the shape does not overlap with an already placed shape if (sum(msk_quad(1:long, 1:larg) * msk_shap(1:long, 1:larg)) > 0) cycle l2 ! Call the subroutine to create an ellipse mask at coordinates (x0, y0) call make_mask(x0 = x0, & ! y0 = y0, & ! a = a, & ! b = b, & ! shap = 'ellipsis', & ! msk = msk, & ! long = long, & ! larg = larg) ! msk_quad(x0 - width / 2:x0 + width / 2, & ! y0 - height / 2:y0 + height / 2) = 1 ! Mark the area of the placed shape icells = icells + 1 ! Increment the count of placed cells if (icells == n_cells) exit l1 ! Exit if the desired number of cells has been reached enddo l2 enddo l1 return endsubroutine make_composite_mask