import bounds from "./bounds.js"; import cut from "./cut.js"; import dedup from "./dedup.js"; import delta from "./delta.js"; import extract from "./extract.js"; import geometry from "./geometry.js"; import hashmap from "./hash/hashmap.js"; import {hasOwnProperty} from "./object.js"; import prequantize from "./prequantize.js"; // Constructs the TopoJSON Topology for the specified hash of features. // Each object in the specified hash must be a GeoJSON object, // meaning FeatureCollection, a Feature or a geometry object. export default function(objects, quantization) { var bbox = bounds(objects = geometry(objects)), transform = quantization > 0 && bbox && prequantize(objects, bbox, quantization), topology = dedup(cut(extract(objects))), coordinates = topology.coordinates, indexByArc = hashmap(topology.arcs.length * 1.4, hashArc, equalArc); objects = topology.objects; // for garbage collection topology.bbox = bbox; topology.arcs = topology.arcs.map(function(arc, i) { indexByArc.set(arc, i); return coordinates.slice(arc[0], arc[1] + 1); }); delete topology.coordinates; coordinates = null; function indexGeometry(geometry) { if (geometry && hasOwnProperty.call(indexGeometryType, geometry.type)) indexGeometryType[geometry.type](geometry); } var indexGeometryType = { GeometryCollection: function(o) { o.geometries.forEach(indexGeometry); }, LineString: function(o) { o.arcs = indexArcs(o.arcs); }, MultiLineString: function(o) { o.arcs = o.arcs.map(indexArcs); }, Polygon: function(o) { o.arcs = o.arcs.map(indexArcs); }, MultiPolygon: function(o) { o.arcs = o.arcs.map(indexMultiArcs); } }; function indexArcs(arc) { var indexes = []; do { var index = indexByArc.get(arc); indexes.push(arc[0] < arc[1] ? index : ~index); } while (arc = arc.next); return indexes; } function indexMultiArcs(arcs) { return arcs.map(indexArcs); } for (var key in objects) { indexGeometry(objects[key]); } if (transform) { topology.transform = transform; topology.arcs = delta(topology.arcs); } return topology; } function hashArc(arc) { var i = arc[0], j = arc[1], t; if (j < i) t = i, i = j, j = t; return i + 31 * j; } function equalArc(arcA, arcB) { var ia = arcA[0], ja = arcA[1], ib = arcB[0], jb = arcB[1], t; if (ja < ia) t = ia, ia = ja, ja = t; if (jb < ib) t = ib, ib = jb, jb = t; return ia === ib && ja === jb; }