///|
fn remap_refs(j : Json, ids : Map[Int, Int]) -> Json {
match j {
Array(a) => a.map(v => remap_refs(v, ids)).to_json()
Number(n, ..) => {
let r = n.to_int()
let k = ids[arc_id(r)]
(if r < 0 { -k - 1 } else { k }).to_json()
}
_ => j
}
}
///|
fn remap_geometry(g : Json, ids : Map[Int, Int]) -> Json {
if kind(g) == "GeometryCollection" {
replace_fields(
g,
Map([
(
"geometries",
array(field(g, "geometries"))
.map(c => remap_geometry(c, ids))
.to_json(),
),
]),
)
} else if field(g, "arcs") != Json::null() {
replace_fields(g, Map([("arcs", remap_refs(field(g, "arcs"), ids))]))
} else {
g
}
}
///|
/// Select objects and remove unused arcs. Signed references are renumbered without changing features.
pub fn Topology::prune(
self : Topology,
names : Array[String],
) -> Topology raise TopoError {
let used : Map[Int, Bool] = Map([])
for g in self.selected(names) {
for r in geometry_refs(g) {
used[arc_id(r)] = true
}
}
let old_ids = used.keys().collect()
old_ids.sort()
let mapping : Map[Int, Int] = Map([])
let old_arcs = array(field(self.data, "arcs"))
let arcs = []
for k = 0; k < old_ids.length(); k = k + 1 {
mapping[old_ids[k]] = k
arcs.push(old_arcs[old_ids[k]])
}
let objects : Map[String, Json] = Map([])
for name in names {
objects[name] = remap_geometry(self.object(name), mapping)
}
let out = match self.data {
Object(m) => m.copy()
_ => Map([])
}
out.remove("bbox")
out["arcs"] = arcs.to_json()
out["objects"] = Json::object(objects)
let t = read(Json::object(out).stringify())
match t.bbox() {
Some(b) =>
read(replace_fields(t.data, Map([("bbox", b.to_json())])).stringify())
None => t
}
}