mapshaper 0.6.63 → 0.6.65

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.6.63",
3
+ "version": "0.6.65",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -2578,6 +2578,25 @@
2578
2578
  internal.snapVerticesToPoint(ids, lyr.invertPoint(p[0], p[1]), lyr.source.dataset.arcs, true);
2579
2579
  }
2580
2580
 
2581
+ function setRectangleCoords(lyr, ids, coords) {
2582
+ ids.forEach(function(id, i) {
2583
+ var p = coords[i];
2584
+ internal.snapVerticesToPoint([id], p, lyr.source.dataset.arcs, true);
2585
+ if (isProjectedLayer(lyr)) {
2586
+ internal.snapVerticesToPoint([id], lyr.projectPoint(p[0], p[1]), lyr.arcs, true);
2587
+ }
2588
+ });
2589
+ }
2590
+
2591
+ // lyr: display layer
2592
+ // export function updateRectangleCoords(lyr, ids, coords) {
2593
+ // if (!isProjectedLayer(lyr)) return;
2594
+ // ids.forEach(function(id, i) {
2595
+ // var p = coords[i];
2596
+ // internal.snapVerticesToPoint([id], lyr.invertPoint(p[0], p[1]), lyr.source.dataset.arcs, true);
2597
+ // });
2598
+ // }
2599
+
2581
2600
  function isProjectedLayer(lyr) {
2582
2601
  // TODO: could do some validation on the layer's contents
2583
2602
  return !!(lyr.source && lyr.invertPoint);
@@ -4852,6 +4871,7 @@
4852
4871
  var menus = {
4853
4872
  standard: ['info', 'selection', 'data', 'box'],
4854
4873
  polygons: ['info', 'selection', 'data', 'box', 'vertices'],
4874
+ rectangles: ['info', 'selection', 'data', 'box', 'rectangles', 'vertices'],
4855
4875
  lines: ['info', 'selection', 'data', 'box', 'vertices'],
4856
4876
  table: ['info', 'selection', 'data'],
4857
4877
  labels: ['info', 'selection', 'data', 'box', 'labels', 'location'],
@@ -4875,6 +4895,7 @@
4875
4895
  vertices: 'edit vertices',
4876
4896
  selection: 'select features',
4877
4897
  'add-points': 'add points',
4898
+ rectangles: 'drag-to-resize',
4878
4899
  off: 'turn off'
4879
4900
  };
4880
4901
  var btn, menu;
@@ -4929,11 +4950,11 @@
4929
4950
  };
4930
4951
 
4931
4952
  this.modeUsesSelection = function(mode) {
4932
- return ['info', 'selection', 'data', 'labels', 'location', 'vertices'].includes(mode);
4953
+ return ['info', 'selection', 'data', 'labels', 'location', 'vertices', 'rectangles'].includes(mode);
4933
4954
  };
4934
4955
 
4935
4956
  this.modeUsesPopup = function(mode) {
4936
- return ['info', 'selection', 'data', 'box', 'labels', 'location'].includes(mode);
4957
+ return ['info', 'selection', 'data', 'box', 'labels', 'location', 'rectangles'].includes(mode);
4937
4958
  };
4938
4959
 
4939
4960
  this.getMode = getInteractionMode;
@@ -4975,7 +4996,8 @@
4975
4996
  return menus.lines;
4976
4997
  }
4977
4998
  if (internal.layerHasPaths(o.layer) && o.layer.geometry_type == 'polygon') {
4978
- return menus.polygons;
4999
+ return internal.layerOnlyHasRectangles(o.layer, o.dataset.arcs) ?
5000
+ menus.rectangles : menus.polygons;
4979
5001
  }
4980
5002
  return menus.standard;
4981
5003
  }
@@ -7029,7 +7051,8 @@
7029
7051
 
7030
7052
  function clickable() {
7031
7053
  // click used to pin popup and select features
7032
- return interactionMode == 'data' || interactionMode == 'info' || interactionMode == 'selection';
7054
+ return interactionMode == 'data' || interactionMode == 'info' ||
7055
+ interactionMode == 'selection' || interactionMode == 'rectangles';
7033
7056
  }
7034
7057
 
7035
7058
  self.getHitId = function() {return storedData.id;};
@@ -7787,6 +7810,10 @@
7787
7810
  _on = false,
7788
7811
  handles;
7789
7812
 
7813
+ if (opts.classname) {
7814
+ el.addClass(opts.classname);
7815
+ }
7816
+
7790
7817
  el.hide();
7791
7818
 
7792
7819
  gui.on('map_rendered', function() {
@@ -7857,6 +7884,11 @@
7857
7884
  });
7858
7885
  }
7859
7886
 
7887
+ box.setDataCoords = function(bbox) {
7888
+ boxCoords = bbox;
7889
+ redraw();
7890
+ };
7891
+
7860
7892
  box.getDataCoords = function() {
7861
7893
  if (!boxCoords) return null;
7862
7894
  var dataBox = getBBoxCoords(gui.map.getActiveLayer(), boxCoords);
@@ -7883,8 +7915,8 @@
7883
7915
  props = {
7884
7916
  top: Math.min(y1, y2),
7885
7917
  left: Math.min(x1, x2),
7886
- width: Math.max(w - stroke * 2, 1),
7887
- height: Math.max(h - stroke * 2, 1)
7918
+ width: Math.max(w - stroke / 2, 1),
7919
+ height: Math.max(h - stroke / 2, 1)
7888
7920
  };
7889
7921
  el.css(props);
7890
7922
  el.show();
@@ -9322,7 +9354,10 @@
9322
9354
  var inSelection = o.ids.indexOf(o.id) > -1;
9323
9355
  var geomType = lyr.geometry_type;
9324
9356
  var style;
9325
- if (isPinned) {
9357
+ if (isPinned && o.mode == 'rectangles') {
9358
+ // kludge for rectangle editing mode
9359
+ style = selectionStyles[geomType];
9360
+ } else if (isPinned) {
9326
9361
  // a feature is pinned
9327
9362
  style = pinnedStyles[geomType];
9328
9363
  } else if (inSelection) {
@@ -10682,6 +10717,82 @@
10682
10717
  return self;
10683
10718
  }
10684
10719
 
10720
+ function RectangleControl(gui, hit) {
10721
+ var box = new HighlightBox(gui, {persistent: true, handles: true, classname: 'rectangles'});
10722
+ var _on = false;
10723
+ var dragInfo;
10724
+
10725
+ gui.addMode('rectangle_tool', turnOn, turnOff);
10726
+
10727
+ gui.on('interaction_mode_change', function(e) {
10728
+ if (e.mode === 'rectangles') {
10729
+ gui.enterMode('rectangle_tool');
10730
+ } else if (gui.getMode() == 'rectangle_tool') {
10731
+ gui.clearMode();
10732
+ }
10733
+ });
10734
+
10735
+ hit.on('change', function(e) {
10736
+ if (!_on) return;
10737
+ // TODO: handle multiple hits (see gui-inspection-control2)
10738
+ var id = e.id;
10739
+ if (e.id > -1 && e.pinned) {
10740
+ var target = hit.getHitTarget();
10741
+ var path = target.layer.shapes[e.id][0];
10742
+ var bbox = target.arcs.getSimpleShapeBounds(path).toArray();
10743
+ box.setDataCoords(bbox);
10744
+ dragInfo = {
10745
+ id: e.id,
10746
+ target: target,
10747
+ ids: [],
10748
+ points: []
10749
+ };
10750
+ var iter = target.arcs.getShapeIter(path);
10751
+ while (iter.hasNext()) {
10752
+ dragInfo.points.push([iter.x, iter.y]);
10753
+ dragInfo.ids.push(iter._arc.i);
10754
+ }
10755
+ gui.container.findChild('.map-layers').classed('dragging', true);
10756
+
10757
+ } else if (dragInfo) {
10758
+ // TODO: handle this event: add undo/redo states
10759
+ gui.dispatchEvent('rectangle_dragend', dragInfo);
10760
+ gui.container.findChild('.map-layers').classed('dragging', false);
10761
+ reset();
10762
+ } else {
10763
+ box.hide();
10764
+ }
10765
+
10766
+ });
10767
+
10768
+ box.on('handle_drag', function(e) {
10769
+ if (!_on || !dragInfo) return;
10770
+ var coords = internal.bboxToCoords(box.getDataCoords());
10771
+ setRectangleCoords(dragInfo.target, dragInfo.ids, coords);
10772
+ gui.dispatchEvent('map-needs-refresh');
10773
+ });
10774
+
10775
+ function turnOn() {
10776
+ box.turnOn();
10777
+ _on = true;
10778
+ }
10779
+
10780
+ function turnOff() {
10781
+ box.turnOff();
10782
+ if (gui.interaction.getMode() == 'rectangles') {
10783
+ // mode change was not initiated by interactive menu -- turn off interactivity
10784
+ gui.interaction.turnOff();
10785
+ }
10786
+ _on = false;
10787
+ reset();
10788
+ }
10789
+
10790
+ function reset() {
10791
+ box.hide();
10792
+ dragInfo = null;
10793
+ }
10794
+ }
10795
+
10685
10796
  // Create low-detail versions of large arc collections for faster rendering
10686
10797
  // at zoomed-out scales.
10687
10798
  function enhanceArcCollectionForDisplay(unfilteredArcs) {
@@ -11372,6 +11483,7 @@
11372
11483
  new InspectionControl2(gui, _hit);
11373
11484
  new SelectionTool(gui, _ext, _hit),
11374
11485
  new BoxTool(gui, _ext, _nav),
11486
+ new RectangleControl(gui, _hit),
11375
11487
  initInteractiveEditing(gui, _ext, _hit);
11376
11488
  // initDrawing(gui, _ext, _mouse, _hit);
11377
11489
  _hit.on('change', updateOverlayLayer);