How to generate uniformly distributed random coordinates inside a cuboid such that the distance between points is greater than a constant value?

24 views (last 30 days)
I want to generate uniform randomly distributed points inside a cube. The points should also satisfy a condition that they should be atleast a constant distance apart. I have written a matlab code, but the end result is not uniformly distributed points. I think the issue is that i am creating one random point at a time. Please have a look at the attached script. Any suggestions?
close all
% matlab code to generate random coordinates for inclusions
% translation of inclusions into polymer box
% here uniform distribution is considered
% polymer box size 80*80*100
% inclusions should not overlap each other
% inclusions should not cross the boundary too
% in order to avoid inclusions from crossing the boundary, consider a
% shrinked box dimension
% all units in Angstroms
% size of inclusion 8*8*10
% RVE dimension
xlo = 0;
xhi = 80;
ylo = 0;
yhi = 80;
zlo = 0;
zhi = 100;
% inclusion dimension
xlo_incl = 0;
xhi_incl = 8;
ylo_incl = 0;
yhi_incl = 8;
zlo_incl = 0;
zhi_incl = 10;
% half the diagonal distance of inclusion should be avoided from RVE size
% to prevent inclusions from overlapping the boundary
% tolerance of 1 Angstroms is provided
point1 = [xlo_incl ylo_incl zlo_incl];
point2 = [xhi_incl yhi_incl zhi_incl];
dia_dist = norm(point2-point1);
trim_tolerance = 1;
trim_dist = dia_dist*0.5+trim_tolerance;
% actual dimension to work with
xlo_trim = xlo+trim_dist;
xhi_trim = xhi-trim_dist;
ylo_trim = ylo+trim_dist;
yhi_trim = yhi-trim_dist;
zlo_trim = zlo+trim_dist;
zhi_trim = zhi-trim_dist;
% generate random numbers
num_incl = 8;
dia_tolerance = 3; % tolerance value for seperation of RVE(angstroms)
dia_tot = dia_dist+dia_tolerance;
x_rand = xlo_trim+(xhi_trim-xlo_trim)*rand(1,1);
y_rand = ylo_trim+(yhi_trim-ylo_trim)*rand(1,1);
z_rand = zlo_trim+(zhi_trim-zlo_trim)*rand(1,1);
rand_coord = zeros(num_incl,3);
rand_coord(1,:) = [x_rand y_rand z_rand];
i = 1;
check_matrix =(dia_tot+1);
x_rand1 = xlo_trim+(xhi_trim-xlo_trim)*rand(1,1);
y_rand1 = ylo_trim+(yhi_trim-ylo_trim)*rand(1,1);
z_rand1 = zlo_trim+(zhi_trim-zlo_trim)*rand(1,1);
coord_new = [x_rand1 y_rand1 z_rand1];
for j=1:i
check_dist(j) = norm(coord_new-rand_coord(j,:));
A = all(check_matrix(:) > dia_tot);
if A > 0
rand_coord(i+1,:) = coord_new;
i = i+1;
John D'Errico
John D'Errico on 16 Dec 2021
Edited: John D'Errico on 16 Dec 2021
If the points are truly uniformly distributed, then there is no theortetical minimum distance between pairs of points. Does the fact that you are generating them one at a time matter? No. The fallacy lies in your expectations, that a uniform distribution has no points that lie closely together.
As Walter has pointed out, this becomes a sphere packing problem, but sphere packing is not so trivial.
Simple schemes like rejection sampling can work, but don't expect to get any kind of dense sampling that might be even close to optimal, certainly not in a reasonable amount of time. You can also try things like starting with a random sample, then perturbing points to move away from each other when they are too close or too far from their nearest neighbors. You could think of that in terms of a force on each point, that depends upon the distance to their nearest neighbor.
Of course that result will no longer be truly uniformly distributed. However, it may be the best thing you can do in a reasonable time if you want some sort of fairly dense packing subject to a minimum distance.

Sign in to comment.

Answers (1)

Moreno, M.
Moreno, M. on 20 Mar 2022
Edited: Walter Roberson on 21 Mar 2022




Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!