// Ported from topojson-client src/untransform.js; Math.round uses floor(x + 0.5).
///|
pub struct Quantizer {
priv scale : Array[Double]
priv translate : Array[Double]
} derive(Debug)
///|
pub fn quantizer(
scale : Array[Double],
translate : Array[Double],
) -> Quantizer raise TopoError {
if scale.length() != 2 || translate.length() != 2 {
raise Invalid("transform.dimension")
}
for n in scale {
if !finite(n) || n == 0.0 || n.abs() > 1.0e12 {
raise Invalid("transform.scale")
}
}
for n in translate {
if !finite(n) || n.abs() > 1.0e12 {
raise Invalid("transform.translate")
}
}
{ scale: scale.copy(), translate: translate.copy(), }
}
///|
pub fn Quantizer::point(
self : Quantizer,
p : Array[Double],
) -> Array[Double] raise TopoError {
check_position(p.to_json())
let out = p.copy()
for i = 0; i < 2; i = i + 1 {
let v = @double.floor((p[i] - self.translate[i]) / self.scale[i] + 0.5)
if !finite(v) || v.abs() > 1.0e12 {
raise Invalid("quantize.range")
}
out[i] = v
}
out
}
///|
/// Quantize and delta-encode; discard consecutive coincident positions.
pub fn Quantizer::arc(
self : Quantizer,
points : Array[Array[Double]],
) -> Array[Array[Double]] raise TopoError {
if points.length() < 2 || points.length() > 1000000 {
raise Invalid("arc.size")
}
let first = self.point(points[0])
let out = [first]
let mut x = first[0]
let mut y = first[1]
for i = 1; i < points.length(); i = i + 1 {
let p = self.point(points[i])
let nx = p[0]
let ny = p[1]
p[0] -= x
p[1] -= y
x = nx
y = ny
if p[0] != 0.0 || p[1] != 0.0 {
out.push(p)
}
}
if out.length() == 1 {
out.push([0.0, 0.0])
}
out
}