///|
pub(all) struct QuantizationReport {
grid : Int
samples : Int
stored_before : Int
stored_after : Int
max_error_x : Double
max_error_y : Double
half_step_x : Double
half_step_y : Double
} derive(Debug, ToJson)
///|
fn point_samples(g : Json, out : Array[Array[Double]]) -> Unit {
match kind(g) {
"Point" => out.push(array(field(g, "coordinates")).map(number))
"MultiPoint" =>
for p in array(field(g, "coordinates")) {
out.push(array(p).map(number))
}
"GeometryCollection" =>
for c in array(field(g, "geometries")) {
point_samples(c, out)
}
_ => ()
}
}
///|
/// Measure coordinate rounding error against every source position before coincident-point removal.
pub fn Topology::quantization_report(
self : Topology,
grid : Int,
) -> QuantizationReport raise TopoError {
let output = self.quantize(grid)
let tr = field(output.data, "transform")
let scale = array(field(tr, "scale")).map(number)
let translate = array(field(tr, "translate")).map(number)
let q = quantizer(scale, translate)
let samples = []
for arc in array(field(self.data, "arcs")) {
for p in array(arc) {
samples.push(array(p).map(number))
}
}
for name in self.names() {
point_samples(self.lookup(name), samples)
}
let mut ex = 0.0
let mut ey = 0.0
for p in samples {
let encoded = q.point(p)
ex = ex.max((encoded[0] * scale[0] + translate[0] - p[0]).abs())
ey = ey.max((encoded[1] * scale[1] + translate[1] - p[1]).abs())
}
{
grid,
samples: samples.length(),
stored_before: self.statistics().stored_positions,
stored_after: output.statistics().stored_positions,
max_error_x: ex,
max_error_y: ey,
half_step_x: scale[0].abs() / 2.0,
half_step_y: scale[1].abs() / 2.0,
}
}