mapshaper 0.6.9 → 0.6.10

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
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.6.9";
3
+ var VERSION = "0.6.10";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -8470,7 +8470,9 @@
8470
8470
  function getBoundsPrecisionForDisplay(bbox) {
8471
8471
  var w = Math.abs(bbox[2] - bbox[0]),
8472
8472
  h = Math.abs(bbox[3] - bbox[1]),
8473
- range = Math.min(w, h) + 1e-8,
8473
+ // switched to max bound, based on experience with shift-drag box info
8474
+ // range = Math.min(w, h) + 1e-8,
8475
+ range = Math.max(w, h) + 1e-8,
8474
8476
  digits = 0;
8475
8477
  while (range < 2000) {
8476
8478
  range *= 10;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.6.9",
3
+ "version": "0.6.10",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -2046,7 +2046,7 @@
2046
2046
  // bbox: display coords
2047
2047
  // intended to work with rectangular projections like Mercator
2048
2048
  function getBBoxCoords(lyr, bbox) {
2049
- if (!isProjectedLayer(lyr)) return bbox;
2049
+ if (!isProjectedLayer(lyr)) return bbox.concat();
2050
2050
  var a = translateDisplayPoint(lyr, [bbox[0], bbox[1]]);
2051
2051
  var b = translateDisplayPoint(lyr, [bbox[2], bbox[3]]);
2052
2052
  var bounds = new internal.Bounds();
@@ -6923,9 +6923,208 @@
6923
6923
  });
6924
6924
  }
6925
6925
 
6926
+ function HighlightBox(gui, optsArg) {
6927
+ var el = El('div').addClass('zoom-box').appendTo('body'),
6928
+ opts = Object.assign({handles: false, persistent: false}, optsArg),
6929
+ box = new EventDispatcher(),
6930
+ stroke = 2,
6931
+ activeHandle = null,
6932
+ prevXY = null,
6933
+ boxCoords = null,
6934
+ _on = false,
6935
+ handles;
6936
+
6937
+ el.hide();
6938
+
6939
+ gui.on('map_navigation', function() {
6940
+ if (!_on) return;
6941
+ redraw();
6942
+ });
6943
+
6944
+ gui.on('box_drag', function(e) {
6945
+ if (!_on) return;
6946
+ boxCoords = getBoxCoords(e.data);
6947
+ redraw();
6948
+ box.dispatchEvent('drag');
6949
+ });
6950
+
6951
+ gui.on('box_drag_end', function(e) {
6952
+ if (!_on) return;
6953
+ boxCoords = getBoxCoords(e.data);
6954
+ var pix = coordsToPix(boxCoords, gui.map.getExtent());
6955
+ box.dispatchEvent('dragend', {map_bbox: pix});
6956
+ if (!opts.persistent) {
6957
+ box.hide();
6958
+ } else {
6959
+ redraw();
6960
+ }
6961
+ });
6962
+
6963
+ if (opts.handles) {
6964
+ handles = initHandles(el);
6965
+ handles.forEach(function(handle) {
6966
+ handle.el.on('mousedown', function(e) {
6967
+ activeHandle = handle;
6968
+ prevXY = {x: e.pageX, y: e.pageY};
6969
+ });
6970
+ });
6971
+
6972
+ document.addEventListener('mousemove', function(e) {
6973
+ if (!_on || !activeHandle || !prevXY || !boxCoords) return;
6974
+ var xy = {x: e.pageX, y: e.pageY};
6975
+ var scale = gui.map.getExtent().getPixelSize();
6976
+ var dx = (xy.x - prevXY.x) * scale;
6977
+ var dy = -(xy.y - prevXY.y) * scale;
6978
+ if (activeHandle.col == 'left') {
6979
+ boxCoords[0] += dx;
6980
+ } else if (activeHandle.col == 'right') {
6981
+ boxCoords[2] += dx;
6982
+ }
6983
+ if (activeHandle.row == 'top') {
6984
+ boxCoords[3] += dy;
6985
+ } else if (activeHandle.row == 'bottom') {
6986
+ boxCoords[1] += dy;
6987
+ }
6988
+ prevXY = xy;
6989
+ redraw();
6990
+ box.dispatchEvent('handle_drag');
6991
+ });
6992
+
6993
+ document.addEventListener('mouseup', function() {
6994
+ if (activeHandle && _on) {
6995
+ activeHandle = null;
6996
+ prevXY = null;
6997
+ box.dispatchEvent('handle_up');
6998
+ // reset box if it has been inverted (by dragging)
6999
+ fixBounds(boxCoords);
7000
+ redraw();
7001
+ }
7002
+ });
7003
+ }
7004
+
7005
+ box.getDataCoords = function() {
7006
+ if (!boxCoords) return null;
7007
+ var dataBox = getBBoxCoords(gui.map.getActiveLayer(), boxCoords);
7008
+ fixBounds(dataBox);
7009
+ return internal.getRoundedCoords(dataBox, internal.getBoundsPrecisionForDisplay(dataBox));
7010
+ };
7011
+
7012
+ box.turnOn = function() {
7013
+ _on = true;
7014
+ };
7015
+
7016
+ box.turnOff = function() {
7017
+ _on = false;
7018
+ };
7019
+
7020
+ box.hide = function() {
7021
+ el.hide();
7022
+ boxCoords = null;
7023
+ };
7024
+
7025
+ box.show = function(x1, y1, x2, y2) {
7026
+ var w = Math.abs(x1 - x2),
7027
+ h = Math.abs(y1 - y2),
7028
+ props = {
7029
+ top: Math.min(y1, y2),
7030
+ left: Math.min(x1, x2),
7031
+ width: Math.max(w - stroke * 2, 1),
7032
+ height: Math.max(h - stroke * 2, 1)
7033
+ };
7034
+ el.css(props);
7035
+ el.show();
7036
+ if (handles) {
7037
+ showHandles(handles, props);
7038
+ }
7039
+ };
7040
+
7041
+ function getBoxCoords(e) {
7042
+ var bbox = pixToCoords(e.a.concat(e.b), gui.map.getExtent());
7043
+ fixBounds(bbox);
7044
+ return bbox;
7045
+ }
7046
+
7047
+ function redraw() {
7048
+ if (!boxCoords) return;
7049
+ var ext = gui.map.getExtent();
7050
+ var b = coordsToPix(boxCoords, ext);
7051
+ var pos = ext.position();
7052
+ var dx = pos.pageX,
7053
+ dy = pos.pageY;
7054
+ box.show(b[0] + dx, b[1] + dy, b[2] + dx, b[3] + dy);
7055
+ }
7056
+
7057
+ return box;
7058
+ }
7059
+
7060
+ function coordsToPix(bbox, ext) {
7061
+ var a = ext.translateCoords(bbox[0], bbox[1]);
7062
+ var b = ext.translateCoords(bbox[2], bbox[3]);
7063
+ return [a[0], b[1], b[0], a[1]];
7064
+ }
7065
+
7066
+ function pixToCoords(bbox, ext) {
7067
+ var a = ext.translatePixelCoords(bbox[0], bbox[1]);
7068
+ var b = ext.translatePixelCoords(bbox[2], bbox[3]);
7069
+ return [a[0], b[1], b[0], a[1]];
7070
+ }
7071
+
7072
+
7073
+ function fixBounds(bbox) {
7074
+ var tmp;
7075
+ if (bbox[0] > bbox[2]) {
7076
+ tmp = bbox[0];
7077
+ bbox[0] = bbox[2];
7078
+ bbox[2] = tmp;
7079
+ }
7080
+ if (bbox[1] > bbox[3]) {
7081
+ tmp = bbox[1];
7082
+ bbox[1] = bbox[3];
7083
+ bbox[3] = tmp;
7084
+ }
7085
+ }
7086
+
7087
+ function initHandles(el) {
7088
+ var handles = [];
7089
+ for (var i=0; i<9; i++) {
7090
+ if (i == 4) continue;
7091
+ var c = Math.floor(i / 3);
7092
+ var r = i % 3;
7093
+ handles.push({
7094
+ el: El('div').addClass('handle').appendTo(el),
7095
+ col: c == 0 && 'left' || c == 1 && 'center' || 'right',
7096
+ row: r == 0 && 'top' || r == 1 && 'center' || 'bottom'
7097
+ });
7098
+ }
7099
+ return handles;
7100
+ }
7101
+
7102
+ function showHandles(handles, props) {
7103
+ var SIZE = 6; // should match .handle size in page.css
7104
+ handles.forEach(function(handle) {
7105
+ var top = 0,
7106
+ left = 0;
7107
+ if (handle.col == 'center') {
7108
+ left += props.width / 2 - SIZE / 2;
7109
+ } else if (handle.col == 'right') {
7110
+ left += props.width - SIZE;
7111
+ }
7112
+ if (handle.row == 'center') {
7113
+ top += props.height / 2 - SIZE / 2;
7114
+ } else if (handle.row == 'bottom') {
7115
+ top += props.height - SIZE;
7116
+ }
7117
+ handle.el.css({
7118
+ top: top,
7119
+ left: left
7120
+ });
7121
+ });
7122
+ }
7123
+
6926
7124
  function MapNav(gui, ext, mouse) {
6927
7125
  var wheel = new MouseWheel(mouse),
6928
7126
  zoomTween = new Tween(Tween.sineInOut),
7127
+ zoomBox = new HighlightBox(gui), // .addClass('zooming'),
6929
7128
  boxDrag = false,
6930
7129
  zoomScaleMultiplier = 1,
6931
7130
  inBtn, outBtn,
@@ -6959,6 +7158,11 @@
6959
7158
  ext.home();
6960
7159
  });
6961
7160
 
7161
+ ext.on('change', function() {
7162
+ // kludge so controls (e.g. HighlightBox) can initialize before map is ready
7163
+ gui.dispatchEvent('map_navigation');
7164
+ });
7165
+
6962
7166
  zoomTween.on('change', function(e) {
6963
7167
  ext.zoomToExtent(e.value, _fx, _fy);
6964
7168
  });
@@ -6978,6 +7182,7 @@
6978
7182
  // zoomDrag = !!e.metaKey || !!e.ctrlKey; // meta is command on mac, windows key on windows
6979
7183
  boxDrag = !!e.shiftKey;
6980
7184
  if (boxDrag) {
7185
+ if (useBoxZoom()) zoomBox.turnOn();
6981
7186
  dragStartEvt = e;
6982
7187
  gui.dispatchEvent('box_drag_start');
6983
7188
  }
@@ -6998,9 +7203,14 @@
6998
7203
  if (boxDrag) {
6999
7204
  boxDrag = false;
7000
7205
  gui.dispatchEvent('box_drag_end', getBoxData(e));
7206
+ zoomBox.turnOff();
7001
7207
  }
7002
7208
  });
7003
7209
 
7210
+ zoomBox.on('dragend', function(e) {
7211
+ zoomToBbox(e.map_bbox);
7212
+ });
7213
+
7004
7214
  wheel.on('mousewheel', function(e) {
7005
7215
  var tickFraction = 0.11; // 0.15; // fraction of zoom step per wheel event;
7006
7216
  var k = 1 + (tickFraction * e.multiplier * zoomScaleMultiplier),
@@ -7009,46 +7219,17 @@
7009
7219
  ext.zoomByPct(delta, e.x / ext.width(), e.y / ext.height());
7010
7220
  });
7011
7221
 
7012
- function fixBounds(bbox) {
7013
- if (bbox[0] > bbox[2]) {
7014
- swapElements(bbox, 0, 2);
7015
- }
7016
- if (bbox[1] > bbox[3]) {
7017
- swapElements(bbox, 1, 3);
7018
- }
7019
- }
7020
-
7021
- function swapElements(arr, i, j) {
7022
- var tmp = arr[i];
7023
- arr[i] = arr[j];
7024
- arr[j] = tmp;
7222
+ function useBoxZoom() {
7223
+ return gui.getMode() != 'selection_tool' && gui.getMode() != 'box_tool';
7025
7224
  }
7026
7225
 
7027
7226
  function getBoxData(e) {
7028
- var pageBox = [e.pageX, e.pageY, dragStartEvt.pageX, dragStartEvt.pageY];
7029
- var mapBox = [e.x, e.y, dragStartEvt.x, dragStartEvt.y];
7030
- var displayBox = pixToCoords(mapBox);
7031
- var dataBox = getBBoxCoords(gui.map.getActiveLayer(), displayBox);
7032
- fixBounds(pageBox);
7033
- fixBounds(mapBox);
7034
- fixBounds(displayBox);
7035
- fixBounds(dataBox);
7036
7227
  return {
7037
- map_bbox: mapBox,
7038
- page_bbox: pageBox,
7039
- // round coords, for nicer 'info' display
7040
- // (rounded precision should be sub-pixel)
7041
- map_display_bbox: internal.getRoundedCoords(displayBox, internal.getBoundsPrecisionForDisplay(displayBox)),
7042
- map_data_bbox: internal.getRoundedCoords(dataBox, internal.getBoundsPrecisionForDisplay(dataBox))
7228
+ a: [e.x, e.y],
7229
+ b: [dragStartEvt.x, dragStartEvt.y]
7043
7230
  };
7044
7231
  }
7045
7232
 
7046
- function pixToCoords(bbox) {
7047
- var a = ext.translatePixelCoords(bbox[0], bbox[1]);
7048
- var b = ext.translatePixelCoords(bbox[2], bbox[3]);
7049
- return [a[0], b[1], b[0], a[1]];
7050
- }
7051
-
7052
7233
  function disabled() {
7053
7234
  return !!gui.options.disableNavigation;
7054
7235
  }
@@ -7093,28 +7274,9 @@
7093
7274
  }
7094
7275
  }
7095
7276
 
7096
- function HighlightBox() {
7097
- var box = El('div').addClass('zoom-box').appendTo('body'),
7098
- show = box.show.bind(box), // original show() function
7099
- stroke = 2;
7100
- box.hide();
7101
- box.show = function(x1, y1, x2, y2) {
7102
- var w = Math.abs(x1 - x2),
7103
- h = Math.abs(y1 - y2);
7104
- box.css({
7105
- top: Math.min(y1, y2),
7106
- left: Math.min(x1, x2),
7107
- width: Math.max(w - stroke * 2, 1),
7108
- height: Math.max(h - stroke * 2, 1)
7109
- });
7110
- show();
7111
- };
7112
- return box;
7113
- }
7114
-
7115
7277
  function SelectionTool(gui, ext, hit) {
7116
7278
  var popup = gui.container.findChild('.selection-tool-options');
7117
- var box = new HighlightBox();
7279
+ var box = new HighlightBox(gui);
7118
7280
  var _on = false;
7119
7281
 
7120
7282
  gui.addMode('selection_tool', turnOn, turnOff);
@@ -7127,16 +7289,17 @@
7127
7289
  }
7128
7290
  });
7129
7291
 
7130
- gui.on('box_drag', function(e) {
7292
+ box.on('drag', function(e) {
7131
7293
  if (!_on) return;
7132
- var b = e.page_bbox;
7133
- box.show(b[0], b[1], b[2], b[3]);
7134
- updateSelection(e.map_data_bbox, true);
7294
+ updateSelection(box.getDataCoords(), true);
7135
7295
  });
7136
7296
 
7137
- gui.on('box_drag_end', function(e) {
7297
+ box.on('dragend', function(e) {
7138
7298
  if (!_on) return;
7139
- box.hide();
7299
+ updateSelection(box.getDataCoords());
7300
+ });
7301
+
7302
+ gui.on('selection_bridge', function(e) {
7140
7303
  updateSelection(e.map_data_bbox);
7141
7304
  });
7142
7305
 
@@ -7151,10 +7314,12 @@
7151
7314
  }
7152
7315
 
7153
7316
  function turnOn() {
7317
+ box.turnOn();
7154
7318
  _on = true;
7155
7319
  }
7156
7320
 
7157
7321
  function turnOff() {
7322
+ box.turnOff();
7158
7323
  reset();
7159
7324
  _on = false;
7160
7325
  if (gui.interaction.getMode() == 'selection') {
@@ -9367,15 +9532,14 @@
9367
9532
  }
9368
9533
  }
9369
9534
 
9370
- // Controls both the shift-drag zoom-to-extent tool and the shift-drag editing tool
9371
-
9372
- function BoxTool(gui, ext, mouse, nav) {
9535
+ // Controls the shift-drag box editing tool
9536
+ //
9537
+ function BoxTool(gui, ext, nav) {
9373
9538
  var self = new EventDispatcher();
9374
- var box = new HighlightBox();
9539
+ var box = new HighlightBox(gui, {persistent: true, handles: true});
9375
9540
  var popup = gui.container.findChild('.box-tool-options');
9376
9541
  var coords = popup.findChild('.box-coords');
9377
9542
  var _on = false;
9378
- var bboxData;
9379
9543
 
9380
9544
  var infoBtn = new SimpleButton(popup.findChild('.info-btn')).on('click', function() {
9381
9545
  if (coords.visible()) hideCoords(); else showCoords();
@@ -9385,28 +9549,19 @@
9385
9549
  reset();
9386
9550
  });
9387
9551
 
9388
- // Removing zoom-in button -- cumbersome way to zoom
9389
- // new SimpleButton(popup.findChild('.zoom-btn')).on('click', function() {
9390
- // nav.zoomToBbox(bboxPixels);
9391
- // reset();
9392
- // });
9393
-
9394
- // Removing button for creating a layer containing a single rectangle.
9395
- // You can get the bbox with the Info button and create a rectangle in the console
9396
- // using -rectangle bbox=<coordinates>
9397
- // new SimpleButton(popup.findChild('.rectangle-btn')).on('click', function() {
9398
- // runCommand('-rectangle bbox=' + bbox.join(','));
9399
- // });
9400
-
9401
9552
  new SimpleButton(popup.findChild('.select-btn')).on('click', function() {
9553
+ var coords = box.getDataCoords();
9554
+ if (!coords) return;
9402
9555
  gui.enterMode('selection_tool');
9403
9556
  gui.interaction.setMode('selection');
9404
9557
  // kludge to pass bbox to the selection tool
9405
- gui.dispatchEvent('box_drag_end', bboxData);
9558
+ gui.dispatchEvent('selection_bridge', {
9559
+ map_data_bbox: coords
9560
+ });
9406
9561
  });
9407
9562
 
9408
9563
  new SimpleButton(popup.findChild('.clip-btn')).on('click', function() {
9409
- runCommand('-clip bbox=' + bboxData.map_data_bbox.join(','));
9564
+ runCommand('-clip bbox=' + box.getDataCoords().join(','));
9410
9565
  });
9411
9566
 
9412
9567
  gui.addMode('box_tool', turnOn, turnOff);
@@ -9419,37 +9574,18 @@
9419
9574
  }
9420
9575
  });
9421
9576
 
9422
- // Update the visible rectangle when the map view changes
9423
- // (e.g. during zooming or panning)
9424
- ext.on('change', function() {
9425
- if (!_on || !box.visible() || !bboxData) return;
9426
- var b = coordsToPix(bboxData.map_display_bbox);
9427
- var pos = ext.position();
9428
- var dx = pos.pageX,
9429
- dy = pos.pageY;
9430
- box.show(b[0] + dx, b[1] + dy, b[2] + dx, b[3] + dy);
9431
- });
9432
-
9433
9577
  gui.on('box_drag_start', function() {
9434
- box.classed('zooming', inZoomMode());
9578
+ // box.classed('zooming', inZoomMode());
9435
9579
  hideCoords();
9436
9580
  });
9437
9581
 
9438
- gui.on('box_drag', function(e) {
9439
- var b = e.page_bbox;
9440
- bboxData = e.data;
9441
- if (_on || inZoomMode()) {
9442
- box.show(b[0], b[1], b[2], b[3]);
9443
- }
9582
+ box.on('dragend', function(e) {
9583
+ if (_on) popup.show();
9444
9584
  });
9445
9585
 
9446
- gui.on('box_drag_end', function(e) {
9447
- bboxData = e.data;
9448
- if (inZoomMode()) {
9449
- box.hide();
9450
- nav.zoomToBbox(e.map_bbox);
9451
- } else if (_on) {
9452
- popup.show();
9586
+ box.on('handle_drag', function() {
9587
+ if (coords.visible()) {
9588
+ showCoords();
9453
9589
  }
9454
9590
  });
9455
9591
 
@@ -9468,7 +9604,7 @@
9468
9604
 
9469
9605
  function showCoords() {
9470
9606
  El(infoBtn.node()).addClass('selected-btn');
9471
- coords.text(bboxData.map_data_bbox.join(','));
9607
+ coords.text(box.getDataCoords().join(','));
9472
9608
  coords.show();
9473
9609
  GUI.selectElement(coords.node());
9474
9610
  }
@@ -9479,10 +9615,12 @@
9479
9615
  }
9480
9616
 
9481
9617
  function turnOn() {
9618
+ box.turnOn();
9482
9619
  _on = true;
9483
9620
  }
9484
9621
 
9485
9622
  function turnOff() {
9623
+ box.turnOff();
9486
9624
  if (gui.interaction.getMode() == 'box') {
9487
9625
  // mode change was not initiated by interactive menu -- turn off interactivity
9488
9626
  gui.interaction.turnOff();
@@ -9497,12 +9635,6 @@
9497
9635
  hideCoords();
9498
9636
  }
9499
9637
 
9500
- function coordsToPix(bbox) {
9501
- var a = ext.translateCoords(bbox[0], bbox[1]);
9502
- var b = ext.translateCoords(bbox[2], bbox[3]);
9503
- return [a[0], b[1], b[0], a[1]];
9504
- }
9505
-
9506
9638
  return self;
9507
9639
  }
9508
9640
 
@@ -10019,7 +10151,7 @@
10019
10151
  _ext = new MapExtent(position),
10020
10152
  _hit = new InteractiveSelection(gui, _ext, _mouse),
10021
10153
  _nav = new MapNav(gui, _ext, _mouse),
10022
- _boxTool = new BoxTool(gui, _ext, _mouse, _nav),
10154
+ _boxTool = new BoxTool(gui, _ext, _nav),
10023
10155
  _selectionTool = new SelectionTool(gui, _ext, _hit),
10024
10156
  _visibleLayers = [], // cached visible map layers
10025
10157
  _fullBounds = null,
package/www/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.6.9";
3
+ var VERSION = "0.6.10";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -8470,7 +8470,9 @@
8470
8470
  function getBoundsPrecisionForDisplay(bbox) {
8471
8471
  var w = Math.abs(bbox[2] - bbox[0]),
8472
8472
  h = Math.abs(bbox[3] - bbox[1]),
8473
- range = Math.min(w, h) + 1e-8,
8473
+ // switched to max bound, based on experience with shift-drag box info
8474
+ // range = Math.min(w, h) + 1e-8,
8475
+ range = Math.max(w, h) + 1e-8,
8474
8476
  digits = 0;
8475
8477
  while (range < 2000) {
8476
8478
  range *= 10;
package/www/page.css CHANGED
@@ -184,6 +184,7 @@ body {
184
184
 
185
185
  .selection-tool-options .info-box {
186
186
  pointer-events: initial;
187
+ text-align: center;
187
188
  }
188
189
 
189
190
  /* --- Box tool dialog --------- */
@@ -200,6 +201,7 @@ body {
200
201
  }
201
202
 
202
203
  .box-tool-options .box-coords {
204
+ margin-top: 7px;
203
205
  pointer-events: initial;
204
206
  }
205
207
 
@@ -1241,8 +1243,14 @@ div.basemap-style-btn.active img {
1241
1243
  pointer-events: none;
1242
1244
  }
1243
1245
 
1244
- .zoom-box.zooming {
1245
- border-color: #1385B7;
1246
+ .zoom-box .handle {
1247
+ position: absolute;
1248
+ z-index: 16;
1249
+ /* cursor: pointer; */
1250
+ background: #cc6acc;
1251
+ pointer-events: all;
1252
+ width: 6px;
1253
+ height: 6px;
1246
1254
  }
1247
1255
 
1248
1256
  /* Simplification control ------------ */