annotate src/DML/VendorAssetsBundle/Resources/assets/vega/2.2.6/topojson.js @ 1:f38015048f48 tip

Added GPL
author Daniel Wolff
date Sat, 13 Feb 2016 20:43:38 +0100
parents 493bcb69166c
children
rev   line source
Daniel@0 1 !function() {
Daniel@0 2 var topojson = {
Daniel@0 3 version: "1.6.19",
Daniel@0 4 mesh: function(topology) { return object(topology, meshArcs.apply(this, arguments)); },
Daniel@0 5 meshArcs: meshArcs,
Daniel@0 6 merge: function(topology) { return object(topology, mergeArcs.apply(this, arguments)); },
Daniel@0 7 mergeArcs: mergeArcs,
Daniel@0 8 feature: featureOrCollection,
Daniel@0 9 neighbors: neighbors,
Daniel@0 10 presimplify: presimplify
Daniel@0 11 };
Daniel@0 12
Daniel@0 13 function stitchArcs(topology, arcs) {
Daniel@0 14 var stitchedArcs = {},
Daniel@0 15 fragmentByStart = {},
Daniel@0 16 fragmentByEnd = {},
Daniel@0 17 fragments = [],
Daniel@0 18 emptyIndex = -1;
Daniel@0 19
Daniel@0 20 // Stitch empty arcs first, since they may be subsumed by other arcs.
Daniel@0 21 arcs.forEach(function(i, j) {
Daniel@0 22 var arc = topology.arcs[i < 0 ? ~i : i], t;
Daniel@0 23 if (arc.length < 3 && !arc[1][0] && !arc[1][1]) {
Daniel@0 24 t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t;
Daniel@0 25 }
Daniel@0 26 });
Daniel@0 27
Daniel@0 28 arcs.forEach(function(i) {
Daniel@0 29 var e = ends(i),
Daniel@0 30 start = e[0],
Daniel@0 31 end = e[1],
Daniel@0 32 f, g;
Daniel@0 33
Daniel@0 34 if (f = fragmentByEnd[start]) {
Daniel@0 35 delete fragmentByEnd[f.end];
Daniel@0 36 f.push(i);
Daniel@0 37 f.end = end;
Daniel@0 38 if (g = fragmentByStart[end]) {
Daniel@0 39 delete fragmentByStart[g.start];
Daniel@0 40 var fg = g === f ? f : f.concat(g);
Daniel@0 41 fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
Daniel@0 42 } else {
Daniel@0 43 fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
Daniel@0 44 }
Daniel@0 45 } else if (f = fragmentByStart[end]) {
Daniel@0 46 delete fragmentByStart[f.start];
Daniel@0 47 f.unshift(i);
Daniel@0 48 f.start = start;
Daniel@0 49 if (g = fragmentByEnd[start]) {
Daniel@0 50 delete fragmentByEnd[g.end];
Daniel@0 51 var gf = g === f ? f : g.concat(f);
Daniel@0 52 fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
Daniel@0 53 } else {
Daniel@0 54 fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
Daniel@0 55 }
Daniel@0 56 } else {
Daniel@0 57 f = [i];
Daniel@0 58 fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f;
Daniel@0 59 }
Daniel@0 60 });
Daniel@0 61
Daniel@0 62 function ends(i) {
Daniel@0 63 var arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0], p1;
Daniel@0 64 if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; });
Daniel@0 65 else p1 = arc[arc.length - 1];
Daniel@0 66 return i < 0 ? [p1, p0] : [p0, p1];
Daniel@0 67 }
Daniel@0 68
Daniel@0 69 function flush(fragmentByEnd, fragmentByStart) {
Daniel@0 70 for (var k in fragmentByEnd) {
Daniel@0 71 var f = fragmentByEnd[k];
Daniel@0 72 delete fragmentByStart[f.start];
Daniel@0 73 delete f.start;
Daniel@0 74 delete f.end;
Daniel@0 75 f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; });
Daniel@0 76 fragments.push(f);
Daniel@0 77 }
Daniel@0 78 }
Daniel@0 79
Daniel@0 80 flush(fragmentByEnd, fragmentByStart);
Daniel@0 81 flush(fragmentByStart, fragmentByEnd);
Daniel@0 82 arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); });
Daniel@0 83
Daniel@0 84 return fragments;
Daniel@0 85 }
Daniel@0 86
Daniel@0 87 function meshArcs(topology, o, filter) {
Daniel@0 88 var arcs = [];
Daniel@0 89
Daniel@0 90 if (arguments.length > 1) {
Daniel@0 91 var geomsByArc = [],
Daniel@0 92 geom;
Daniel@0 93
Daniel@0 94 function arc(i) {
Daniel@0 95 var j = i < 0 ? ~i : i;
Daniel@0 96 (geomsByArc[j] || (geomsByArc[j] = [])).push({i: i, g: geom});
Daniel@0 97 }
Daniel@0 98
Daniel@0 99 function line(arcs) {
Daniel@0 100 arcs.forEach(arc);
Daniel@0 101 }
Daniel@0 102
Daniel@0 103 function polygon(arcs) {
Daniel@0 104 arcs.forEach(line);
Daniel@0 105 }
Daniel@0 106
Daniel@0 107 function geometry(o) {
Daniel@0 108 if (o.type === "GeometryCollection") o.geometries.forEach(geometry);
Daniel@0 109 else if (o.type in geometryType) geom = o, geometryType[o.type](o.arcs);
Daniel@0 110 }
Daniel@0 111
Daniel@0 112 var geometryType = {
Daniel@0 113 LineString: line,
Daniel@0 114 MultiLineString: polygon,
Daniel@0 115 Polygon: polygon,
Daniel@0 116 MultiPolygon: function(arcs) { arcs.forEach(polygon); }
Daniel@0 117 };
Daniel@0 118
Daniel@0 119 geometry(o);
Daniel@0 120
Daniel@0 121 geomsByArc.forEach(arguments.length < 3
Daniel@0 122 ? function(geoms) { arcs.push(geoms[0].i); }
Daniel@0 123 : function(geoms) { if (filter(geoms[0].g, geoms[geoms.length - 1].g)) arcs.push(geoms[0].i); });
Daniel@0 124 } else {
Daniel@0 125 for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push(i);
Daniel@0 126 }
Daniel@0 127
Daniel@0 128 return {type: "MultiLineString", arcs: stitchArcs(topology, arcs)};
Daniel@0 129 }
Daniel@0 130
Daniel@0 131 function mergeArcs(topology, objects) {
Daniel@0 132 var polygonsByArc = {},
Daniel@0 133 polygons = [],
Daniel@0 134 components = [];
Daniel@0 135
Daniel@0 136 objects.forEach(function(o) {
Daniel@0 137 if (o.type === "Polygon") register(o.arcs);
Daniel@0 138 else if (o.type === "MultiPolygon") o.arcs.forEach(register);
Daniel@0 139 });
Daniel@0 140
Daniel@0 141 function register(polygon) {
Daniel@0 142 polygon.forEach(function(ring) {
Daniel@0 143 ring.forEach(function(arc) {
Daniel@0 144 (polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon);
Daniel@0 145 });
Daniel@0 146 });
Daniel@0 147 polygons.push(polygon);
Daniel@0 148 }
Daniel@0 149
Daniel@0 150 function exterior(ring) {
Daniel@0 151 return cartesianRingArea(object(topology, {type: "Polygon", arcs: [ring]}).coordinates[0]) > 0; // TODO allow spherical?
Daniel@0 152 }
Daniel@0 153
Daniel@0 154 polygons.forEach(function(polygon) {
Daniel@0 155 if (!polygon._) {
Daniel@0 156 var component = [],
Daniel@0 157 neighbors = [polygon];
Daniel@0 158 polygon._ = 1;
Daniel@0 159 components.push(component);
Daniel@0 160 while (polygon = neighbors.pop()) {
Daniel@0 161 component.push(polygon);
Daniel@0 162 polygon.forEach(function(ring) {
Daniel@0 163 ring.forEach(function(arc) {
Daniel@0 164 polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) {
Daniel@0 165 if (!polygon._) {
Daniel@0 166 polygon._ = 1;
Daniel@0 167 neighbors.push(polygon);
Daniel@0 168 }
Daniel@0 169 });
Daniel@0 170 });
Daniel@0 171 });
Daniel@0 172 }
Daniel@0 173 }
Daniel@0 174 });
Daniel@0 175
Daniel@0 176 polygons.forEach(function(polygon) {
Daniel@0 177 delete polygon._;
Daniel@0 178 });
Daniel@0 179
Daniel@0 180 return {
Daniel@0 181 type: "MultiPolygon",
Daniel@0 182 arcs: components.map(function(polygons) {
Daniel@0 183 var arcs = [];
Daniel@0 184
Daniel@0 185 // Extract the exterior (unique) arcs.
Daniel@0 186 polygons.forEach(function(polygon) {
Daniel@0 187 polygon.forEach(function(ring) {
Daniel@0 188 ring.forEach(function(arc) {
Daniel@0 189 if (polygonsByArc[arc < 0 ? ~arc : arc].length < 2) {
Daniel@0 190 arcs.push(arc);
Daniel@0 191 }
Daniel@0 192 });
Daniel@0 193 });
Daniel@0 194 });
Daniel@0 195
Daniel@0 196 // Stitch the arcs into one or more rings.
Daniel@0 197 arcs = stitchArcs(topology, arcs);
Daniel@0 198
Daniel@0 199 // If more than one ring is returned,
Daniel@0 200 // at most one of these rings can be the exterior;
Daniel@0 201 // this exterior ring has the same winding order
Daniel@0 202 // as any exterior ring in the original polygons.
Daniel@0 203 if ((n = arcs.length) > 1) {
Daniel@0 204 var sgn = exterior(polygons[0][0]);
Daniel@0 205 for (var i = 0, t; i < n; ++i) {
Daniel@0 206 if (sgn === exterior(arcs[i])) {
Daniel@0 207 t = arcs[0], arcs[0] = arcs[i], arcs[i] = t;
Daniel@0 208 break;
Daniel@0 209 }
Daniel@0 210 }
Daniel@0 211 }
Daniel@0 212
Daniel@0 213 return arcs;
Daniel@0 214 })
Daniel@0 215 };
Daniel@0 216 }
Daniel@0 217
Daniel@0 218 function featureOrCollection(topology, o) {
Daniel@0 219 return o.type === "GeometryCollection" ? {
Daniel@0 220 type: "FeatureCollection",
Daniel@0 221 features: o.geometries.map(function(o) { return feature(topology, o); })
Daniel@0 222 } : feature(topology, o);
Daniel@0 223 }
Daniel@0 224
Daniel@0 225 function feature(topology, o) {
Daniel@0 226 var f = {
Daniel@0 227 type: "Feature",
Daniel@0 228 id: o.id,
Daniel@0 229 properties: o.properties || {},
Daniel@0 230 geometry: object(topology, o)
Daniel@0 231 };
Daniel@0 232 if (o.id == null) delete f.id;
Daniel@0 233 return f;
Daniel@0 234 }
Daniel@0 235
Daniel@0 236 function object(topology, o) {
Daniel@0 237 var absolute = transformAbsolute(topology.transform),
Daniel@0 238 arcs = topology.arcs;
Daniel@0 239
Daniel@0 240 function arc(i, points) {
Daniel@0 241 if (points.length) points.pop();
Daniel@0 242 for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length, p; k < n; ++k) {
Daniel@0 243 points.push(p = a[k].slice());
Daniel@0 244 absolute(p, k);
Daniel@0 245 }
Daniel@0 246 if (i < 0) reverse(points, n);
Daniel@0 247 }
Daniel@0 248
Daniel@0 249 function point(p) {
Daniel@0 250 p = p.slice();
Daniel@0 251 absolute(p, 0);
Daniel@0 252 return p;
Daniel@0 253 }
Daniel@0 254
Daniel@0 255 function line(arcs) {
Daniel@0 256 var points = [];
Daniel@0 257 for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points);
Daniel@0 258 if (points.length < 2) points.push(points[0].slice());
Daniel@0 259 return points;
Daniel@0 260 }
Daniel@0 261
Daniel@0 262 function ring(arcs) {
Daniel@0 263 var points = line(arcs);
Daniel@0 264 while (points.length < 4) points.push(points[0].slice());
Daniel@0 265 return points;
Daniel@0 266 }
Daniel@0 267
Daniel@0 268 function polygon(arcs) {
Daniel@0 269 return arcs.map(ring);
Daniel@0 270 }
Daniel@0 271
Daniel@0 272 function geometry(o) {
Daniel@0 273 var t = o.type;
Daniel@0 274 return t === "GeometryCollection" ? {type: t, geometries: o.geometries.map(geometry)}
Daniel@0 275 : t in geometryType ? {type: t, coordinates: geometryType[t](o)}
Daniel@0 276 : null;
Daniel@0 277 }
Daniel@0 278
Daniel@0 279 var geometryType = {
Daniel@0 280 Point: function(o) { return point(o.coordinates); },
Daniel@0 281 MultiPoint: function(o) { return o.coordinates.map(point); },
Daniel@0 282 LineString: function(o) { return line(o.arcs); },
Daniel@0 283 MultiLineString: function(o) { return o.arcs.map(line); },
Daniel@0 284 Polygon: function(o) { return polygon(o.arcs); },
Daniel@0 285 MultiPolygon: function(o) { return o.arcs.map(polygon); }
Daniel@0 286 };
Daniel@0 287
Daniel@0 288 return geometry(o);
Daniel@0 289 }
Daniel@0 290
Daniel@0 291 function reverse(array, n) {
Daniel@0 292 var t, j = array.length, i = j - n; while (i < --j) t = array[i], array[i++] = array[j], array[j] = t;
Daniel@0 293 }
Daniel@0 294
Daniel@0 295 function bisect(a, x) {
Daniel@0 296 var lo = 0, hi = a.length;
Daniel@0 297 while (lo < hi) {
Daniel@0 298 var mid = lo + hi >>> 1;
Daniel@0 299 if (a[mid] < x) lo = mid + 1;
Daniel@0 300 else hi = mid;
Daniel@0 301 }
Daniel@0 302 return lo;
Daniel@0 303 }
Daniel@0 304
Daniel@0 305 function neighbors(objects) {
Daniel@0 306 var indexesByArc = {}, // arc index -> array of object indexes
Daniel@0 307 neighbors = objects.map(function() { return []; });
Daniel@0 308
Daniel@0 309 function line(arcs, i) {
Daniel@0 310 arcs.forEach(function(a) {
Daniel@0 311 if (a < 0) a = ~a;
Daniel@0 312 var o = indexesByArc[a];
Daniel@0 313 if (o) o.push(i);
Daniel@0 314 else indexesByArc[a] = [i];
Daniel@0 315 });
Daniel@0 316 }
Daniel@0 317
Daniel@0 318 function polygon(arcs, i) {
Daniel@0 319 arcs.forEach(function(arc) { line(arc, i); });
Daniel@0 320 }
Daniel@0 321
Daniel@0 322 function geometry(o, i) {
Daniel@0 323 if (o.type === "GeometryCollection") o.geometries.forEach(function(o) { geometry(o, i); });
Daniel@0 324 else if (o.type in geometryType) geometryType[o.type](o.arcs, i);
Daniel@0 325 }
Daniel@0 326
Daniel@0 327 var geometryType = {
Daniel@0 328 LineString: line,
Daniel@0 329 MultiLineString: polygon,
Daniel@0 330 Polygon: polygon,
Daniel@0 331 MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); }
Daniel@0 332 };
Daniel@0 333
Daniel@0 334 objects.forEach(geometry);
Daniel@0 335
Daniel@0 336 for (var i in indexesByArc) {
Daniel@0 337 for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) {
Daniel@0 338 for (var k = j + 1; k < m; ++k) {
Daniel@0 339 var ij = indexes[j], ik = indexes[k], n;
Daniel@0 340 if ((n = neighbors[ij])[i = bisect(n, ik)] !== ik) n.splice(i, 0, ik);
Daniel@0 341 if ((n = neighbors[ik])[i = bisect(n, ij)] !== ij) n.splice(i, 0, ij);
Daniel@0 342 }
Daniel@0 343 }
Daniel@0 344 }
Daniel@0 345
Daniel@0 346 return neighbors;
Daniel@0 347 }
Daniel@0 348
Daniel@0 349 function presimplify(topology, triangleArea) {
Daniel@0 350 var absolute = transformAbsolute(topology.transform),
Daniel@0 351 relative = transformRelative(topology.transform),
Daniel@0 352 heap = minAreaHeap();
Daniel@0 353
Daniel@0 354 if (!triangleArea) triangleArea = cartesianTriangleArea;
Daniel@0 355
Daniel@0 356 topology.arcs.forEach(function(arc) {
Daniel@0 357 var triangles = [],
Daniel@0 358 maxArea = 0,
Daniel@0 359 triangle;
Daniel@0 360
Daniel@0 361 // To store each point’s effective area, we create a new array rather than
Daniel@0 362 // extending the passed-in point to workaround a Chrome/V8 bug (getting
Daniel@0 363 // stuck in smi mode). For midpoints, the initial effective area of
Daniel@0 364 // Infinity will be computed in the next step.
Daniel@0 365 for (var i = 0, n = arc.length, p; i < n; ++i) {
Daniel@0 366 p = arc[i];
Daniel@0 367 absolute(arc[i] = [p[0], p[1], Infinity], i);
Daniel@0 368 }
Daniel@0 369
Daniel@0 370 for (var i = 1, n = arc.length - 1; i < n; ++i) {
Daniel@0 371 triangle = arc.slice(i - 1, i + 2);
Daniel@0 372 triangle[1][2] = triangleArea(triangle);
Daniel@0 373 triangles.push(triangle);
Daniel@0 374 heap.push(triangle);
Daniel@0 375 }
Daniel@0 376
Daniel@0 377 for (var i = 0, n = triangles.length; i < n; ++i) {
Daniel@0 378 triangle = triangles[i];
Daniel@0 379 triangle.previous = triangles[i - 1];
Daniel@0 380 triangle.next = triangles[i + 1];
Daniel@0 381 }
Daniel@0 382
Daniel@0 383 while (triangle = heap.pop()) {
Daniel@0 384 var previous = triangle.previous,
Daniel@0 385 next = triangle.next;
Daniel@0 386
Daniel@0 387 // If the area of the current point is less than that of the previous point
Daniel@0 388 // to be eliminated, use the latter's area instead. This ensures that the
Daniel@0 389 // current point cannot be eliminated without eliminating previously-
Daniel@0 390 // eliminated points.
Daniel@0 391 if (triangle[1][2] < maxArea) triangle[1][2] = maxArea;
Daniel@0 392 else maxArea = triangle[1][2];
Daniel@0 393
Daniel@0 394 if (previous) {
Daniel@0 395 previous.next = next;
Daniel@0 396 previous[2] = triangle[2];
Daniel@0 397 update(previous);
Daniel@0 398 }
Daniel@0 399
Daniel@0 400 if (next) {
Daniel@0 401 next.previous = previous;
Daniel@0 402 next[0] = triangle[0];
Daniel@0 403 update(next);
Daniel@0 404 }
Daniel@0 405 }
Daniel@0 406
Daniel@0 407 arc.forEach(relative);
Daniel@0 408 });
Daniel@0 409
Daniel@0 410 function update(triangle) {
Daniel@0 411 heap.remove(triangle);
Daniel@0 412 triangle[1][2] = triangleArea(triangle);
Daniel@0 413 heap.push(triangle);
Daniel@0 414 }
Daniel@0 415
Daniel@0 416 return topology;
Daniel@0 417 };
Daniel@0 418
Daniel@0 419 function cartesianRingArea(ring) {
Daniel@0 420 var i = -1,
Daniel@0 421 n = ring.length,
Daniel@0 422 a,
Daniel@0 423 b = ring[n - 1],
Daniel@0 424 area = 0;
Daniel@0 425
Daniel@0 426 while (++i < n) {
Daniel@0 427 a = b;
Daniel@0 428 b = ring[i];
Daniel@0 429 area += a[0] * b[1] - a[1] * b[0];
Daniel@0 430 }
Daniel@0 431
Daniel@0 432 return area * .5;
Daniel@0 433 }
Daniel@0 434
Daniel@0 435 function cartesianTriangleArea(triangle) {
Daniel@0 436 var a = triangle[0], b = triangle[1], c = triangle[2];
Daniel@0 437 return Math.abs((a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]));
Daniel@0 438 }
Daniel@0 439
Daniel@0 440 function compareArea(a, b) {
Daniel@0 441 return a[1][2] - b[1][2];
Daniel@0 442 }
Daniel@0 443
Daniel@0 444 function minAreaHeap() {
Daniel@0 445 var heap = {},
Daniel@0 446 array = [],
Daniel@0 447 size = 0;
Daniel@0 448
Daniel@0 449 heap.push = function(object) {
Daniel@0 450 up(array[object._ = size] = object, size++);
Daniel@0 451 return size;
Daniel@0 452 };
Daniel@0 453
Daniel@0 454 heap.pop = function() {
Daniel@0 455 if (size <= 0) return;
Daniel@0 456 var removed = array[0], object;
Daniel@0 457 if (--size > 0) object = array[size], down(array[object._ = 0] = object, 0);
Daniel@0 458 return removed;
Daniel@0 459 };
Daniel@0 460
Daniel@0 461 heap.remove = function(removed) {
Daniel@0 462 var i = removed._, object;
Daniel@0 463 if (array[i] !== removed) return; // invalid request
Daniel@0 464 if (i !== --size) object = array[size], (compareArea(object, removed) < 0 ? up : down)(array[object._ = i] = object, i);
Daniel@0 465 return i;
Daniel@0 466 };
Daniel@0 467
Daniel@0 468 function up(object, i) {
Daniel@0 469 while (i > 0) {
Daniel@0 470 var j = ((i + 1) >> 1) - 1,
Daniel@0 471 parent = array[j];
Daniel@0 472 if (compareArea(object, parent) >= 0) break;
Daniel@0 473 array[parent._ = i] = parent;
Daniel@0 474 array[object._ = i = j] = object;
Daniel@0 475 }
Daniel@0 476 }
Daniel@0 477
Daniel@0 478 function down(object, i) {
Daniel@0 479 while (true) {
Daniel@0 480 var r = (i + 1) << 1,
Daniel@0 481 l = r - 1,
Daniel@0 482 j = i,
Daniel@0 483 child = array[j];
Daniel@0 484 if (l < size && compareArea(array[l], child) < 0) child = array[j = l];
Daniel@0 485 if (r < size && compareArea(array[r], child) < 0) child = array[j = r];
Daniel@0 486 if (j === i) break;
Daniel@0 487 array[child._ = i] = child;
Daniel@0 488 array[object._ = i = j] = object;
Daniel@0 489 }
Daniel@0 490 }
Daniel@0 491
Daniel@0 492 return heap;
Daniel@0 493 }
Daniel@0 494
Daniel@0 495 function transformAbsolute(transform) {
Daniel@0 496 if (!transform) return noop;
Daniel@0 497 var x0,
Daniel@0 498 y0,
Daniel@0 499 kx = transform.scale[0],
Daniel@0 500 ky = transform.scale[1],
Daniel@0 501 dx = transform.translate[0],
Daniel@0 502 dy = transform.translate[1];
Daniel@0 503 return function(point, i) {
Daniel@0 504 if (!i) x0 = y0 = 0;
Daniel@0 505 point[0] = (x0 += point[0]) * kx + dx;
Daniel@0 506 point[1] = (y0 += point[1]) * ky + dy;
Daniel@0 507 };
Daniel@0 508 }
Daniel@0 509
Daniel@0 510 function transformRelative(transform) {
Daniel@0 511 if (!transform) return noop;
Daniel@0 512 var x0,
Daniel@0 513 y0,
Daniel@0 514 kx = transform.scale[0],
Daniel@0 515 ky = transform.scale[1],
Daniel@0 516 dx = transform.translate[0],
Daniel@0 517 dy = transform.translate[1];
Daniel@0 518 return function(point, i) {
Daniel@0 519 if (!i) x0 = y0 = 0;
Daniel@0 520 var x1 = (point[0] - dx) / kx | 0,
Daniel@0 521 y1 = (point[1] - dy) / ky | 0;
Daniel@0 522 point[0] = x1 - x0;
Daniel@0 523 point[1] = y1 - y0;
Daniel@0 524 x0 = x1;
Daniel@0 525 y0 = y1;
Daniel@0 526 };
Daniel@0 527 }
Daniel@0 528
Daniel@0 529 function noop() {}
Daniel@0 530
Daniel@0 531 if (typeof define === "function" && define.amd) define(topojson);
Daniel@0 532 else if (typeof module === "object" && module.exports) module.exports = topojson;
Daniel@0 533 else this.topojson = topojson;
Daniel@0 534 }();