topojson.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. /* This file is automatically rebuilt by the Cesium build process. */
  2. function identity(x) {
  3. return x;
  4. }
  5. function transform(transform) {
  6. if (transform == null) return identity;
  7. var x0,
  8. y0,
  9. kx = transform.scale[0],
  10. ky = transform.scale[1],
  11. dx = transform.translate[0],
  12. dy = transform.translate[1];
  13. return function(input, i) {
  14. if (!i) x0 = y0 = 0;
  15. var j = 2, n = input.length, output = new Array(n);
  16. output[0] = (x0 += input[0]) * kx + dx;
  17. output[1] = (y0 += input[1]) * ky + dy;
  18. while (j < n) output[j] = input[j], ++j;
  19. return output;
  20. };
  21. }
  22. function bbox(topology) {
  23. var t = transform(topology.transform), key,
  24. x0 = Infinity, y0 = x0, x1 = -x0, y1 = -x0;
  25. function bboxPoint(p) {
  26. p = t(p);
  27. if (p[0] < x0) x0 = p[0];
  28. if (p[0] > x1) x1 = p[0];
  29. if (p[1] < y0) y0 = p[1];
  30. if (p[1] > y1) y1 = p[1];
  31. }
  32. function bboxGeometry(o) {
  33. switch (o.type) {
  34. case "GeometryCollection": o.geometries.forEach(bboxGeometry); break;
  35. case "Point": bboxPoint(o.coordinates); break;
  36. case "MultiPoint": o.coordinates.forEach(bboxPoint); break;
  37. }
  38. }
  39. topology.arcs.forEach(function(arc) {
  40. var i = -1, n = arc.length, p;
  41. while (++i < n) {
  42. p = t(arc[i], i);
  43. if (p[0] < x0) x0 = p[0];
  44. if (p[0] > x1) x1 = p[0];
  45. if (p[1] < y0) y0 = p[1];
  46. if (p[1] > y1) y1 = p[1];
  47. }
  48. });
  49. for (key in topology.objects) {
  50. bboxGeometry(topology.objects[key]);
  51. }
  52. return [x0, y0, x1, y1];
  53. }
  54. function reverse(array, n) {
  55. var t, j = array.length, i = j - n;
  56. while (i < --j) t = array[i], array[i++] = array[j], array[j] = t;
  57. }
  58. function feature(topology, o) {
  59. if (typeof o === "string") o = topology.objects[o];
  60. return o.type === "GeometryCollection"
  61. ? {type: "FeatureCollection", features: o.geometries.map(function(o) { return feature$1(topology, o); })}
  62. : feature$1(topology, o);
  63. }
  64. function feature$1(topology, o) {
  65. var id = o.id,
  66. bbox = o.bbox,
  67. properties = o.properties == null ? {} : o.properties,
  68. geometry = object(topology, o);
  69. return id == null && bbox == null ? {type: "Feature", properties: properties, geometry: geometry}
  70. : bbox == null ? {type: "Feature", id: id, properties: properties, geometry: geometry}
  71. : {type: "Feature", id: id, bbox: bbox, properties: properties, geometry: geometry};
  72. }
  73. function object(topology, o) {
  74. var transformPoint = transform(topology.transform),
  75. arcs = topology.arcs;
  76. function arc(i, points) {
  77. if (points.length) points.pop();
  78. for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length; k < n; ++k) {
  79. points.push(transformPoint(a[k], k));
  80. }
  81. if (i < 0) reverse(points, n);
  82. }
  83. function point(p) {
  84. return transformPoint(p);
  85. }
  86. function line(arcs) {
  87. var points = [];
  88. for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points);
  89. if (points.length < 2) points.push(points[0]); // This should never happen per the specification.
  90. return points;
  91. }
  92. function ring(arcs) {
  93. var points = line(arcs);
  94. while (points.length < 4) points.push(points[0]); // This may happen if an arc has only two points.
  95. return points;
  96. }
  97. function polygon(arcs) {
  98. return arcs.map(ring);
  99. }
  100. function geometry(o) {
  101. var type = o.type, coordinates;
  102. switch (type) {
  103. case "GeometryCollection": return {type: type, geometries: o.geometries.map(geometry)};
  104. case "Point": coordinates = point(o.coordinates); break;
  105. case "MultiPoint": coordinates = o.coordinates.map(point); break;
  106. case "LineString": coordinates = line(o.arcs); break;
  107. case "MultiLineString": coordinates = o.arcs.map(line); break;
  108. case "Polygon": coordinates = polygon(o.arcs); break;
  109. case "MultiPolygon": coordinates = o.arcs.map(polygon); break;
  110. default: return null;
  111. }
  112. return {type: type, coordinates: coordinates};
  113. }
  114. return geometry(o);
  115. }
  116. function stitch(topology, arcs) {
  117. var stitchedArcs = {},
  118. fragmentByStart = {},
  119. fragmentByEnd = {},
  120. fragments = [],
  121. emptyIndex = -1;
  122. // Stitch empty arcs first, since they may be subsumed by other arcs.
  123. arcs.forEach(function(i, j) {
  124. var arc = topology.arcs[i < 0 ? ~i : i], t;
  125. if (arc.length < 3 && !arc[1][0] && !arc[1][1]) {
  126. t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t;
  127. }
  128. });
  129. arcs.forEach(function(i) {
  130. var e = ends(i),
  131. start = e[0],
  132. end = e[1],
  133. f, g;
  134. if (f = fragmentByEnd[start]) {
  135. delete fragmentByEnd[f.end];
  136. f.push(i);
  137. f.end = end;
  138. if (g = fragmentByStart[end]) {
  139. delete fragmentByStart[g.start];
  140. var fg = g === f ? f : f.concat(g);
  141. fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
  142. } else {
  143. fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
  144. }
  145. } else if (f = fragmentByStart[end]) {
  146. delete fragmentByStart[f.start];
  147. f.unshift(i);
  148. f.start = start;
  149. if (g = fragmentByEnd[start]) {
  150. delete fragmentByEnd[g.end];
  151. var gf = g === f ? f : g.concat(f);
  152. fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
  153. } else {
  154. fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
  155. }
  156. } else {
  157. f = [i];
  158. fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f;
  159. }
  160. });
  161. function ends(i) {
  162. var arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0], p1;
  163. if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; });
  164. else p1 = arc[arc.length - 1];
  165. return i < 0 ? [p1, p0] : [p0, p1];
  166. }
  167. function flush(fragmentByEnd, fragmentByStart) {
  168. for (var k in fragmentByEnd) {
  169. var f = fragmentByEnd[k];
  170. delete fragmentByStart[f.start];
  171. delete f.start;
  172. delete f.end;
  173. f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; });
  174. fragments.push(f);
  175. }
  176. }
  177. flush(fragmentByEnd, fragmentByStart);
  178. flush(fragmentByStart, fragmentByEnd);
  179. arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); });
  180. return fragments;
  181. }
  182. function mesh(topology) {
  183. return object(topology, meshArcs.apply(this, arguments));
  184. }
  185. function meshArcs(topology, object, filter) {
  186. var arcs, i, n;
  187. if (arguments.length > 1) arcs = extractArcs(topology, object, filter);
  188. else for (i = 0, arcs = new Array(n = topology.arcs.length); i < n; ++i) arcs[i] = i;
  189. return {type: "MultiLineString", arcs: stitch(topology, arcs)};
  190. }
  191. function extractArcs(topology, object, filter) {
  192. var arcs = [],
  193. geomsByArc = [],
  194. geom;
  195. function extract0(i) {
  196. var j = i < 0 ? ~i : i;
  197. (geomsByArc[j] || (geomsByArc[j] = [])).push({i: i, g: geom});
  198. }
  199. function extract1(arcs) {
  200. arcs.forEach(extract0);
  201. }
  202. function extract2(arcs) {
  203. arcs.forEach(extract1);
  204. }
  205. function extract3(arcs) {
  206. arcs.forEach(extract2);
  207. }
  208. function geometry(o) {
  209. switch (geom = o, o.type) {
  210. case "GeometryCollection": o.geometries.forEach(geometry); break;
  211. case "LineString": extract1(o.arcs); break;
  212. case "MultiLineString": case "Polygon": extract2(o.arcs); break;
  213. case "MultiPolygon": extract3(o.arcs); break;
  214. }
  215. }
  216. geometry(object);
  217. geomsByArc.forEach(filter == null
  218. ? function(geoms) { arcs.push(geoms[0].i); }
  219. : function(geoms) { if (filter(geoms[0].g, geoms[geoms.length - 1].g)) arcs.push(geoms[0].i); });
  220. return arcs;
  221. }
  222. function planarRingArea(ring) {
  223. var i = -1, n = ring.length, a, b = ring[n - 1], area = 0;
  224. while (++i < n) a = b, b = ring[i], area += a[0] * b[1] - a[1] * b[0];
  225. return Math.abs(area); // Note: doubled area!
  226. }
  227. function merge(topology) {
  228. return object(topology, mergeArcs.apply(this, arguments));
  229. }
  230. function mergeArcs(topology, objects) {
  231. var polygonsByArc = {},
  232. polygons = [],
  233. groups = [];
  234. objects.forEach(geometry);
  235. function geometry(o) {
  236. switch (o.type) {
  237. case "GeometryCollection": o.geometries.forEach(geometry); break;
  238. case "Polygon": extract(o.arcs); break;
  239. case "MultiPolygon": o.arcs.forEach(extract); break;
  240. }
  241. }
  242. function extract(polygon) {
  243. polygon.forEach(function(ring) {
  244. ring.forEach(function(arc) {
  245. (polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon);
  246. });
  247. });
  248. polygons.push(polygon);
  249. }
  250. function area(ring) {
  251. return planarRingArea(object(topology, {type: "Polygon", arcs: [ring]}).coordinates[0]);
  252. }
  253. polygons.forEach(function(polygon) {
  254. if (!polygon._) {
  255. var group = [],
  256. neighbors = [polygon];
  257. polygon._ = 1;
  258. groups.push(group);
  259. while (polygon = neighbors.pop()) {
  260. group.push(polygon);
  261. polygon.forEach(function(ring) {
  262. ring.forEach(function(arc) {
  263. polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) {
  264. if (!polygon._) {
  265. polygon._ = 1;
  266. neighbors.push(polygon);
  267. }
  268. });
  269. });
  270. });
  271. }
  272. }
  273. });
  274. polygons.forEach(function(polygon) {
  275. delete polygon._;
  276. });
  277. return {
  278. type: "MultiPolygon",
  279. arcs: groups.map(function(polygons) {
  280. var arcs = [], n;
  281. // Extract the exterior (unique) arcs.
  282. polygons.forEach(function(polygon) {
  283. polygon.forEach(function(ring) {
  284. ring.forEach(function(arc) {
  285. if (polygonsByArc[arc < 0 ? ~arc : arc].length < 2) {
  286. arcs.push(arc);
  287. }
  288. });
  289. });
  290. });
  291. // Stitch the arcs into one or more rings.
  292. arcs = stitch(topology, arcs);
  293. // If more than one ring is returned,
  294. // at most one of these rings can be the exterior;
  295. // choose the one with the greatest absolute area.
  296. if ((n = arcs.length) > 1) {
  297. for (var i = 1, k = area(arcs[0]), ki, t; i < n; ++i) {
  298. if ((ki = area(arcs[i])) > k) {
  299. t = arcs[0], arcs[0] = arcs[i], arcs[i] = t, k = ki;
  300. }
  301. }
  302. }
  303. return arcs;
  304. }).filter(function(arcs) {
  305. return arcs.length > 0;
  306. })
  307. };
  308. }
  309. function bisect(a, x) {
  310. var lo = 0, hi = a.length;
  311. while (lo < hi) {
  312. var mid = lo + hi >>> 1;
  313. if (a[mid] < x) lo = mid + 1;
  314. else hi = mid;
  315. }
  316. return lo;
  317. }
  318. function neighbors(objects) {
  319. var indexesByArc = {}, // arc index -> array of object indexes
  320. neighbors = objects.map(function() { return []; });
  321. function line(arcs, i) {
  322. arcs.forEach(function(a) {
  323. if (a < 0) a = ~a;
  324. var o = indexesByArc[a];
  325. if (o) o.push(i);
  326. else indexesByArc[a] = [i];
  327. });
  328. }
  329. function polygon(arcs, i) {
  330. arcs.forEach(function(arc) { line(arc, i); });
  331. }
  332. function geometry(o, i) {
  333. if (o.type === "GeometryCollection") o.geometries.forEach(function(o) { geometry(o, i); });
  334. else if (o.type in geometryType) geometryType[o.type](o.arcs, i);
  335. }
  336. var geometryType = {
  337. LineString: line,
  338. MultiLineString: polygon,
  339. Polygon: polygon,
  340. MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); }
  341. };
  342. objects.forEach(geometry);
  343. for (var i in indexesByArc) {
  344. for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) {
  345. for (var k = j + 1; k < m; ++k) {
  346. var ij = indexes[j], ik = indexes[k], n;
  347. if ((n = neighbors[ij])[i = bisect(n, ik)] !== ik) n.splice(i, 0, ik);
  348. if ((n = neighbors[ik])[i = bisect(n, ij)] !== ij) n.splice(i, 0, ij);
  349. }
  350. }
  351. }
  352. return neighbors;
  353. }
  354. function untransform(transform) {
  355. if (transform == null) return identity;
  356. var x0,
  357. y0,
  358. kx = transform.scale[0],
  359. ky = transform.scale[1],
  360. dx = transform.translate[0],
  361. dy = transform.translate[1];
  362. return function(input, i) {
  363. if (!i) x0 = y0 = 0;
  364. var j = 2,
  365. n = input.length,
  366. output = new Array(n),
  367. x1 = Math.round((input[0] - dx) / kx),
  368. y1 = Math.round((input[1] - dy) / ky);
  369. output[0] = x1 - x0, x0 = x1;
  370. output[1] = y1 - y0, y0 = y1;
  371. while (j < n) output[j] = input[j], ++j;
  372. return output;
  373. };
  374. }
  375. function quantize(topology, transform) {
  376. if (topology.transform) throw new Error("already quantized");
  377. if (!transform || !transform.scale) {
  378. if (!((n = Math.floor(transform)) >= 2)) throw new Error("n must be ≥2");
  379. box = topology.bbox || bbox(topology);
  380. var x0 = box[0], y0 = box[1], x1 = box[2], y1 = box[3], n;
  381. transform = {scale: [x1 - x0 ? (x1 - x0) / (n - 1) : 1, y1 - y0 ? (y1 - y0) / (n - 1) : 1], translate: [x0, y0]};
  382. } else {
  383. box = topology.bbox;
  384. }
  385. var t = untransform(transform), box, key, inputs = topology.objects, outputs = {};
  386. function quantizePoint(point) {
  387. return t(point);
  388. }
  389. function quantizeGeometry(input) {
  390. var output;
  391. switch (input.type) {
  392. case "GeometryCollection": output = {type: "GeometryCollection", geometries: input.geometries.map(quantizeGeometry)}; break;
  393. case "Point": output = {type: "Point", coordinates: quantizePoint(input.coordinates)}; break;
  394. case "MultiPoint": output = {type: "MultiPoint", coordinates: input.coordinates.map(quantizePoint)}; break;
  395. default: return input;
  396. }
  397. if (input.id != null) output.id = input.id;
  398. if (input.bbox != null) output.bbox = input.bbox;
  399. if (input.properties != null) output.properties = input.properties;
  400. return output;
  401. }
  402. function quantizeArc(input) {
  403. var i = 0, j = 1, n = input.length, p, output = new Array(n); // pessimistic
  404. output[0] = t(input[0], 0);
  405. while (++i < n) if ((p = t(input[i], i))[0] || p[1]) output[j++] = p; // non-coincident points
  406. if (j === 1) output[j++] = [0, 0]; // an arc must have at least two points
  407. output.length = j;
  408. return output;
  409. }
  410. for (key in inputs) outputs[key] = quantizeGeometry(inputs[key]);
  411. return {
  412. type: "Topology",
  413. bbox: box,
  414. transform: transform,
  415. objects: outputs,
  416. arcs: topology.arcs.map(quantizeArc)
  417. };
  418. }
  419. var index = /*#__PURE__*/Object.freeze({
  420. __proto__: null,
  421. bbox: bbox,
  422. feature: feature,
  423. mesh: mesh,
  424. meshArcs: meshArcs,
  425. merge: merge,
  426. mergeArcs: mergeArcs,
  427. neighbors: neighbors,
  428. quantize: quantize,
  429. transform: transform,
  430. untransform: untransform
  431. });
  432. export { index as default };