mapshaper 0.5.117 → 0.6.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.5.117",
3
+ "version": "0.6.2",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -9,6 +9,7 @@
9
9
  "cartography",
10
10
  "simplification",
11
11
  "topology",
12
+ "csv",
12
13
  "gis"
13
14
  ],
14
15
  "author": "Matthew Bloch <masiyou@gmail.com>",
@@ -19,16 +20,15 @@
19
20
  "url": "https://github.com/mbloch/mapshaper"
20
21
  },
21
22
  "engines": {
22
- "node": ">=6.0.0"
23
+ "node": ">=12.0.0"
23
24
  },
24
25
  "scripts": {
25
- "test": "mocha -r esm --parallel --jobs 4 --check-leaks -R dot",
26
+ "test": "mocha test",
26
27
  "build": "rollup --config",
27
- "prepublishOnly": "npm test; ./pre-publish",
28
+ "lint": "eslint --ext mjs src/",
29
+ "prepublishOnly": "npm lint; npm test; ./pre-publish",
28
30
  "postpublish": "./release_web_ui; ./release_github_version",
29
- "browserify_old": "browserify -r sync-request -r mproj -r buffer -r iconv-lite -r fs -r flatbush -r rw -r path -r d3-scale-chromatic -r d3-color -r d3-interpolate -o www/modules.js",
30
- "browserify": "browserify -r sync-request -r mproj -r buffer -r iconv-lite -r fs -r flatbush -r rw -r path -r d3-scale-chromatic -r d3-color -r d3-interpolate -r kdbush -r @tmcw/togeojson -o www/modules.js",
31
- "watch": "rollup --config --watch",
31
+ "browserify": "browserify -r sync-request -r mproj -r buffer -r iconv-lite -r fs -r flatbush -r rw -r path -r kdbush -r @tmcw/togeojson -o www/modules.js",
32
32
  "dev": "rollup --config --watch"
33
33
  },
34
34
  "main": "./mapshaper.js",
@@ -50,7 +50,7 @@
50
50
  "delaunator": "^5.0.0",
51
51
  "flatbush": "^3.2.1",
52
52
  "geokdbush": "^1.1.0",
53
- "iconv-lite": "0.4.24",
53
+ "iconv-lite": "^0.6.3",
54
54
  "kdbush": "^3.0.0",
55
55
  "mproj": "0.0.35",
56
56
  "opn": "^5.3.0",
@@ -59,16 +59,24 @@
59
59
  "tinyqueue": "^2.0.3"
60
60
  },
61
61
  "devDependencies": {
62
- "@rollup/plugin-node-resolve": "^13.0.6",
62
+ "@rollup/plugin-node-resolve": "^13.3.0",
63
63
  "browserify": "^17.0.0",
64
64
  "csv-spectrum": "^1.0.0",
65
- "deep-eql": ">=0.1.3",
66
- "esm": "^3.2.25",
67
- "mocha": "^8.4.0",
68
- "rollup": "^2.60.0",
65
+ "eslint": "^8.16.0",
66
+ "mocha": "^10.0.0",
67
+ "rollup": "^2.73.0",
69
68
  "shell-quote": "^1.6.1",
70
69
  "underscore": "^1.13.1"
71
70
  },
71
+ "mocha": {
72
+ "reporter": "dot",
73
+ "node-option": [
74
+ "experimental-specifier-resolution=node"
75
+ ],
76
+ "check-leaks": true,
77
+ "parallel": true,
78
+ "jobs": 4
79
+ },
72
80
  "bin": {
73
81
  "mapshaper": "./bin/mapshaper",
74
82
  "mapshaper-gui": "./bin/mapshaper-gui",
package/www/elements.css CHANGED
@@ -67,10 +67,10 @@ div.tip {
67
67
  z-index: 500;
68
68
  cursor: pointer;
69
69
  text-align: center;
70
- font-size: 13px;
70
+ font-size: 14px;
71
71
  line-height: 1;
72
72
  font-weight: normal;
73
- color: #799FCB;
73
+ color: #1385B7;
74
74
  }
75
75
 
76
76
  .tip-button .tip-anchor {
Binary file
package/www/index.html CHANGED
@@ -130,7 +130,8 @@
130
130
 
131
131
  <div class="export-options main-area popup-dialog">
132
132
  <div class="info-box">
133
- <h3>Export menu</h3>
133
+ <div class="close2-btn"></div>
134
+ <h3>Export options</h3>
134
135
  <div style="height:3px"></div>
135
136
  <div class=export-layers>
136
137
  <h4 class="menu-title">Layers</h4>
@@ -140,22 +141,23 @@
140
141
  <div class="export-formats option-menu">
141
142
  </div>
142
143
 
143
- <div class="option-menu"><input type="text" class="advanced-options" placeholder="export options" /><div class="tip-button">?<div class="tip-anchor">
144
+ <div class="option-menu"><input type="text" class="advanced-options" placeholder="command line options" /><div class="tip-button">?<div class="tip-anchor">
144
145
  <div class="tip">Enter options from the command line interface for the -o command. Examples: "bbox" "no-quantization"
145
146
  "precision=0.001"</div></div></div></div>
146
- <div class="cancel-btn btn dialog-btn">Cancel</div>
147
+ <!-- <div class="cancel-btn btn dialog-btn">Cancel</div> -->
147
148
  <div class="save-btn btn dialog-btn">Export</div>
148
149
  </div>
149
150
  </div>
150
151
 
151
152
  <div class="basemap-options main-area popup-dialog">
152
153
  <div class="info-box">
154
+ <div class="close2-btn"></div>
153
155
  <h3>Basemap options</h3>
154
156
  <p class="basemap-note">Your data will be displayed using the Mercator projection.</p>
155
157
  <p class="basemap-warning"></p>
156
158
  <div class="basemap-styles"></div>
157
159
  <div>
158
- <div class="close-btn btn dialog-btn">Close</div>
160
+ <!-- <div class="close-btn btn dialog-btn">Close</div> -->
159
161
  <div class="clear-btn btn dialog-btn disabled">Clear</div>
160
162
  <div class="fade-btn btn dialog-btn disabled">Fade</div>
161
163
  <!-- <div class="hide-btn btn dialog-btn disabled">Hide</div> -->
@@ -165,7 +167,8 @@
165
167
 
166
168
  <div class="simplify-options main-area popup-dialog">
167
169
  <div class="info-box">
168
- <h3>Simplification menu</h3>
170
+ <div class="close2-btn"></div>
171
+ <h3>Simplification</h3>
169
172
  <div class="option-menu">
170
173
  <div><label for="import-retain-opt"><input type="checkbox" class="checkbox import-retain-opt"/>prevent shape removal</label>
171
174
  <div class="tip-button">?<div class="tip-anchor">
@@ -208,7 +211,7 @@ a smoother appearance.</div></div></div></div>
208
211
  </div> <!-- option menu -->
209
212
 
210
213
  <div>
211
- <div class="cancel-btn btn dialog-btn">Cancel</div>
214
+ <!-- <div class="cancel-btn btn dialog-btn">Cancel</div> -->
212
215
  <div class="submit-btn btn dialog-btn">Apply</div>
213
216
  </div>
214
217
  </div> <!-- .info-box -->
@@ -310,7 +310,6 @@
310
310
 
311
311
  // tests if filename is a type that can be used
312
312
  GUI.isReadableFileType = function(filename) {
313
- var ext = internal.getFileExtension(filename).toLowerCase();
314
313
  return !!internal.guessInputFileType(filename) || internal.couldBeDsvFile(filename) ||
315
314
  internal.isZipFile(filename);
316
315
  };
@@ -1354,7 +1353,6 @@
1354
1353
  }
1355
1354
  }
1356
1355
  model.updated({select: true});
1357
-
1358
1356
  }
1359
1357
 
1360
1358
  function clearQueuedFiles() {
@@ -1451,9 +1449,8 @@
1451
1449
  }
1452
1450
 
1453
1451
 
1454
- // TODO: support .cpg
1455
1452
  function isShapefilePart(name) {
1456
- return /\.(shp|shx|dbf|prj)$/i.test(name);
1453
+ return /\.(shp|shx|dbf|prj|cpg)$/i.test(name);
1457
1454
  }
1458
1455
 
1459
1456
  function readImportOpts() {
@@ -1685,7 +1682,6 @@
1685
1682
  }
1686
1683
 
1687
1684
  function Slider(ref, opts) {
1688
- var _el = El(ref);
1689
1685
  var _self = this;
1690
1686
  var defaults = {
1691
1687
  space: 7
@@ -1716,7 +1712,7 @@
1716
1712
  _handle = El(ref);
1717
1713
  draggable(_handle)
1718
1714
  .on('drag', function(e) {
1719
- setHandlePos(startX + e.dx, true);
1715
+ setHandlePos(startX + e.dx);
1720
1716
  })
1721
1717
  .on('dragstart', function(e) {
1722
1718
  startX = position();
@@ -1742,7 +1738,7 @@
1742
1738
  return _pct;
1743
1739
  };
1744
1740
 
1745
- function setHandlePos(x, fire) {
1741
+ function setHandlePos(x) {
1746
1742
  x = utils$1.clamp(x, 0, size());
1747
1743
  var pct = x / size();
1748
1744
  if (pct != _pct) {
@@ -2131,7 +2127,7 @@
2131
2127
 
2132
2128
  // init settings menu
2133
2129
  new SimpleButton(menu.findChild('.submit-btn').addClass('default-btn')).on('click', onSubmit);
2134
- new SimpleButton(menu.findChild('.cancel-btn')).on('click', function() {
2130
+ new SimpleButton(menu.findChild('.close2-btn')).on('click', function() {
2135
2131
  if (el.visible()) {
2136
2132
  // cancel just hides menu if slider is visible
2137
2133
  menu.hide();
@@ -2264,7 +2260,7 @@
2264
2260
  menu.hide();
2265
2261
  setTimeout(function() {
2266
2262
  var opts = getSimplifyOptions();
2267
- mapshaper.simplify(dataset, opts);
2263
+ mapshaper.cmd.simplify(dataset, opts);
2268
2264
  gui.session.simplificationApplied(getSimplifyOptionsAsString());
2269
2265
  updateZ(gui.map.getActiveLayer()); // question: does this update all display layers?
2270
2266
  model.updated({
@@ -3125,7 +3121,7 @@
3125
3121
 
3126
3122
  function cleanLayerName(raw) {
3127
3123
  return raw.replace(/[\n\t/\\]/g, '')
3128
- .replace(/^[\.\s]+/, '').replace(/[\.\s]+$/, '');
3124
+ .replace(/^[.\s]+/, '').replace(/[.\s]+$/, '');
3129
3125
  }
3130
3126
 
3131
3127
  function updateLayerStackOrder(layers) {
@@ -3159,7 +3155,7 @@
3159
3155
  var layersArr = [];
3160
3156
  var toggleBtn = null; // checkbox <input> for toggling layer selection
3161
3157
  var exportBtn = gui.container.findChild('.export-btn');
3162
- new SimpleButton(menu.findChild('.cancel-btn')).on('click', gui.clearMode);
3158
+ new SimpleButton(menu.findChild('.close2-btn')).on('click', gui.clearMode);
3163
3159
 
3164
3160
  if (!GUI.exportIsSupported()) {
3165
3161
  exportBtn.on('click', function() {
@@ -3859,8 +3855,6 @@
3859
3855
  }
3860
3856
  }
3861
3857
 
3862
- var snapVerticesToPoint = internal.snapVerticesToPoint;
3863
- var cloneShape = internal.cloneShape;
3864
3858
  var copyRecord = internal.copyRecord;
3865
3859
 
3866
3860
  function Undo(gui) {
@@ -4415,7 +4409,8 @@
4415
4409
  return self;
4416
4410
  }
4417
4411
 
4418
- var Buffer = require('buffer').Buffer; // works with browserify
4412
+ // Fall back to browserify's Buffer polyfill
4413
+ var B = typeof Buffer != 'undefined' ? Buffer : require('buffer').Buffer;
4419
4414
 
4420
4415
  // This module provides a way for multiple jobs to run together asynchronously
4421
4416
  // while keeping job-level context variables (like "defs") separate.
@@ -4743,7 +4738,7 @@
4743
4738
  '/': '&#x2F;'
4744
4739
  };
4745
4740
  function htmlEscape(s) {
4746
- return String(s).replace(/[&<>"'\/]/g, function(s) {
4741
+ return String(s).replace(/[&<>"'/]/g, function(s) {
4747
4742
  return entityMap[s];
4748
4743
  });
4749
4744
  }
@@ -5386,8 +5381,8 @@
5386
5381
  var type = matches[4];
5387
5382
  var isString = type == 's',
5388
5383
  isHex = type == 'x' || type == 'X',
5389
- isInt = type == 'd' || type == 'i',
5390
- isFloat = type == 'f',
5384
+ // isInt = type == 'd' || type == 'i',
5385
+ // isFloat = type == 'f',
5391
5386
  isNumber = !isString;
5392
5387
 
5393
5388
  var sign = "",
@@ -5446,7 +5441,7 @@
5446
5441
 
5447
5442
  // Get a function for interpolating formatted values into a string.
5448
5443
  function formatter(fmt) {
5449
- var codeRxp = /%([\',+0]*)([1-9]?)((?:\.[1-9])?)([sdifxX%])/g;
5444
+ var codeRxp = /%([',+0]*)([1-9]?)((?:\.[1-9])?)([sdifxX%])/g;
5450
5445
  var literals = [],
5451
5446
  formatCodes = [],
5452
5447
  startIdx = 0,
@@ -5490,10 +5485,10 @@
5490
5485
 
5491
5486
  function createBuffer(arg, arg2) {
5492
5487
  if (isInteger(arg)) {
5493
- return Buffer.allocUnsafe ? Buffer.allocUnsafe(arg) : new Buffer(arg);
5488
+ return B.allocUnsafe ? B.allocUnsafe(arg) : new B(arg);
5494
5489
  } else {
5495
5490
  // check allocUnsafe to make sure Buffer.from() will accept strings (it didn't before Node v5.10)
5496
- return Buffer.from && Buffer.allocUnsafe ? Buffer.from(arg, arg2) : new Buffer(arg, arg2);
5491
+ return B.from && B.allocUnsafe ? B.from(arg, arg2) : new B(arg, arg2);
5497
5492
  }
5498
5493
  }
5499
5494
 
@@ -5846,27 +5841,21 @@
5846
5841
 
5847
5842
  function pointTest(x, y) {
5848
5843
  var bullseyeDist = 2, // hit all points w/in 2 px
5849
- tinyDist = 0.5,
5850
- toPx = ext.getTransform().mx,
5851
- hits = [],
5852
5844
  hitThreshold = 25,
5853
- newThreshold = Infinity;
5845
+ toPx = ext.getTransform().mx,
5846
+ hits = [];
5854
5847
 
5848
+ // inlining forEachPoint() does not not appreciably speed this up
5855
5849
  internal.forEachPoint(displayLayer.layer.shapes, function(p, id) {
5856
5850
  var dist = geom.distance2D(x, y, p[0], p[1]) * toPx;
5857
5851
  if (dist > hitThreshold) return;
5858
- // got a hit
5859
- if (dist < newThreshold) {
5860
- // start a collection of hits
5861
- hits = [id];
5862
- hitThreshold = Math.max(bullseyeDist, dist + tinyDist);
5863
- newThreshold = dist < bullseyeDist ? -1 : dist - tinyDist;
5864
- } else {
5865
- // add to hits if inside bullseye or is same dist as previous hit
5866
- hits.push(id);
5852
+ if (dist < hitThreshold && hitThreshold > bullseyeDist) {
5853
+ hits = [];
5854
+ hitThreshold = Math.max(bullseyeDist, dist);
5867
5855
  }
5856
+ hits.push(id);
5868
5857
  });
5869
- // TODO: add info on what part of a shape gets hit
5858
+ // TODO: add info on what part of a shape gets hit?
5870
5859
  return {
5871
5860
  ids: utils$1.uniq(hits) // multipoint features can register multiple hits
5872
5861
  };
@@ -8756,7 +8745,7 @@
8756
8745
  bx = t.bx,
8757
8746
  by = t.by;
8758
8747
  if (size === 0) return;
8759
- if (size <= 4 && !styler) {
8748
+ if (size <= 6 && !styler) {
8760
8749
  // optimized drawing of many small same-colored dots
8761
8750
  _self.drawSquareDotsFaster(shapes, color, size, t);
8762
8751
  return;
@@ -8813,14 +8802,12 @@
8813
8802
  // pixels: Uint32Array of pixel colors
8814
8803
  // w, h: Size of canvas
8815
8804
  function drawSquareFaster(x, y, rgba, size, pixels, w, h) {
8816
- var xmin = (x - size * 0.5) | 0;
8817
- var ymin = (y - size * 0.5) | 0;
8818
- var xmax = xmin + size - 1;
8819
- var ymax = ymin + size - 1;
8820
- var c, r;
8821
- for (c = xmin; c <= xmax; c++) {
8822
- if (c < 0 || c >= w) continue;
8823
- for (r = ymin; r <= ymax && r >= 0 && r < h; r++) {
8805
+ var xmin = x < 0 ? 0 : (x - size * 0.5) | 0;
8806
+ var ymin = y < 0 ? 0 : (y - size * 0.5) | 0;
8807
+ var xmax = x >= w-1 ? w-1 : xmin + size - 1;
8808
+ var ymax = y >= h-1 ? h-1 : ymin + size - 1;
8809
+ for (var r = ymin; r <= ymax; r++) {
8810
+ for (var c = xmin; c <= xmax; c++) {
8824
8811
  pixels[r * w + c] = rgba;
8825
8812
  }
8826
8813
  }
@@ -8907,24 +8894,25 @@
8907
8894
  return s;
8908
8895
  }
8909
8896
 
8910
-
8911
8897
  function getDotScale(ext) {
8912
8898
  var smallSide = Math.min(ext.width(), ext.height());
8899
+ var mapScale = ext.scale();
8913
8900
  // reduce size on smaller screens
8914
8901
  var j = smallSide < 200 && 0.5 || smallSide < 400 && 0.75 || 1;
8902
+ // grow dots as map zooms in
8915
8903
  var k = 1;
8916
- var mapScale = ext.scale();
8917
8904
  if (mapScale < 0.5) {
8918
8905
  k = Math.pow(mapScale + 0.5, 0.35);
8919
- }
8920
- if (mapScale > 1) {
8906
+ } else if (mapScale > 1) {
8921
8907
  // scale faster at first, so small dots in large datasets
8922
8908
  // become easily visible and clickable after zooming in a bit
8923
8909
  k *= Math.pow(Math.min(mapScale, 10), 0.3);
8924
8910
  k *= Math.pow(mapScale, 0.1);
8925
8911
  }
8926
-
8927
- return k * j * GUI.getPixelRatio();
8912
+ // grow pixels more slowly on retina displays (to reduce number of pixels to
8913
+ // draw for large point datasets when slightly zoomed in)
8914
+ var l = Math.pow(GUI.getPixelRatio(), 0.8);
8915
+ return j * k * l;
8928
8916
  }
8929
8917
 
8930
8918
  function getScaledTransform(ext) {
@@ -9497,7 +9485,7 @@
9497
9485
 
9498
9486
  // Only generate low-detail arcs for larger datasets
9499
9487
  if (size > 5e5) {
9500
- if (!!unfilteredArcs.getVertexData().zz) {
9488
+ if (unfilteredArcs.getVertexData().zz) {
9501
9489
  // Use precalculated simplification data for vertex filtering, if available
9502
9490
  filteredArcs = initFilteredArcs(unfilteredArcs);
9503
9491
  filteredSegLen = internal.getAvgSegment(filteredArcs);
@@ -9764,7 +9752,7 @@
9764
9752
  var menu = gui.container.findChild('.basemap-options');
9765
9753
  // var hideBtn = new SimpleButton(menu.findChild('.hide-btn'));
9766
9754
  var fadeBtn = new SimpleButton(menu.findChild('.fade-btn'));
9767
- var closeBtn = new SimpleButton(menu.findChild('.close-btn'));
9755
+ var closeBtn = new SimpleButton(menu.findChild('.close2-btn'));
9768
9756
  var clearBtn = new SimpleButton(menu.findChild('.clear-btn'));
9769
9757
  var list = menu.findChild('.basemap-styles');
9770
9758
  var container = gui.container.findChild('.basemap-container');
@@ -9863,7 +9851,13 @@
9863
9851
  var warning;
9864
9852
 
9865
9853
  if (!dataCRS || !displayCRS || !crsIsUsable(displayCRS) || !crsIsUsable(dataCRS)) {
9866
- warning = 'The current layer is not compatible with the projection used by the basemaps.';
9854
+ warning = 'This data is incompatible with the basemaps.';
9855
+ if (!internal.layerHasGeometry(activeLyr.layer)) {
9856
+ warning += ' Reason: layer is missing geographic data';
9857
+ } else if (!dataCRS) {
9858
+ warning += ' Reason: unknown projection.';
9859
+ }
9860
+
9867
9861
  basemapWarning.html(warning).show();
9868
9862
  basemapNote.hide();
9869
9863
  } else {