mapshaper 0.6.107 → 0.6.109

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/mapshaper.js CHANGED
@@ -3193,7 +3193,8 @@
3193
3193
  var den = determinant2D(bx - ax, by - ay, dx - cx, dy - cy);
3194
3194
  var m = orient2D(cx, cy, dx, dy, ax, ay) / den;
3195
3195
  var p = [ax + m * (bx - ax), ay + m * (by - ay)];
3196
- if (Math.abs(den) < 1e-18) {
3196
+ if (Math.abs(den) < 1e-25) {
3197
+ // changed from 1e-18 to 1e-25 (see geom ex1)
3197
3198
  // assume that collinear and near-collinear segment intersections have been
3198
3199
  // accounted for already.
3199
3200
  // TODO: is this a valid assumption?
@@ -13545,14 +13546,8 @@
13545
13546
  function getBoundsPrecisionForDisplay(bbox) {
13546
13547
  var w = Math.abs(bbox[2] - bbox[0]),
13547
13548
  h = Math.abs(bbox[3] - bbox[1]),
13548
- // switched to max bound, based on experience with shift-drag box info
13549
- // range = Math.min(w, h) + 1e-8,
13550
- range = Math.max(w, h) + 1e-8,
13551
- digits = 0;
13552
- while (range < 2000 && digits < 1) {
13553
- range *= 10;
13554
- digits++;
13555
- }
13549
+ range = (w + h) / 2 + 1e-8,
13550
+ digits = Math.max(0, Math.round(3 - Math.log10(range)));
13556
13551
  return digits;
13557
13552
  }
13558
13553
 
@@ -16796,6 +16791,7 @@
16796
16791
  arcs.flatten();
16797
16792
 
16798
16793
  var changed = snapAndCut(dataset, snapDist);
16794
+
16799
16795
  // Detect topology again if coordinates have changed
16800
16796
  if (changed || opts.rebuild_topology) {
16801
16797
  buildTopology(dataset);
@@ -16834,6 +16830,7 @@
16834
16830
  if (cutCount > 0 || snapCount > 0 || dupeCount > 0) {
16835
16831
  coordsHaveChanged = true;
16836
16832
  }
16833
+
16837
16834
  // perform a second snap + cut pass if needed
16838
16835
  if (cutCount > 0) {
16839
16836
  cutCount = 0;
@@ -16882,17 +16879,6 @@
16882
16879
  }
16883
16880
  }
16884
16881
 
16885
- // Divides a collection of arcs at points where arc paths cross each other
16886
- // Returns array for remapping arc ids
16887
- function divideArcs(arcs, opts) {
16888
- var points = findClippingPoints(arcs, opts);
16889
- // TODO: avoid the following if no points need to be added
16890
- var map = insertCutPoints(points, arcs);
16891
- // segment-point intersections currently create duplicate points
16892
- // TODO: consider dedup in a later cleanup pass?
16893
- // arcs.dedupCoords();
16894
- return map;
16895
- }
16896
16882
 
16897
16883
  function cutPathsAtIntersections(dataset, opts) {
16898
16884
  var n = dataset.arcs.getPointCount();
@@ -16911,6 +16897,25 @@
16911
16897
  });
16912
16898
  }
16913
16899
 
16900
+
16901
+ // Divides a collection of arcs at points where arc paths cross each other
16902
+ // Returns array for remapping arc ids
16903
+ function divideArcs(arcs, opts) {
16904
+ var points = findClippingPoints(arcs, opts);
16905
+ // TODO: avoid the following if no points need to be added
16906
+ var map = insertCutPoints(points, arcs);
16907
+ // segment-point intersections currently create duplicate points
16908
+ // TODO: consider dedup in a later cleanup pass?
16909
+ // arcs.dedupCoords();
16910
+ return map;
16911
+ }
16912
+
16913
+ function findClippingPoints(arcs, opts) {
16914
+ var intersections = findSegmentIntersections(arcs, opts),
16915
+ data = arcs.getVertexData();
16916
+ return convertIntersectionsToCutPoints(intersections, data.xx, data.yy);
16917
+ }
16918
+
16914
16919
  // Inserts array of cutting points into an ArcCollection
16915
16920
  // Returns array for remapping arc ids
16916
16921
  function insertCutPoints(unfilteredPoints, arcs) {
@@ -17043,12 +17048,6 @@
17043
17048
  return filtered;
17044
17049
  }
17045
17050
 
17046
- function findClippingPoints(arcs, opts) {
17047
- var intersections = findSegmentIntersections(arcs, opts),
17048
- data = arcs.getVertexData();
17049
- return convertIntersectionsToCutPoints(intersections, data.xx, data.yy);
17050
- }
17051
-
17052
17051
  var IntersectionCuts = /*#__PURE__*/Object.freeze({
17053
17052
  __proto__: null,
17054
17053
  addIntersectionCuts: addIntersectionCuts,
@@ -25446,6 +25445,9 @@ ${svg}
25446
25445
  .option('calc', calcOpt)
25447
25446
  .option('name', nameOpt)
25448
25447
  .option('target', targetOpt)
25448
+ .option('no-snap', { // undocumented, for debugging
25449
+ type: 'flag'
25450
+ })
25449
25451
  .option('no-replace', noReplaceOpt);
25450
25452
 
25451
25453
  parser.command('point-grid')
@@ -30101,8 +30103,6 @@ ${svg}
30101
30103
  const detright = (ax - cx) * (by - cy);
30102
30104
  const det = detleft - detright;
30103
30105
 
30104
- if (detleft === 0 || detright === 0 || (detleft > 0) !== (detright > 0)) return det;
30105
-
30106
30106
  const detsum = Math.abs(detleft + detright);
30107
30107
  if (Math.abs(det) >= ccwerrboundA * detsum) return det;
30108
30108
 
@@ -46044,7 +46044,7 @@ ${svg}
46044
46044
  });
46045
46045
  }
46046
46046
 
46047
- var version = "0.6.107";
46047
+ var version = "0.6.109";
46048
46048
 
46049
46049
  // Parse command line args into commands and run them
46050
46050
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.6.107",
3
+ "version": "0.6.109",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -69,6 +69,7 @@
69
69
  "csv-spectrum": "^1.0.0",
70
70
  "eslint": "^8.16.0",
71
71
  "mocha": "^10.2.0",
72
+ "robust-predicates": "^3.0.2",
72
73
  "rollup": "^4.44.1",
73
74
  "rollup-plugin-polyfill-node": "^0.13.0",
74
75
  "shell-quote": "^1.7.4",
package/www/index.html CHANGED
@@ -244,7 +244,6 @@ of more acute angles are
244
244
  preferentially removed, for
245
245
  a smoother appearance.</div></div></div></div>
246
246
 
247
-
248
247
  </div> <!-- option menu -->
249
248
 
250
249
  <div>
@@ -2726,11 +2726,12 @@
2726
2726
  // p1: [x, y] coords
2727
2727
  // p2: [x, y] coords offset by 1x1 pixel
2728
2728
  function formatCoordsForDisplay(p1, p2) {
2729
+ var maxD = 13;
2729
2730
  var dx = Math.abs(p1[0] - p2[0]);
2730
2731
  var dy = Math.abs(p1[1] - p2[1]);
2731
2732
  var offs = (dx + dy) / 2;
2732
2733
  var decimals = 0;
2733
- while (offs < 1 && decimals < 6) {
2734
+ while (offs < 1 && decimals <= maxD) {
2734
2735
  offs *= 10;
2735
2736
  decimals++;
2736
2737
  }
@@ -4757,6 +4758,7 @@
4757
4758
  if (_open) close();
4758
4759
  menu.empty();
4759
4760
 
4761
+
4760
4762
  if (openMenu && openMenu != this) {
4761
4763
  openMenu.close();
4762
4764
  }
@@ -11560,6 +11562,7 @@
11560
11562
  // stop zooming before rounding errors become too obvious
11561
11563
  function maxScale() {
11562
11564
  var minPixelScale = 1e-16;
11565
+ // var minPixelScale = 1e-17; // gets jumpy
11563
11566
  var xmax = maxAbs(_fullBounds.xmin, _fullBounds.xmax, _fullBounds.centerX());
11564
11567
  var ymax = maxAbs(_fullBounds.ymin, _fullBounds.ymax, _fullBounds.centerY());
11565
11568
  var xscale = _fullBounds.width() / _position.width() / xmax / minPixelScale;
@@ -11906,9 +11909,8 @@
11906
11909
  var iter = new internal.ShapeIter(arcs);
11907
11910
  var t = getScaledTransform(_ext);
11908
11911
  var bounds = _ext.getBounds();
11909
- var radius = (style.strokeWidth > 2 ? style.strokeWidth * 0.9 : 1.8) * GUI.getPixelRatio() * getScaledLineScale(_ext, style);
11912
+ var radius = (style.strokeWidth > 2 ? style.strokeWidth * 1 : 2.2) * GUI.getPixelRatio() * getScaledLineScale(_ext, style);
11910
11913
  var color = style.strokeColor || 'black';
11911
-
11912
11914
  var i, j, p;
11913
11915
  _ctx.beginPath();
11914
11916
  _ctx.fillStyle = color;
@@ -12560,7 +12562,7 @@
12560
12562
  var self = new EventDispatcher();
12561
12563
  var box = new HighlightBox(gui, {name: 'box-tool', persistent: true, handles: true, draggable: true});
12562
12564
  var popup = gui.container.findChild('.box-tool-options');
12563
- var coords = popup.findChild('.box-coords');
12565
+ var coords = popup.findChild('.box-coords').hide();
12564
12566
  var _on = false;
12565
12567
  var instructionsShown = false;
12566
12568
  var alert;
@@ -12994,6 +12996,10 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
12994
12996
  var fullBounds;
12995
12997
  var needReset;
12996
12998
 
12999
+ if (!updated) {
13000
+ return; // e.g. if command is run in console before data is loaded
13001
+ }
13002
+
12997
13003
  if (arcsMayHaveChanged(e.flags)) {
12998
13004
  // regenerate filtered arcs the next time they are needed for rendering
12999
13005
  // delete e.dataset.gui.displayArcs
@@ -13099,15 +13105,17 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13099
13105
  // add margin
13100
13106
  // use larger margin for small sizes
13101
13107
  var widthPx = _ext.width();
13102
- var marginPct = widthPx < 700 && 3.5 || widthPx < 800 && 3 || 2.5;
13108
+ var marginPct = widthPx < 700 && 4.5 || widthPx < 800 && 4 || 3.5;
13103
13109
  if (isTableView()) {
13104
13110
  var n = internal.getFeatureCount(_activeLyr);
13105
13111
  marginPct = n < 5 && 20 || n < 100 && 10 || 4;
13106
13112
  }
13107
13113
  b.scale(1 + marginPct / 100 * 2);
13108
13114
 
13109
- // Inflate display bounding box by a tiny amount (gives extent to single-point layers and collapsed shapes)
13110
- b.padBounds(1e-4, 1e-4, 1e-4, 1e-4);
13115
+ // Inflate display bounding box of single-point layers and collapsed shapes a bit
13116
+ if (b.width() === 0 || b.height() === 0) {
13117
+ b.padBounds(1e-4, 1e-4, 1e-4, 1e-4);
13118
+ }
13111
13119
  return b;
13112
13120
  }
13113
13121
 
package/www/mapshaper.js CHANGED
@@ -3193,7 +3193,8 @@
3193
3193
  var den = determinant2D(bx - ax, by - ay, dx - cx, dy - cy);
3194
3194
  var m = orient2D(cx, cy, dx, dy, ax, ay) / den;
3195
3195
  var p = [ax + m * (bx - ax), ay + m * (by - ay)];
3196
- if (Math.abs(den) < 1e-18) {
3196
+ if (Math.abs(den) < 1e-25) {
3197
+ // changed from 1e-18 to 1e-25 (see geom ex1)
3197
3198
  // assume that collinear and near-collinear segment intersections have been
3198
3199
  // accounted for already.
3199
3200
  // TODO: is this a valid assumption?
@@ -13545,14 +13546,8 @@
13545
13546
  function getBoundsPrecisionForDisplay(bbox) {
13546
13547
  var w = Math.abs(bbox[2] - bbox[0]),
13547
13548
  h = Math.abs(bbox[3] - bbox[1]),
13548
- // switched to max bound, based on experience with shift-drag box info
13549
- // range = Math.min(w, h) + 1e-8,
13550
- range = Math.max(w, h) + 1e-8,
13551
- digits = 0;
13552
- while (range < 2000 && digits < 1) {
13553
- range *= 10;
13554
- digits++;
13555
- }
13549
+ range = (w + h) / 2 + 1e-8,
13550
+ digits = Math.max(0, Math.round(3 - Math.log10(range)));
13556
13551
  return digits;
13557
13552
  }
13558
13553
 
@@ -16796,6 +16791,7 @@
16796
16791
  arcs.flatten();
16797
16792
 
16798
16793
  var changed = snapAndCut(dataset, snapDist);
16794
+
16799
16795
  // Detect topology again if coordinates have changed
16800
16796
  if (changed || opts.rebuild_topology) {
16801
16797
  buildTopology(dataset);
@@ -16834,6 +16830,7 @@
16834
16830
  if (cutCount > 0 || snapCount > 0 || dupeCount > 0) {
16835
16831
  coordsHaveChanged = true;
16836
16832
  }
16833
+
16837
16834
  // perform a second snap + cut pass if needed
16838
16835
  if (cutCount > 0) {
16839
16836
  cutCount = 0;
@@ -16882,17 +16879,6 @@
16882
16879
  }
16883
16880
  }
16884
16881
 
16885
- // Divides a collection of arcs at points where arc paths cross each other
16886
- // Returns array for remapping arc ids
16887
- function divideArcs(arcs, opts) {
16888
- var points = findClippingPoints(arcs, opts);
16889
- // TODO: avoid the following if no points need to be added
16890
- var map = insertCutPoints(points, arcs);
16891
- // segment-point intersections currently create duplicate points
16892
- // TODO: consider dedup in a later cleanup pass?
16893
- // arcs.dedupCoords();
16894
- return map;
16895
- }
16896
16882
 
16897
16883
  function cutPathsAtIntersections(dataset, opts) {
16898
16884
  var n = dataset.arcs.getPointCount();
@@ -16911,6 +16897,25 @@
16911
16897
  });
16912
16898
  }
16913
16899
 
16900
+
16901
+ // Divides a collection of arcs at points where arc paths cross each other
16902
+ // Returns array for remapping arc ids
16903
+ function divideArcs(arcs, opts) {
16904
+ var points = findClippingPoints(arcs, opts);
16905
+ // TODO: avoid the following if no points need to be added
16906
+ var map = insertCutPoints(points, arcs);
16907
+ // segment-point intersections currently create duplicate points
16908
+ // TODO: consider dedup in a later cleanup pass?
16909
+ // arcs.dedupCoords();
16910
+ return map;
16911
+ }
16912
+
16913
+ function findClippingPoints(arcs, opts) {
16914
+ var intersections = findSegmentIntersections(arcs, opts),
16915
+ data = arcs.getVertexData();
16916
+ return convertIntersectionsToCutPoints(intersections, data.xx, data.yy);
16917
+ }
16918
+
16914
16919
  // Inserts array of cutting points into an ArcCollection
16915
16920
  // Returns array for remapping arc ids
16916
16921
  function insertCutPoints(unfilteredPoints, arcs) {
@@ -17043,12 +17048,6 @@
17043
17048
  return filtered;
17044
17049
  }
17045
17050
 
17046
- function findClippingPoints(arcs, opts) {
17047
- var intersections = findSegmentIntersections(arcs, opts),
17048
- data = arcs.getVertexData();
17049
- return convertIntersectionsToCutPoints(intersections, data.xx, data.yy);
17050
- }
17051
-
17052
17051
  var IntersectionCuts = /*#__PURE__*/Object.freeze({
17053
17052
  __proto__: null,
17054
17053
  addIntersectionCuts: addIntersectionCuts,
@@ -25446,6 +25445,9 @@ ${svg}
25446
25445
  .option('calc', calcOpt)
25447
25446
  .option('name', nameOpt)
25448
25447
  .option('target', targetOpt)
25448
+ .option('no-snap', { // undocumented, for debugging
25449
+ type: 'flag'
25450
+ })
25449
25451
  .option('no-replace', noReplaceOpt);
25450
25452
 
25451
25453
  parser.command('point-grid')
@@ -30101,8 +30103,6 @@ ${svg}
30101
30103
  const detright = (ax - cx) * (by - cy);
30102
30104
  const det = detleft - detright;
30103
30105
 
30104
- if (detleft === 0 || detright === 0 || (detleft > 0) !== (detright > 0)) return det;
30105
-
30106
30106
  const detsum = Math.abs(detleft + detright);
30107
30107
  if (Math.abs(det) >= ccwerrboundA * detsum) return det;
30108
30108
 
@@ -46044,7 +46044,7 @@ ${svg}
46044
46044
  });
46045
46045
  }
46046
46046
 
46047
- var version = "0.6.107";
46047
+ var version = "0.6.109";
46048
46048
 
46049
46049
  // Parse command line args into commands and run them
46050
46050
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.