Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Recalling Values

Status
Not open for further replies.

jaym0310

Technical User
Apr 3, 2012
3
US
Hello,
I'm new to using fortran and I've been working on a project to randomly generate locations of circles on a coordinate grid. I'm also trying to make sure the locations do not overlap.

My initial idea was to make sure the generated values are not within a diameter's distance from each other. To do this I need to be able to access the previously generated values to do the calculations.

If anyone could offer any advice on how I could do that, it would be much appreciated.

Thanks
 
Q1: You mean to tell me that you are not keeping record of every location you generate?

You need to.

Q2: are all the circles supposed to be the same diameter?

Like a round-robin, you are going to have to match up every circle center against every other one and, hence, you could start with a double loop...i.e., one loop inside the other one...and see what the distance between every two point is.

Two full loops that run the entire length of the array are not necessary, though...once you compare the first center against all other ones, when you get to the second center, you do not need to compare that one against the first one and so on...in other words, you do not need to look back, just forward.

So, in your nested do loops, the second loop could start at the index where the second loop is at:

Code:
do i = 1, n
  x1 = centersX(i)
  y1 = centersY(i)
  do j = i+1,n
    x2 = centersX(j)
    y2 = centersY(j)
    d  = distance(x1,y1,x2,y2)
  end do
end do

Then again, this is after the fact; maybe, you would want to validate a just generated center and compare it against all other location, before you decide to keep it in the first place....if it does not pass the distance test, you throw it and generate another one.

does this help?
 
jaym01310,

this looks pretty much like some homework for programming classes. And your homework is made that you should work on it and understand how things are done in programming (programming is only learned by programming) - not just make others solve them for you.

At least you should offer some code that you developed to solve your problem - and then ask why this or that feature does not work as expected.

Okay, Salgerman is in a very patient mood today, but I got mailed by Dave Murphy, that we should red flag student's posts and not help them in cheating with their homework.

So, what's your background ?

Norbert


The optimist believes we live in the best of all possible worlds - the pessimist fears this might be true.
 
I am a 2nd year college student and I'm working on a project for research that I am carrying out. I know that this site isn't used for answering homework questions. I was just hoping to get some advice on some commands that could help me finish my program since I'm still learning.

All of the circles are the same diameter. And they are placed in a grid until the total area of the circles is equal to 25% of the total area.

Here is the code I have so far.

!Code to randomly generate circles onto a 1x1 grid. Radius of circle = 0.05 un.
PROGRAM simple_circle
IMPLICIT NONE

!Define variables
INTEGER::i,sum_i
INTEGER,PARAMETER::ikind=selected_real_kind(p=4)
REAL(kind=ikind)::x,y,r,area_c,sum_a,pi
!The variables i and sum_i are used for the counter
!Variable area_c is the area of the circle
!Variable sum_a is the sum of the areas of the circles
!Variables x and y are used to plot the location of the centers of each of the circles

!Main Body
OPEN(7,file='circle_loc')
WRITE(7,*)'# of Circles X-coordinate Y-coordinate Sum of Areas'
pi=3.14
r=0.05
x=0
y=0
i=1
area_c=0
sum_i=0
sum_a=0

DO WHILE(sum_a<0.25)
CALL RANDOM_NUMBER(x)
CALL RANDOM_NUMBER(y)
IF(x>=0.95 .or. x<=0.05 .or. y<=0.05 .or. y>=0.95) THEN
PRINT*, "~Generated location thrown out."
sum_i= i+sum_i
!A Generated location will be thrown out if the total circle area is outside of the 1x1 grid.

ELSE
area_c=pi*r**2
sum_a= area_c+sum_a
sum_i= i+sum_i

END IF

WRITE(7,*)sum_i,x,y,sum_a
END DO
PRINT*,''
PRINT*,'Finished. Your text file has been created'

END PROGRAM

I had considered a nested do loop but each of the values have to be a certain distance from each other. When I run the program, it gives 32 values. Would this process work for more than just 2?

 
This is one of those where it is easier to write the program than to explain it.

First, you need to do a hand calculation an figure out what is the maximum number of circles that can fit in the grid.
Then, you declare a couple of arrays of such length...one for the x coordinates of the center of the circles and one for the y coordinates.
Then, you do as you are doing, you enter the while loop and generate a random location.
Then you test to see if it passes closeness to the boundary of the grid test.
If so, then, you pretend that you already have a few x,y center locations in the x,y arrays and test whether the just generated x and y just generated are far enough from every other center x and y already generated.
If so, you add this center to the array and increment the count...but you only increment the count when the center has passed both tests and you are actually about to add it to the list.
go back to generate another center.

hope this helps
 
jaym0310,

now we have something to start with. And now I understand your initial question. And the answer to this is the use of arrays, as salgerman pointed out.

You declare your varaibles x nd y as arrays

Code:
real :: xx(100), yy(100)    ! this creates 100 elements of default type real for x and y each

! do as salgerman advised and then
xx(j) = x       ! this saves a succesfully set of coords to the array
yy(j) = y

thus saving all your circle's centers for reference while testing.

Norbert


The optimist believes we live in the best of all possible worlds - the pessimist fears this might be true.
 
Don't forget to take into account the cases when the problem has no solutions (for example, the circle radius is too large for the given grid - or modifify the problem specification, change "is equal to 25%" to "not lesser than 25%" and allow to cross grid borders;).

Moreover: unfortunate placed initial circles may prevent from subsequent placements...

Yet another good advice: no needs to calculate distances (sqrt of), calculate (x1-x2)**2 + (y1-y2)**2 only and compare with 4*r...

(more interesting problem than it would seem at first sight;)
 
That is a question of good programming practice. I for myself parameterize all my project's constants - this is an important issue in program maintenance and adaption. You never know, which modifications to the project's data might show up in the future.

And I dare say that of all the programs that were written with the understanding that there never will be a change in the data set, not 5 % found this assumption to be true.

So it would be

Code:
real :: rLength, rHeight, rRadius, rFill

rLength = 1.0   ! length of the rectangle to fill with circles
rHeight = 1.0   ! height of the rectangle to fill
rRadius = 0.05  ! radius of the circles
rFill = 0.25    ! fraction of the rectangle's area to be filled

If you use these variables in your code instead of the numerical constants you will find it much easier to adapt your prog if somebody rises the idea of 'What if .... is set to ....'

Norbert


The optimist believes we live in the best of all possible worlds - the pessimist fears this might be true.
 
ArkM...no need for sqrt? and compare to 4*r?...you meant 4*r*r?

By the way, there is no need to square things off either, just:
Code:
d=2*r
if ( (abs(xx(j) - x) > d) .or. (abs(yy(j) - y) > d) ) then
   ! we are far enough
end if
 
In diagonal direction this is gives a minimum distance of the centers of sqrt (2.0) * d, while the requirement is that the min distance is d only for not overlapping.



Norbert


The optimist believes we live in the best of all possible worlds - the pessimist fears this might be true.
 
Of course, 4*r*r, it was a misprint ;)

abs(..)+abs(..) is another (good) metrics (taxicab distance) - not for circles in this case...
 
I am currently working on making the necessary changes to my program. Thank you so much for your help.

~Jaym
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top