function weightedVoronoiDistributionAndGraph(center, shapeFunction, numOfSeed, seedingArea, relaxRound, weightMapFunction) {
const cx = center[0], cy = center[1];
const weightedVoronoiRelaxation = function (voronoi) {
let width = voronoi.xmax - voronoi.xmin;
let seed = voronoi.delaunay.points;
let weights = new Array(seed.length / 2).fill(0), centroids = new Array(seed.length).fill(0), counts = new Array(seed.length / 2).fill(0);
let seedIndex = 0;
for (let x = voronoi.xmin; x < voronoi.xmax; x++) {
for (let y = voronoi.ymin; y < voronoi.ymax; y++) {
let weight = weightMapFunction([x, y]);
seedIndex = voronoi.delaunay.find(x, y, seedIndex);
centroids[seedIndex * 2] += x * weight;
centroids[seedIndex * 2 + 1] += y * weight;
weights[seedIndex] += weight;
counts[seedIndex]++;
}
}
for (let i = 0; i < centroids.length; i += 2) {
if (weights[i / 2] > 0) {
centroids[i] /= weights[i / 2];
centroids[i + 1] /= weights[i / 2];
} else {
centroids[i] = seed[i];
centroids[i + 1] = seed[i + 1];
}
}
for (let i = 0; i < seed.length; i++) {
seed[i] += (centroids[i] - seed[i]);
}
return new Delaunay(seed).voronoi([voronoi.xmin, voronoi.ymin, voronoi.xmax, voronoi.ymax]);
}
let seed = [];
for (let i = 0; i < numOfSeed; i++) {
let xx = cx - seedingArea[0] / 2 + Math.random() * seedingArea[0];
let yy = cy - seedingArea[1] / 2 + Math.random() * seedingArea[1];
seed.push(xx, yy);
}
let voronoi = new Delaunay(seed).voronoi([cx - seedingArea[0] / 2, cy - seedingArea[1] / 2, cx + seedingArea[0] / 2, cy + seedingArea[1] / 2]);
for (let i = 0; i < relaxRound; i++) {
voronoi = weightedVoronoiRelaxation(voronoi);
}
let ids = [], ps = [], idMap = {};
let count = 0;
let graph = new Set();
for (let i = 0; i < voronoi.delaunay.points.length; i+=2) {
const p = [voronoi.delaunay.points[i], voronoi.delaunay.points[i + 1]];
const id = i / 2;
if (shapeFunction(p)) {
ids.push(id);
ps.push(...p);
idMap[id] = count;
count ++;
}
}
for (let i = 0; i < ids.length; ++i) {
let nei = voronoi.neighbors(ids[i]);
for (const id of nei){
if (ids.includes(id)){
let rId = idMap[id];
let str = rId > i ? i + " " + rId : rId + " " + i;
graph.add(str);
}
}
}
return [ps, graph];
}