mapshaper 0.6.108 → 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?
@@ -16790,6 +16791,7 @@
16790
16791
  arcs.flatten();
16791
16792
 
16792
16793
  var changed = snapAndCut(dataset, snapDist);
16794
+
16793
16795
  // Detect topology again if coordinates have changed
16794
16796
  if (changed || opts.rebuild_topology) {
16795
16797
  buildTopology(dataset);
@@ -16828,6 +16830,7 @@
16828
16830
  if (cutCount > 0 || snapCount > 0 || dupeCount > 0) {
16829
16831
  coordsHaveChanged = true;
16830
16832
  }
16833
+
16831
16834
  // perform a second snap + cut pass if needed
16832
16835
  if (cutCount > 0) {
16833
16836
  cutCount = 0;
@@ -16876,17 +16879,6 @@
16876
16879
  }
16877
16880
  }
16878
16881
 
16879
- // Divides a collection of arcs at points where arc paths cross each other
16880
- // Returns array for remapping arc ids
16881
- function divideArcs(arcs, opts) {
16882
- var points = findClippingPoints(arcs, opts);
16883
- // TODO: avoid the following if no points need to be added
16884
- var map = insertCutPoints(points, arcs);
16885
- // segment-point intersections currently create duplicate points
16886
- // TODO: consider dedup in a later cleanup pass?
16887
- // arcs.dedupCoords();
16888
- return map;
16889
- }
16890
16882
 
16891
16883
  function cutPathsAtIntersections(dataset, opts) {
16892
16884
  var n = dataset.arcs.getPointCount();
@@ -16905,6 +16897,25 @@
16905
16897
  });
16906
16898
  }
16907
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
+
16908
16919
  // Inserts array of cutting points into an ArcCollection
16909
16920
  // Returns array for remapping arc ids
16910
16921
  function insertCutPoints(unfilteredPoints, arcs) {
@@ -17037,12 +17048,6 @@
17037
17048
  return filtered;
17038
17049
  }
17039
17050
 
17040
- function findClippingPoints(arcs, opts) {
17041
- var intersections = findSegmentIntersections(arcs, opts),
17042
- data = arcs.getVertexData();
17043
- return convertIntersectionsToCutPoints(intersections, data.xx, data.yy);
17044
- }
17045
-
17046
17051
  var IntersectionCuts = /*#__PURE__*/Object.freeze({
17047
17052
  __proto__: null,
17048
17053
  addIntersectionCuts: addIntersectionCuts,
@@ -25440,6 +25445,9 @@ ${svg}
25440
25445
  .option('calc', calcOpt)
25441
25446
  .option('name', nameOpt)
25442
25447
  .option('target', targetOpt)
25448
+ .option('no-snap', { // undocumented, for debugging
25449
+ type: 'flag'
25450
+ })
25443
25451
  .option('no-replace', noReplaceOpt);
25444
25452
 
25445
25453
  parser.command('point-grid')
@@ -30095,8 +30103,6 @@ ${svg}
30095
30103
  const detright = (ax - cx) * (by - cy);
30096
30104
  const det = detleft - detright;
30097
30105
 
30098
- if (detleft === 0 || detright === 0 || (detleft > 0) !== (detright > 0)) return det;
30099
-
30100
30106
  const detsum = Math.abs(detleft + detright);
30101
30107
  if (Math.abs(det) >= ccwerrboundA * detsum) return det;
30102
30108
 
@@ -46038,7 +46044,7 @@ ${svg}
46038
46044
  });
46039
46045
  }
46040
46046
 
46041
- var version = "0.6.108";
46047
+ var version = "0.6.109";
46042
46048
 
46043
46049
  // Parse command line args into commands and run them
46044
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.108",
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",
@@ -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;
@@ -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?
@@ -16790,6 +16791,7 @@
16790
16791
  arcs.flatten();
16791
16792
 
16792
16793
  var changed = snapAndCut(dataset, snapDist);
16794
+
16793
16795
  // Detect topology again if coordinates have changed
16794
16796
  if (changed || opts.rebuild_topology) {
16795
16797
  buildTopology(dataset);
@@ -16828,6 +16830,7 @@
16828
16830
  if (cutCount > 0 || snapCount > 0 || dupeCount > 0) {
16829
16831
  coordsHaveChanged = true;
16830
16832
  }
16833
+
16831
16834
  // perform a second snap + cut pass if needed
16832
16835
  if (cutCount > 0) {
16833
16836
  cutCount = 0;
@@ -16876,17 +16879,6 @@
16876
16879
  }
16877
16880
  }
16878
16881
 
16879
- // Divides a collection of arcs at points where arc paths cross each other
16880
- // Returns array for remapping arc ids
16881
- function divideArcs(arcs, opts) {
16882
- var points = findClippingPoints(arcs, opts);
16883
- // TODO: avoid the following if no points need to be added
16884
- var map = insertCutPoints(points, arcs);
16885
- // segment-point intersections currently create duplicate points
16886
- // TODO: consider dedup in a later cleanup pass?
16887
- // arcs.dedupCoords();
16888
- return map;
16889
- }
16890
16882
 
16891
16883
  function cutPathsAtIntersections(dataset, opts) {
16892
16884
  var n = dataset.arcs.getPointCount();
@@ -16905,6 +16897,25 @@
16905
16897
  });
16906
16898
  }
16907
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
+
16908
16919
  // Inserts array of cutting points into an ArcCollection
16909
16920
  // Returns array for remapping arc ids
16910
16921
  function insertCutPoints(unfilteredPoints, arcs) {
@@ -17037,12 +17048,6 @@
17037
17048
  return filtered;
17038
17049
  }
17039
17050
 
17040
- function findClippingPoints(arcs, opts) {
17041
- var intersections = findSegmentIntersections(arcs, opts),
17042
- data = arcs.getVertexData();
17043
- return convertIntersectionsToCutPoints(intersections, data.xx, data.yy);
17044
- }
17045
-
17046
17051
  var IntersectionCuts = /*#__PURE__*/Object.freeze({
17047
17052
  __proto__: null,
17048
17053
  addIntersectionCuts: addIntersectionCuts,
@@ -25440,6 +25445,9 @@ ${svg}
25440
25445
  .option('calc', calcOpt)
25441
25446
  .option('name', nameOpt)
25442
25447
  .option('target', targetOpt)
25448
+ .option('no-snap', { // undocumented, for debugging
25449
+ type: 'flag'
25450
+ })
25443
25451
  .option('no-replace', noReplaceOpt);
25444
25452
 
25445
25453
  parser.command('point-grid')
@@ -30095,8 +30103,6 @@ ${svg}
30095
30103
  const detright = (ax - cx) * (by - cy);
30096
30104
  const det = detleft - detright;
30097
30105
 
30098
- if (detleft === 0 || detright === 0 || (detleft > 0) !== (detright > 0)) return det;
30099
-
30100
30106
  const detsum = Math.abs(detleft + detright);
30101
30107
  if (Math.abs(det) >= ccwerrboundA * detsum) return det;
30102
30108
 
@@ -46038,7 +46044,7 @@ ${svg}
46038
46044
  });
46039
46045
  }
46040
46046
 
46041
- var version = "0.6.108";
46047
+ var version = "0.6.109";
46042
46048
 
46043
46049
  // Parse command line args into commands and run them
46044
46050
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.