// Ported from topojson-client src/mesh.js, ISC.
///|
pub(all) enum Boundary {
All
Interior
Exterior
} derive(Eq, Debug)
///|
fn collect_leaves(g : Json, out : Array[Json]) -> Unit {
if kind(g) == "GeometryCollection" {
for c in array(field(g, "geometries")) {
collect_leaves(c, out)
}
} else {
out.push(g)
}
}
///|
fn mesh_ids(g : Json, mode : Boundary) -> Array[Int] {
let leaves : Array[Json] = []
collect_leaves(g, leaves)
let owners : Map[Int, Array[(Int, Int)]] = Map([])
for k = 0; k < leaves.length(); k = k + 1 {
for r in geometry_refs(leaves[k]) {
let id = arc_id(r)
let a = owners.get(id).unwrap_or([])
a.push((r, k))
owners[id] = a
}
}
let keys = owners.keys().collect()
keys.sort()
let out = []
for id in keys {
let a = owners[id]
let shared = a[0].1 != a[a.length() - 1].1
if mode == All ||
(mode == Interior && shared) ||
(mode == Exterior && !shared) {
out.push(a[0].0)
}
}
out
}
///|
/// Return a MultiLineString with arc references. With no object, selects all stored arcs.
pub fn Topology::mesh_arcs(
self : Topology,
name? : String,
boundary? : Boundary = All,
) -> Json raise TopoError {
let ids = match name {
Some(n) => mesh_ids(self.lookup(n), boundary)
None => {
if boundary != All {
raise Invalid("mesh.object_required")
}
Array::makei(array(field(self.data, "arcs")).length(), i => i)
}
}
{ "type": "MultiLineString", "arcs": self.stitch_refs(ids).to_json() }
}
///|
pub fn Topology::mesh(
self : Topology,
name? : String,
boundary? : Boundary = All,
) -> Json raise TopoError {
self.geometry(self.mesh_arcs(name?, boundary~))
}