function dot_density(triangulated_geojson, fields, n_represented = 1) {
let targets = fields.map(f => [])
const { features } = triangulated_geojson;
let total_counts = 0
let ix = 0;
for (let field of fields) {
let i = 0
for (let feature of features) {
const target = randround(feature.properties[field]/n_represented)
total_counts += target || 0
targets[ix][i++] = target || 0
}
ix++;
}
const x_array = new Float32Array(total_counts)
const y_array = new Float32Array(total_counts)
const field_array = new Array(total_counts).fill("")
const ix_array = d3.range(total_counts)
d3.shuffle(ix_array)
let attempted = 0;
let overall_position = 0;
let fnum = 0
for (let feature of features) {
if (!feature.triangles) {feature.triangles = multipolygon_to_triangles(feature.geometry)}
let local_targets = targets.map(d => d[fnum])
fnum += 1
const {coords, vertices} = feature.triangles;
const triangles = [];
for (let i = 0; i < vertices.length; i += 3) {
const a = coords.slice(vertices[i]*2, vertices[i]*2+2);
const b = coords.slice(vertices[i+1]*2, vertices[i+1]*2+2);
const c = coords.slice(vertices[i+2]*2, vertices[i+2]*2+2);
const double_area = Math.abs(
a[0] * (b[1] - c[1]) + b[0] * (c[1] - a[1]) + c[0] * (a[1] - b[1])
)
triangles.push({a, b, c, double_area})
}
let double_areas = d3.sum(triangles.map(d => d.double_area))
for (let {a, b, c, double_area} of triangles) {
const share_of_remaining = double_area/double_areas
double_areas -= double_area
for (let f_num of d3.range(local_targets.length)) {
let how_many_points_do_i_get = randround(local_targets[f_num] * share_of_remaining)
attempted += how_many_points_do_i_get;
for (let i = 0; i < how_many_points_do_i_get; i++) {
const [x, y] = random_point(a, b, c)
const writing_to = ix_array[overall_position++]
x_array[writing_to] = x;
y_array[writing_to] = y;
field_array[writing_to] = f_num
local_targets[f_num] -= 1
}
}
}
}
return {x_array, y_array, field_array}
}