function dot_density(
geojson,
fields,
n_represented = 1,
existing_dots = null,
slack = 3,
existing_index = null
) {
if (existing_dots) {
let dots = [];
let index;
if (existing_index) {
index = existing_index;
} else {
index = new KDBush(existing_dots);
}
for (const feature of geojson.features) {
const points_in_bbox = index
.range(...turf.bbox(feature))
.map((i) => existing_dots[i]);
const points_in_feature = turf
.pointsWithinPolygon(turf.points(points_in_bbox), feature)
.features.map((f) => f.geometry.coordinates);
for (const field of fields) {
const k = randround(feature.properties[field] / n_represented);
if (k > points_in_feature.length + slack) {
throw `Not Enough Points. You asked for ${k} points, but there are only ${points_in_feature.length} existing dots intersecting with this feature. Use an existing dots file with more points or increase your features per dot`;
}
dots = dots.concat(
shuffleArray(points_in_feature)
.slice(0, k)
.map(([x, y]) => ({ x, y, field: field }))
);
}
}
return dots;
} else {
const result = uniform_dot_density(geojson, fields, n_represented);
return d3
.zip(
result.x_array,
result.y_array,
result.field_array.map((i) => fields[i])
)
.map(([x, y, field]) => ({ x, y, field }));
}
}