[PLUGINS] ~maj globale
[lhc/web/www.git] / www / plugins / gis / lib / leaflet / plugins / TOPOJSON.js
1 -/**
2 - * Embed of the topojson library from Mike Bostock v1.6.26
3 - * https://github.com/mbostock/topojson
4 - *
5 - */
6
7 (function (global, factory) {
8 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
9 typeof define === 'function' && define.amd ? define(['exports'], factory) :
10 (factory((global.topojson = global.topojson || {})));
11 }(this, function (exports) { 'use strict';
12
13 function noop() {}
14
15 function transformAbsolute(transform) {
16 if (!transform) return noop;
17 var x0,
18 y0,
19 kx = transform.scale[0],
20 ky = transform.scale[1],
21 dx = transform.translate[0],
22 dy = transform.translate[1];
23 return function(point, i) {
24 if (!i) x0 = y0 = 0;
25 point[0] = (x0 += point[0]) * kx + dx;
26 point[1] = (y0 += point[1]) * ky + dy;
27 };
28 }
29
30 function transformRelative(transform) {
31 if (!transform) return noop;
32 var x0,
33 y0,
34 kx = transform.scale[0],
35 ky = transform.scale[1],
36 dx = transform.translate[0],
37 dy = transform.translate[1];
38 return function(point, i) {
39 if (!i) x0 = y0 = 0;
40 var x1 = Math.round((point[0] - dx) / kx),
41 y1 = Math.round((point[1] - dy) / ky);
42 point[0] = x1 - x0;
43 point[1] = y1 - y0;
44 x0 = x1;
45 y0 = y1;
46 };
47 }
48
49 function reverse(array, n) {
50 var t, j = array.length, i = j - n;
51 while (i < --j) t = array[i], array[i++] = array[j], array[j] = t;
52 }
53
54 function bisect(a, x) {
55 var lo = 0, hi = a.length;
56 while (lo < hi) {
57 var mid = lo + hi >>> 1;
58 if (a[mid] < x) lo = mid + 1;
59 else hi = mid;
60 }
61 return lo;
62 }
63
64 function feature(topology, o) {
65 return o.type === "GeometryCollection" ? {
66 type: "FeatureCollection",
67 features: o.geometries.map(function(o) { return feature$1(topology, o); })
68 } : feature$1(topology, o);
69 }
70
71 function feature$1(topology, o) {
72 var f = {
73 type: "Feature",
74 id: o.id,
75 properties: o.properties || {},
76 geometry: object(topology, o)
77 };
78 if (o.id == null) delete f.id;
79 return f;
80 }
81
82 function object(topology, o) {
83 var absolute = transformAbsolute(topology.transform),
84 arcs = topology.arcs;
85
86 function arc(i, points) {
87 if (points.length) points.pop();
88 for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length, p; k < n; ++k) {
89 points.push(p = a[k].slice());
90 absolute(p, k);
91 }
92 if (i < 0) reverse(points, n);
93 }
94
95 function point(p) {
96 p = p.slice();
97 absolute(p, 0);
98 return p;
99 }
100
101 function line(arcs) {
102 var points = [];
103 for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points);
104 if (points.length < 2) points.push(points[0].slice());
105 return points;
106 }
107
108 function ring(arcs) {
109 var points = line(arcs);
110 while (points.length < 4) points.push(points[0].slice());
111 return points;
112 }
113
114 function polygon(arcs) {
115 return arcs.map(ring);
116 }
117
118 function geometry(o) {
119 var t = o.type;
120 return t === "GeometryCollection" ? {type: t, geometries: o.geometries.map(geometry)}
121 : t in geometryType ? {type: t, coordinates: geometryType[t](o)}
122 : null;
123 }
124
125 var geometryType = {
126 Point: function(o) { return point(o.coordinates); },
127 MultiPoint: function(o) { return o.coordinates.map(point); },
128 LineString: function(o) { return line(o.arcs); },
129 MultiLineString: function(o) { return o.arcs.map(line); },
130 Polygon: function(o) { return polygon(o.arcs); },
131 MultiPolygon: function(o) { return o.arcs.map(polygon); }
132 };
133
134 return geometry(o);
135 }
136
137 function stitchArcs(topology, arcs) {
138 var stitchedArcs = {},
139 fragmentByStart = {},
140 fragmentByEnd = {},
141 fragments = [],
142 emptyIndex = -1;
143
144 // Stitch empty arcs first, since they may be subsumed by other arcs.
145 arcs.forEach(function(i, j) {
146 var arc = topology.arcs[i < 0 ? ~i : i], t;
147 if (arc.length < 3 && !arc[1][0] && !arc[1][1]) {
148 t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t;
149 }
150 });
151
152 arcs.forEach(function(i) {
153 var e = ends(i),
154 start = e[0],
155 end = e[1],
156 f, g;
157
158 if (f = fragmentByEnd[start]) {
159 delete fragmentByEnd[f.end];
160 f.push(i);
161 f.end = end;
162 if (g = fragmentByStart[end]) {
163 delete fragmentByStart[g.start];
164 var fg = g === f ? f : f.concat(g);
165 fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
166 } else {
167 fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
168 }
169 } else if (f = fragmentByStart[end]) {
170 delete fragmentByStart[f.start];
171 f.unshift(i);
172 f.start = start;
173 if (g = fragmentByEnd[start]) {
174 delete fragmentByEnd[g.end];
175 var gf = g === f ? f : g.concat(f);
176 fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
177 } else {
178 fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
179 }
180 } else {
181 f = [i];
182 fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f;
183 }
184 });
185
186 function ends(i) {
187 var arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0], p1;
188 if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; });
189 else p1 = arc[arc.length - 1];
190 return i < 0 ? [p1, p0] : [p0, p1];
191 }
192
193 function flush(fragmentByEnd, fragmentByStart) {
194 for (var k in fragmentByEnd) {
195 var f = fragmentByEnd[k];
196 delete fragmentByStart[f.start];
197 delete f.start;
198 delete f.end;
199 f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; });
200 fragments.push(f);
201 }
202 }
203
204 flush(fragmentByEnd, fragmentByStart);
205 flush(fragmentByStart, fragmentByEnd);
206 arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); });
207
208 return fragments;
209 }
210
211 function mesh(topology) {
212 return object(topology, meshArcs.apply(this, arguments));
213 }
214
215 function meshArcs(topology, o, filter) {
216 var arcs = [];
217
218 function arc(i) {
219 var j = i < 0 ? ~i : i;
220 (geomsByArc[j] || (geomsByArc[j] = [])).push({i: i, g: geom});
221 }
222
223 function line(arcs) {
224 arcs.forEach(arc);
225 }
226
227 function polygon(arcs) {
228 arcs.forEach(line);
229 }
230
231 function geometry(o) {
232 if (o.type === "GeometryCollection") o.geometries.forEach(geometry);
233 else if (o.type in geometryType) geom = o, geometryType[o.type](o.arcs);
234 }
235
236 if (arguments.length > 1) {
237 var geomsByArc = [],
238 geom;
239
240 var geometryType = {
241 LineString: line,
242 MultiLineString: polygon,
243 Polygon: polygon,
244 MultiPolygon: function(arcs) { arcs.forEach(polygon); }
245 };
246
247 geometry(o);
248
249 geomsByArc.forEach(arguments.length < 3
250 ? function(geoms) { arcs.push(geoms[0].i); }
251 : function(geoms) { if (filter(geoms[0].g, geoms[geoms.length - 1].g)) arcs.push(geoms[0].i); });
252 } else {
253 for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push(i);
254 }
255
256 return {type: "MultiLineString", arcs: stitchArcs(topology, arcs)};
257 }
258
259 function cartesianTriangleArea(triangle) {
260 var a = triangle[0], b = triangle[1], c = triangle[2];
261 return Math.abs((a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]));
262 }
263
264 function ring(ring) {
265 var i = -1,
266 n = ring.length,
267 a,
268 b = ring[n - 1],
269 area = 0;
270
271 while (++i < n) {
272 a = b;
273 b = ring[i];
274 area += a[0] * b[1] - a[1] * b[0];
275 }
276
277 return area / 2;
278 }
279
280 function merge(topology) {
281 return object(topology, mergeArcs.apply(this, arguments));
282 }
283
284 function mergeArcs(topology, objects) {
285 var polygonsByArc = {},
286 polygons = [],
287 components = [];
288
289 objects.forEach(function(o) {
290 if (o.type === "Polygon") register(o.arcs);
291 else if (o.type === "MultiPolygon") o.arcs.forEach(register);
292 });
293
294 function register(polygon) {
295 polygon.forEach(function(ring$$) {
296 ring$$.forEach(function(arc) {
297 (polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon);
298 });
299 });
300 polygons.push(polygon);
301 }
302
303 function area(ring$$) {
304 return Math.abs(ring(object(topology, {type: "Polygon", arcs: [ring$$]}).coordinates[0]));
305 }
306
307 polygons.forEach(function(polygon) {
308 if (!polygon._) {
309 var component = [],
310 neighbors = [polygon];
311 polygon._ = 1;
312 components.push(component);
313 while (polygon = neighbors.pop()) {
314 component.push(polygon);
315 polygon.forEach(function(ring$$) {
316 ring$$.forEach(function(arc) {
317 polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) {
318 if (!polygon._) {
319 polygon._ = 1;
320 neighbors.push(polygon);
321 }
322 });
323 });
324 });
325 }
326 }
327 });
328
329 polygons.forEach(function(polygon) {
330 delete polygon._;
331 });
332
333 return {
334 type: "MultiPolygon",
335 arcs: components.map(function(polygons) {
336 var arcs = [], n;
337
338 // Extract the exterior (unique) arcs.
339 polygons.forEach(function(polygon) {
340 polygon.forEach(function(ring$$) {
341 ring$$.forEach(function(arc) {
342 if (polygonsByArc[arc < 0 ? ~arc : arc].length < 2) {
343 arcs.push(arc);
344 }
345 });
346 });
347 });
348
349 // Stitch the arcs into one or more rings.
350 arcs = stitchArcs(topology, arcs);
351
352 // If more than one ring is returned,
353 // at most one of these rings can be the exterior;
354 // choose the one with the greatest absolute area.
355 if ((n = arcs.length) > 1) {
356 for (var i = 1, k = area(arcs[0]), ki, t; i < n; ++i) {
357 if ((ki = area(arcs[i])) > k) {
358 t = arcs[0], arcs[0] = arcs[i], arcs[i] = t, k = ki;
359 }
360 }
361 }
362
363 return arcs;
364 })
365 };
366 }
367
368 function neighbors(objects) {
369 var indexesByArc = {}, // arc index -> array of object indexes
370 neighbors = objects.map(function() { return []; });
371
372 function line(arcs, i) {
373 arcs.forEach(function(a) {
374 if (a < 0) a = ~a;
375 var o = indexesByArc[a];
376 if (o) o.push(i);
377 else indexesByArc[a] = [i];
378 });
379 }
380
381 function polygon(arcs, i) {
382 arcs.forEach(function(arc) { line(arc, i); });
383 }
384
385 function geometry(o, i) {
386 if (o.type === "GeometryCollection") o.geometries.forEach(function(o) { geometry(o, i); });
387 else if (o.type in geometryType) geometryType[o.type](o.arcs, i);
388 }
389
390 var geometryType = {
391 LineString: line,
392 MultiLineString: polygon,
393 Polygon: polygon,
394 MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); }
395 };
396
397 objects.forEach(geometry);
398
399 for (var i in indexesByArc) {
400 for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) {
401 for (var k = j + 1; k < m; ++k) {
402 var ij = indexes[j], ik = indexes[k], n;
403 if ((n = neighbors[ij])[i = bisect(n, ik)] !== ik) n.splice(i, 0, ik);
404 if ((n = neighbors[ik])[i = bisect(n, ij)] !== ij) n.splice(i, 0, ij);
405 }
406 }
407 }
408
409 return neighbors;
410 }
411
412 function compareArea(a, b) {
413 return a[1][2] - b[1][2];
414 }
415
416 function minAreaHeap() {
417 var heap = {},
418 array = [],
419 size = 0;
420
421 heap.push = function(object) {
422 up(array[object._ = size] = object, size++);
423 return size;
424 };
425
426 heap.pop = function() {
427 if (size <= 0) return;
428 var removed = array[0], object;
429 if (--size > 0) object = array[size], down(array[object._ = 0] = object, 0);
430 return removed;
431 };
432
433 heap.remove = function(removed) {
434 var i = removed._, object;
435 if (array[i] !== removed) return; // invalid request
436 if (i !== --size) object = array[size], (compareArea(object, removed) < 0 ? up : down)(array[object._ = i] = object, i);
437 return i;
438 };
439
440 function up(object, i) {
441 while (i > 0) {
442 var j = ((i + 1) >> 1) - 1,
443 parent = array[j];
444 if (compareArea(object, parent) >= 0) break;
445 array[parent._ = i] = parent;
446 array[object._ = i = j] = object;
447 }
448 }
449
450 function down(object, i) {
451 while (true) {
452 var r = (i + 1) << 1,
453 l = r - 1,
454 j = i,
455 child = array[j];
456 if (l < size && compareArea(array[l], child) < 0) child = array[j = l];
457 if (r < size && compareArea(array[r], child) < 0) child = array[j = r];
458 if (j === i) break;
459 array[child._ = i] = child;
460 array[object._ = i = j] = object;
461 }
462 }
463
464 return heap;
465 }
466
467 function presimplify(topology, triangleArea) {
468 var absolute = transformAbsolute(topology.transform),
469 relative = transformRelative(topology.transform),
470 heap = minAreaHeap();
471
472 if (!triangleArea) triangleArea = cartesianTriangleArea;
473
474 topology.arcs.forEach(function(arc) {
475 var triangles = [],
476 maxArea = 0,
477 triangle,
478 i,
479 n,
480 p;
481
482 // To store each point’s effective area, we create a new array rather than
483 // extending the passed-in point to workaround a Chrome/V8 bug (getting
484 // stuck in smi mode). For midpoints, the initial effective area of
485 // Infinity will be computed in the next step.
486 for (i = 0, n = arc.length; i < n; ++i) {
487 p = arc[i];
488 absolute(arc[i] = [p[0], p[1], Infinity], i);
489 }
490
491 for (i = 1, n = arc.length - 1; i < n; ++i) {
492 triangle = arc.slice(i - 1, i + 2);
493 triangle[1][2] = triangleArea(triangle);
494 triangles.push(triangle);
495 heap.push(triangle);
496 }
497
498 for (i = 0, n = triangles.length; i < n; ++i) {
499 triangle = triangles[i];
500 triangle.previous = triangles[i - 1];
501 triangle.next = triangles[i + 1];
502 }
503
504 while (triangle = heap.pop()) {
505 var previous = triangle.previous,
506 next = triangle.next;
507
508 // If the area of the current point is less than that of the previous point
509 // to be eliminated, use the latter's area instead. This ensures that the
510 // current point cannot be eliminated without eliminating previously-
511 // eliminated points.
512 if (triangle[1][2] < maxArea) triangle[1][2] = maxArea;
513 else maxArea = triangle[1][2];
514
515 if (previous) {
516 previous.next = next;
517 previous[2] = triangle[2];
518 update(previous);
519 }
520
521 if (next) {
522 next.previous = previous;
523 next[0] = triangle[0];
524 update(next);
525 }
526 }
527
528 arc.forEach(relative);
529 });
530
531 function update(triangle) {
532 heap.remove(triangle);
533 triangle[1][2] = triangleArea(triangle);
534 heap.push(triangle);
535 }
536
537 return topology;
538 }
539
540 var version = "1.6.26";
541
542 exports.version = version;
543 exports.mesh = mesh;
544 exports.meshArcs = meshArcs;
545 exports.merge = merge;
546 exports.mergeArcs = mergeArcs;
547 exports.feature = feature;
548 exports.neighbors = neighbors;
549 exports.presimplify = presimplify;
550
551 }));
552
553 L.TOPOJSON = L.FeatureGroup.extend({
554 options: {
555 async: true
556 },
557
558 initialize: function (data, options) {
559 L.Util.setOptions(this, options);
560 this._topojson = data;
561 this._layers = {};
562
563 if (data) {
564 this.addTOPOJSON(data, options, this.options.async);
565 }
566 },
567
568 loadJSON: function (url, cb, options, async) {
569 if (async === undefined) async = this.options.async;
570 if (options === undefined) options = this.options;
571
572 var req = new window.XMLHttpRequest();
573
574 // Check for IE8 and IE9 Fix Cors for those browsers
575 if (req.withCredentials === undefined && typeof window.XDomainRequest !== 'undefined') {
576 var xdr = new window.XDomainRequest();
577 xdr.open('GET', url, async);
578 xdr.onprogress = function () { };
579 xdr.ontimeout = function () { };
580 xdr.onerror = function () { };
581 xdr.onload = function () {
582 if (xdr.responseText) {
583 //var xml = new window.ActiveXObject('Microsoft.XMLDOM');
584 //xml.loadJSON(xdr.responseText);
585 cb(xdr.responseText, options);
586 }
587 };
588 setTimeout(function () { xdr.send(); }, 0);
589 } else {
590 req.open('GET', url, async);
591 try {
592 req.overrideMimeType('application/json'); // unsupported by IE
593 } catch (e) { }
594 req.onreadystatechange = function () {
595 if (req.readyState !== 4) return;
596 if (req.status === 200) cb(req.response, options);
597 };
598 req.send(null);
599 }
600 },
601
602 addTOPOJSON: function (url, options, async) {
603 var _this = this,
604 cb = function (data) { _this._addTOPOJSON(data); };
605 this.loadJSON(url, cb, options, async);
606 },
607
608 _addTOPOJSON: function (data) {
609 var layers = this.parseTOPOJSON(data);
610 if (!layers || !layers.length) return;
611 for (var i = 0; i < layers.length; i++) {
612 this.fire('addlayer', {
613 layer: layers[i]
614 });
615 this.addLayer(layers[i]);
616 }
617 this.fire('loaded');
618 },
619 _addData : function (l, d) {
620 if ('addData' in l) l.addData(d);
621 if ('setGeoJSON' in l) l.setGeoJSON(d);
622 },
623 parseTOPOJSON : function (data) {
624 var layers = [],
625 o = typeof data === 'string' ? JSON.parse(data) : data;
626 for (var i in o.objects) {
627 var layer = L.geoJson(),
628 ft = topojson.feature(o, o.objects[i]);
629 if (ft.features) this._addData(layer, ft.features);
630 else _this._addData(layer, ft);
631 layers.push(layer);
632 }
633
634 return layers;
635 }
636 });