Random Coordinates

I want to generate 100 random coordinates in 3D space satisfying the following conditions:
1) the maximum value of any coordinate is less than 14
2) the distance between any two points is always more than 2

I wrote a code that generates the first coordinate and stuck on how to go further because as I move further, I would have to make sure that the new coordinate is farther than 2 units from all of the coordinates already generated.

A 14*14*14 box? You could create an evenly spaced lattice with 7*7*7 points that is within the box.

343 points in the lattice. Put them on a list. Shuffle the list. Take first 100.

The distance between two points in full lattice is almost 14/6, i.e. 2.33. You can randomly shift each of the selected 100 points a small amount to any direction without creating a collision.

Is that good enough?
1
2
3
4
struct point
{
   double x, y, z;
};


Create a
vector<point> pts( NUMPOINTS );

Fill the elements of pts successively as three random numbers uniform on [0,14), checking against all previous points in the vector; add a point only if its distance from all others is > 2. (Speed that up: exclude the absolute difference between corresponding coordinates first; then look at squared distance only. Give up on a potential point as soon as it fails to satisfy the distance criterion against any previous point.)

You've got some space in that box - shouldn't be too many overlaps.

           1:        5.745       9.745       7.564
           2:        1.160       5.328      11.879
           3:        8.114       9.949      11.019
           4:       12.626       9.880       0.436
           5:        5.092      12.574       8.360
           6:       13.692       9.958       4.227
           7:        5.577       9.612       2.933
           8:        3.775       2.927       8.820
           9:        4.101       2.163      11.287
          10:        0.352       5.547       7.169
          11:        3.876       3.773       5.228
          12:        1.017       8.804      10.252
          13:        0.308       2.839       2.580
          14:       10.341       1.606       2.144
          15:       12.496       1.692       0.172
          16:       12.531       6.809      10.501
          17:        3.732       1.297       7.151
          18:        7.635       0.502      13.303
          19:       10.763       8.484       0.555
          20:        6.506       2.760       5.423
          21:       10.877       7.627       6.007
          22:        4.286      11.704      10.737
          23:        9.722      10.405       6.417
          24:        2.497       3.886       2.691
          25:       12.998       0.269       8.822
          26:       10.527       0.975       8.245
          27:        8.614      12.486      11.388
          28:        7.760       3.029      11.672
          29:        3.574       3.660       0.100
          30:        6.967       6.722      11.917
          31:        6.770      13.461       2.753
          32:        1.224      12.018       3.744
          33:        4.446       7.846       8.570
          34:        4.371       8.057      10.959
          35:        3.824      12.201       1.217
          36:        1.863       9.943       6.517
          37:        1.544      13.812       8.935
          38:        1.046      12.135       1.089
          39:       10.727       4.521       0.538
          40:        8.279       9.126       3.696
          41:        7.056       6.858       4.416
          42:        2.706       3.909       7.422
          43:        5.128       0.176      12.404
          44:       13.969      11.811      10.752
          45:        0.893       8.340      12.374
          46:       10.684      12.302      12.914
          47:        4.845      13.707       5.634
          48:        7.713       0.354       2.223
          49:        2.859      11.644       7.718
          50:        7.837      13.741       6.856
          51:       13.572       5.779      12.125
          52:       11.013      13.466       3.498
          53:        3.434       5.947       2.849
          54:       13.075       7.830       6.166
          55:        5.278      10.169      11.849
          56:        6.145       0.290       8.682
          57:       11.906       1.908      12.581
          58:       13.915       9.283      13.641
          59:        4.133       0.740       3.076
          60:        6.737       4.805      10.992
          61:       13.463       0.189       1.211
          62:        6.552      11.518       6.572
          63:        6.260       8.271       6.183
          64:        2.914       7.950       0.806
          65:       11.993      13.431       1.027
          66:        3.770       6.213      13.259
          67:        3.469      10.091       2.009
          68:        1.397       7.045       3.926
          69:        2.786       0.370      13.156
          70:        2.747      10.347      10.055
          71:        5.633       1.647       0.644
          72:        7.269       4.576      13.574
          73:       10.245      11.067      10.307
          74:        7.790       6.808       7.516
          75:       11.170      12.760       9.575
          76:        5.097       8.219       0.269
          77:       11.140       4.898      13.152
          78:        3.953      13.587      11.341
          79:        7.781       8.201       9.076
          80:        7.501      10.345       1.173
          81:        2.175       5.418       8.810
          82:        5.121       6.557       1.479
          83:        9.148       2.969       3.876
          84:        9.360       0.177       6.627
          85:        2.949      12.139      12.603
          86:       11.672      11.473       1.654
          87:       13.952       5.973       3.522
          88:       11.628       5.349       3.025
          89:        9.807       8.934      13.501
          90:        2.170       2.687       5.756
          91:        3.247       1.940       1.695
          92:        8.943       5.941       0.089
          93:       13.284       4.543       1.221
          94:       12.320       4.735       4.975
          95:        8.840       5.780      13.105
          96:        1.371       3.103      10.375
          97:        3.931       0.157       9.254
          98:       12.547       5.967       8.067
          99:       13.819       8.330       8.301
         100:       12.190       9.778       7.117
Minimum coordinate = 0.089
Maximum coordinate = 13.969
Minimum distance   = 2.005
Last edited on
@lastchance
I understand the algorithm completely but as I am very new to C++ I am having hard times writing the code.
Last edited on
Perhaps you can show us what you have done so far?

You have generated the first point - OK that means you have used some random numbers.

Then try generating a second point and checking how far it is from the first.
#include <iostream>
#include <cmath>
#include <ctime>
#include <cstdlib>

using namespace std;

struct rand_num {
double x;
double y;
double z;
};
const int row = 210 ;
double d, box_size = 14.14;
//double a[row], b[row], c[row];

int main() {
srand(time(NULL));
rand_num Atom[row];
int count = 0;
double dis;
double temp_x, temp_y, temp_z;
//This fills in the first random coordinates
Atom[0].x = box_size*(double) rand() / (RAND_MAX );
Atom[0].y = box_size*(double) rand() / (RAND_MAX );
Atom[0].z = box_size*(double) rand() / (RAND_MAX );

count ++;
//////////////////////////////////////////////////////////
temp_x = box_size*(double) rand() / (RAND_MAX );
temp_y = box_size*(double) rand() / (RAND_MAX );
temp_z = box_size*(double) rand() / (RAND_MAX );

dis = sqrt(pow(temp_x-Atom[0].x, 2) + pow(temp_y-Atom[0].y, 2) + pow(temp_z-Atom[0].z, 2));
if (dis > 2)
{
Atom[1].x = temp_x;
Atom[1].y = temp_y;
Atom[1].z = temp_z;
count ++;
}
for (int i = 0;i < count;i++)
{
cout << Atom[i].x << '\t' << Atom[i].y << '\t' << Atom[i].z << '\n';
}
return 0;
}
That's good!

Small matters:
- please put [code] [/code] tags around your sample - then the indentation will show properly and we will be able to run in c++-shell without having to download it.

- there are better ways of generating uniform random variables than the discrete rand(); however, we can get to that in a bit.

All you need to do in the first instance is put (nested) loops around the check for a new Atom.
count will be the index of the Atom that you are trying to add, so something like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
while ( count < 100 )
{
   bool ok = true;
   for ( int j = 0; j < count; j++ )    // check ALL previously placed Atoms, 
   {
      // Your current code starting at temp_x = ...
      // ... with dis = .... Atom[j] ...          // comparing with the jth Atom
      // Set ok = false if any Atom is too close; then break out of the loop
   }
   if ( ok )
   {
      // Set Atom[count]    (rather than your current Atom[1]
   }
}



Get the loop structure working. You can improve the random-number stuff and some other details later.
Last edited on
[#include <iostream>
#include <cmath>
#include <ctime>
#include <cstdlib>

using namespace std;

bool search(const int record[], int count_record, int target);

struct rand_num {
double x;
double y;
double z;
};
const int row = 210 ;
double d, box_size = 14.14, min_dis = 2.1;
//double a[row], b[row], c[row];

int main()
{
srand(time(NULL));
rand_num Atom[row];
int count = 0, count_record = 0;
double dis[row];
int record[row];
double temp_x, temp_y, temp_z;
//This fills in the first random coordinates
Atom[0].x = box_size*(double) rand() / (RAND_MAX );
Atom[0].y = box_size*(double) rand() / (RAND_MAX );
Atom[0].z = box_size*(double) rand() / (RAND_MAX );

count ++;
//////////////////////////////////////////////////////////
for (int j = 1;j < row; j++)
{
temp_x = box_size*(double) rand() / (RAND_MAX );
temp_y = box_size*(double) rand() / (RAND_MAX );
temp_z = box_size*(double) rand() / (RAND_MAX );

for (int i = 0;i < j;i++)
{
dis [i]= sqrt(pow(temp_x-Atom[i].x, 2) + pow(temp_y-Atom[i].y, 2) + pow(temp_z-Atom[i].z, 2));

if (dis [i] > min_dis)
{
record[i] = 1;
count_record++;
}
else
{
record [i] = 0;
count_record++;
}
}

if (search(record, count_record, 0) == false)
{
Atom[j].x = temp_x;
Atom[j].y = temp_y;
Atom[j].z = temp_z;
count++;
}
}
////////////////Print out the random coordinates////////////
for (int i = 0;i < count;i++)
{
cout << Atom[i].x << '\t' << Atom[i].y << '\t' << Atom[i].z << '\n';
}
return 0;
}

////////////////////////Functions///////////////////////////
///////////////////////////search function//////////////////
bool search(const int record[], int count_record, int target)
{
for(size_t i = 0;i < count_record;i++)
{
if (target == record [i])
return true;
}
return false;
}
]
This is what I have now. The compilation does not show me any errors but it prints only two coordinates. I don't know where I am going wrong.
I'm finding it hard to read without the indentation. Please use the [code] [/code]
tags carefully. You can put them in by selecting your code and using the < > item in the Format menu to the right of the box you are entering in.

You are getting very confused with counters. We now have count, count_record and j ... you really only need the first of those.

I would suggest that your outer loop is a while loop, not a for loop.
while ( count < row )
This is because your (temp_x,temp_y,temp_z) might NOT get added. At the moment you are just doing row passes and hoping that they are OK. They won't be.

Get rid of your record[] and search stuff ... it isn't needed. Add a particle (and increment count) if it is OK. Don't add the particle (and don't increment count) if it isn't. That's why you should use a while loop based on count ... you can keep looping until you have enough good particles.

Have another look at the loop structure I suggested; don't be too hooked on for loops.
Last edited on
Topic archived. No new replies allowed.