Некоторое время я делал сценарий для чего-то вроде этого go, так как я хотел случайным образом генерировать равномерно распределенные сферы в трехмерном пространстве .
Вы передаете количество объектов вы хотите выполнить рендеринг и количество попыток для каждого из них, чтобы отвести одно дальше от остальных (меньшее число дает вам лучшую производительность, большее число - лучший результат, 10 в большинстве случаев подойдет).
function randomPointsSpace(qty, tries){
let points = [];
for(let i=0; i<qty; i++){
let candidates = [];
for(let j=0; j<tries; j++){
candidates.push(getCandidate());
}
points.push(getBestCandidate(points, candidates));
}
return points;
}
function getCandidate(){
return {x: Math.random(), y: Math.random(), z: Math.random()};
}
function getBestCandidate(members, candidates){
let max = 0,
selected;
for(let k=0; k<candidates.length; k++){
let min = 1,
c = candidates[k];
for(let l=0; l<members.length; l++){
let m = members[l];
let dist = Math.sqrt( (c.x-m.x) ** 2 + (c.y-m.y) ** 2 + (c.z-m.z) ** 2 ) - m.r/2;
if(dist < min){
min = dist;
}
}
if(min > max){
max = min;
selected = c;
selected.r = min/2;
}
}
return selected;
}
const ar = randomPointsSpace(20, 10);
console.log(ar);
Затем вы получаете массив объектов с координатами x, y, x и радио r, все как числа от 0 до 1, которые вам нужно умножить на размер вашего 3D-пространства.
ar = [
{
"x": 0.33811887215352576,
"y": 0.942598814594636,
"z": 0.4027051631550116,
"r": 0.5
},
{
"x": 0.7434202306598208,
"y": 0.10045068968699278,
"z": 0.010629850147066078,
"r": 0.38175578599626914
},
{
"x": 0.6657177122961799,
"y": 0.07700830496311029,
"z": 0.875727933811969,
"r": 0.3390095317818107
}
];
const canvasLateral = 1000;
const objectsMaxSize = 400;
ar.map( (a) => {
a.x *= canvasLateral;
a.y *= canvasLateral;
a.z *= canvasLateral;
a.r *= objectsMaxSize;
});
console.log(ar);