Comp Sci Finding the perimeter of evolving objects in Fortran

  • Thread starter Thread starter Dgrosser
  • Start date Start date
  • Tags Tags
    Fortran Perimeter
AI Thread Summary
The discussion focuses on developing a Fortran program to calculate the perimeter of moving squares that cluster together upon contact. The user has implemented a flood-fill algorithm to identify clusters and is seeking advice on how to compute the perimeter based on the positions of the squares. A proposed method involves checking the adjacent cells of each square to determine how many sides are exposed to empty space. Suggestions include modifying the flood-fill function to return perimeter values and ensuring that edge cases are handled correctly. The conversation emphasizes the importance of accurately counting exposed edges to derive the total perimeter of the clusters.
Dgrosser
Messages
3
Reaction score
0
Hello fellows,

I am writing a computer program in Fortran, to find the perimeter of multiple squares. These squares move as "time" goes along, and if they come in contact with each other, they stick together, forming clusters. The reason why I'm doing this in Fortran is because the original program that randomly places the cubes and moves them is also in Fortran.

To help, I know the program has the position of each square (Which looks like this):
*L is the dimensions of the field)
do i = 1, N
10 x(i) = int(L*ranr()) + 1
y(i) = int(L*ranr()) + 1
if (occ(x(i),y(i)).eq.1) goto 10
occ(x(i),y(i)) = 1
id(x(i),y(i)) = i
write(11,*) x(i), y(i) !Write into pos.dat
enddo

This gives the definition of the squares, which it then transfers to a file (pos.dat).
There is also code to define the clusters, so that each cluster has its own area:

iclust = 0 ! iclust: the temporary number of clusters
csize = 0.0
do i = 1, N
xc = x(i) ! current position in x
yc = y(i) ! current position in y
x1 = xc
y1 = yc
if (fill(x(i),y(i)).eq.1) then
iclust = iclust + 1
tab = 0
clustN(iclust) = tab
clustI(iclust,:) = ids(:)
csize = csize + tab


Finally, all the clusters are figured out by a flood-fill algorithm, which I think may be relavent:
*Note old = 1*
one = 1

if (fill(x1,y1).eq.old) then

fill(x1,y1) = new
tab = tab + 1
ids(tab) = id(x1,y1)
if (x1.eq.L) then
call floodPBC(xc,yc,one,y1,new,old,fill,tab,ids,id)
else
call floodPBC(xc,yc,x1+1,y1,new,old,fill,tab,ids,id)
endif

if (y1.eq.L) then
call floodPBC(xc,yc,x1,one,new,old,fill,tab,ids,id)
else
call floodPBC(xc,yc,x1,y1+1,new,old,fill,tab,ids,id)
endif

if (x1.eq.1) then
call floodPBC(xc,yc,L,y1,new,old,fill,tab,ids,id)
else
call floodPBC(xc,yc,x1-1,y1,new,old,fill,tab,ids,id)
endif

if (y1.eq.1) then
call floodPBC(xc,yc,x1,L,new,old,fill,tab,ids,id)
else
call floodPBC(xc,yc,x1,y1-1,new,old,fill,tab,ids,id)
endif

endif

return
Where yc and xc are original positions, and x1 and y1 are the new updated positions.

Any advice will help. I am not a programer, but I am beginning to learn it. Thank you.
 
Physics news on Phys.org
Dgrosser said:
Hello fellows,

I am writing a computer program in Fortran, to find the perimeter of multiple squares. These squares move as "time" goes along, and if they come in contact with each other, they stick together, forming clusters. The reason why I'm doing this in Fortran is because the original program that randomly places the cubes and moves them is also in Fortran.

To help, I know the program has the position of each square (Which looks like this):
*L is the dimensions of the field)
do i = 1, N
10 x(i) = int(L*ranr()) + 1
y(i) = int(L*ranr()) + 1
if (occ(x(i),y(i)).eq.1) goto 10
occ(x(i),y(i)) = 1
id(x(i),y(i)) = i
write(11,*) x(i), y(i) !Write into pos.dat
enddo

This gives the definition of the squares, which it then transfers to a file (pos.dat).
There is also code to define the clusters, so that each cluster has its own area:

iclust = 0 ! iclust: the temporary number of clusters
csize = 0.0
do i = 1, N
xc = x(i) ! current position in x
yc = y(i) ! current position in y
x1 = xc
y1 = yc
if (fill(x(i),y(i)).eq.1) then
iclust = iclust + 1
tab = 0
clustN(iclust) = tab
clustI(iclust,:) = ids(:)
csize = csize + tab


Finally, all the clusters are figured out by a flood-fill algorithm, which I think may be relavent:
*Note old = 1*
one = 1

if (fill(x1,y1).eq.old) then

fill(x1,y1) = new
tab = tab + 1
ids(tab) = id(x1,y1)
if (x1.eq.L) then
call floodPBC(xc,yc,one,y1,new,old,fill,tab,ids,id)
else
call floodPBC(xc,yc,x1+1,y1,new,old,fill,tab,ids,id)
endif

if (y1.eq.L) then
call floodPBC(xc,yc,x1,one,new,old,fill,tab,ids,id)
else
call floodPBC(xc,yc,x1,y1+1,new,old,fill,tab,ids,id)
endif

if (x1.eq.1) then
call floodPBC(xc,yc,L,y1,new,old,fill,tab,ids,id)
else
call floodPBC(xc,yc,x1-1,y1,new,old,fill,tab,ids,id)
endif

if (y1.eq.1) then
call floodPBC(xc,yc,x1,L,new,old,fill,tab,ids,id)
else
call floodPBC(xc,yc,x1,y1-1,new,old,fill,tab,ids,id)
endif

endif

return
Where yc and xc are original positions, and x1 and y1 are the new updated positions.

Any advice will help. I am not a programer, but I am beginning to learn it. Thank you.

What's your question?
 
My question is how can I find the perimeter of these plotted points in a lattice plane. Each of the squares has a unit side of 1, and one thing I did not mention is that the cubes have a natural value of "1", where the empty space has a natural value of "0". I was thinking I could write a program that would track each cube and check the area around it. If the area above and to the left is empty (y1+1; x1-1), then the perimeter would be 2, as the other areas would be cut off by other cubes. So the code would look something like:

Do i 1,N !(N=Number of cubes)

if (xi+1.eq.0) Perimeter=perimeter+1
if (xi-1.eq.0) Perimeter=perimeter+1
if (yi+1.eq.0) Perimeter=perimeter+1
if (yi-1.eq.0) Perimeter=perimeter+1
enddo

Would this work, or is there something I'm missing?
 
I gather that you are trying to determine the total number of sides that a given custer has that are shared with empty cells. So for a single cell, the answer would be four. For two adjacent cells forming a rectangle the answer would be six. For three cells forming an L it would be eight. Am I understanding you right? If so, two ideas spring to mind.

One would be to modify that flood fill function so that it returns a value, and return the sum of the return values of any calls to itself that it makes plus the number of sides in the cell (x1,y1). Your code in your last post will almost do the edge counting - you need to actually look at the array (so fill(x1+1,y1).eq.0 etc inside the brackets) but it is on the right lines. Watch out for the array edges, though - the flood fill algorithm appears to wrap around the edge of the world, and you need to do the same.

The other option is to look at the array fill, which I gather has a different number for each cluster - so 0 means empty, 1 means "part of first cluster", 2 means "part of second cluster" and so on. Create an array with one entry for each cluster, then loop over each cell in fill. If the cell value is non-zero, count the edges using your idea (as modified in the previous paragraph) and add it to the appropriate entry in your new array.
 

Similar threads

Replies
11
Views
6K
Replies
1
Views
2K
Replies
10
Views
2K
Replies
2
Views
4K
Replies
4
Views
10K
Back
Top