mapshaper 0.5.94 → 0.5.95

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/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ v0.5.95
2
+ * Added vertex deletion in "edit vertices" mode by double-clicking on non-endpoint vertices.
3
+
1
4
  v0.5.94
2
5
  * Added file_exists() test to -if/-elif expression context.
3
6
 
package/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.5.92";
3
+ var VERSION = "0.5.94";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.5.94",
3
+ "version": "0.5.95",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -3728,24 +3728,36 @@
3728
3728
  this.addHistoryState(stashedUndo, redo);
3729
3729
  }, this);
3730
3730
 
3731
- // undo/redo vertex dragging
3732
- gui.on('vertex_dragstart', function(e) {
3733
- stashedUndo = this.makeVertexSetter(e.FID, e.vertex_ids);
3734
- }, this);
3735
-
3736
3731
  gui.on('vertex_dragend', function(e) {
3737
- var redo = this.makeVertexSetter(e.FID, e.vertex_ids);
3738
- this.addHistoryState(stashedUndo, redo);
3732
+ var target = gui.model.getActiveLayer();
3733
+ var arcs = target.dataset.arcs;
3734
+ var startPoint = e.points[0];
3735
+ var endPoint = internal.getVertexCoords(e.ids[0], arcs);
3736
+ var undo = function() {
3737
+ if (e.insertion) {
3738
+ internal.deleteVertex(arcs, e.ids[0]);
3739
+ } else {
3740
+ snapVerticesToPoint(e.ids, startPoint, arcs, true);
3741
+ }
3742
+ };
3743
+ var redo = function() {
3744
+ if (e.insertion) {
3745
+ internal.insertVertex(arcs, e.ids[0], e.points[0]);
3746
+ }
3747
+ snapVerticesToPoint(e.ids, endPoint, arcs, true);
3748
+ };
3749
+ this.addHistoryState(undo, redo);
3739
3750
  }, this);
3740
3751
 
3741
- gui.on('vertex_insert', function(e) {
3752
+ gui.on('vertex_delete', function(e) {
3742
3753
  var target = gui.model.getActiveLayer();
3743
3754
  var arcs = target.dataset.arcs;
3744
- var undo = function() {
3755
+ var p = arcs.getVertex2(e.vertex_id);
3756
+ var redo = function() {
3745
3757
  internal.deleteVertex(arcs, e.vertex_id);
3746
3758
  };
3747
- var redo = function() {
3748
- internal.insertVertex(arcs, e.vertex_id, e.coordinates);
3759
+ var undo = function() {
3760
+ internal.insertVertex(arcs, e.vertex_id, p);
3749
3761
  };
3750
3762
  this.addHistoryState(undo, redo);
3751
3763
  }, this);
@@ -3771,7 +3783,7 @@
3771
3783
  };
3772
3784
  };
3773
3785
 
3774
- this.makeVertexSetter = function(fid, ids) {
3786
+ this.makeVertexSetter = function(ids) {
3775
3787
  var target = gui.model.getActiveLayer();
3776
3788
  var arcs = target.dataset.arcs;
3777
3789
  var p = internal.getVertexCoords(ids[0], arcs);
@@ -6003,18 +6015,6 @@
6003
6015
  triggerHitEvent('change');
6004
6016
  };
6005
6017
 
6006
- self.setSelectedVertices = function(points) {
6007
- if (!active) return;
6008
- storedData.selected_points = points;
6009
- triggerHitEvent('change');
6010
- };
6011
-
6012
- self.clearSelectedVertices = function() {
6013
- if (!storedData.selected_points) return;
6014
- delete storedData.selected_points;
6015
- triggerHitEvent('change');
6016
- };
6017
-
6018
6018
  self.clearVertexOverlay = function() {
6019
6019
  if (!storedData.hit_coordinates) return;
6020
6020
  delete storedData.hit_coordinates;
@@ -6182,9 +6182,11 @@
6182
6182
  newData = noHitData();
6183
6183
  selectionIds = [];
6184
6184
  }
6185
+
6185
6186
  if (!testHitChange(storedData, newData)) {
6186
6187
  return;
6187
6188
  }
6189
+
6188
6190
  storedData = newData;
6189
6191
  gui.container.findChild('.map-layers').classed('symbol-hit', nonEmpty);
6190
6192
  if (active) {
@@ -7534,25 +7536,20 @@
7534
7536
  }
7535
7537
  }
7536
7538
 
7539
+ // pointer thresholds for hovering near a vertex or segment midpoint
7537
7540
  var HOVER_THRESHOLD = 8;
7538
7541
  var MIDPOINT_THRESHOLD = 12;
7539
7542
 
7540
-
7541
7543
  function initVertexDragging(gui, ext, hit) {
7542
- var activeShapeId = -1;
7543
- var draggedVertexIds = null;
7544
- var selectedVertexIds = null;
7545
- var activeMidpoint; // {point, segment}
7544
+ var activeMidpoint;
7545
+ var dragInfo;
7546
7546
 
7547
- function active(e) {
7548
- return e.id > -1 && gui.interaction.getMode() == 'vertices';
7547
+ function active() {
7548
+ return gui.interaction.getMode() == 'vertices';
7549
7549
  }
7550
7550
 
7551
- function fire(type) {
7552
- gui.dispatchEvent(type, {
7553
- FID: activeShapeId,
7554
- vertex_ids: draggedVertexIds
7555
- });
7551
+ function dragging() {
7552
+ return active() && !!dragInfo;
7556
7553
  }
7557
7554
 
7558
7555
  function setHoverVertex(id) {
@@ -7574,127 +7571,103 @@
7574
7571
  var dist = geom.distance2D(p[0], p[1], p2[0], p2[1]);
7575
7572
  var pixelDist = dist / ext.getPixelSize();
7576
7573
  if (pixelDist > HOVER_THRESHOLD) {
7577
- draggedVertexIds = null;
7578
7574
  return null;
7579
7575
  }
7580
- return nearestIds;
7581
- }
7582
-
7583
- function insertMidpoint(v) {
7584
- var target = hit.getHitTarget();
7585
- internal.insertVertex(target.arcs, v.i, v.point);
7586
- }
7587
-
7588
- function toggleVertexSelection(ids) {
7589
- if (!ids || ids.length === 0) return;
7590
- if (!selectedVertexIds) {
7591
- selectedVertexIds = ids;
7592
- } else {
7593
- var intersection = utils$1.intersection(selectedVertexIds, ids);
7594
- var union = selectedVertexIds.concat(ids);
7595
- selectedVertexIds = utils$1.difference(union, intersection);
7596
- }
7597
- // get coordinates
7598
- var target = hit.getHitTarget();
7599
- var points = selectedVertexIds.map(function(id) { return target.arcs.getVertex2(id); });
7600
- hit.setSelectedVertices(points);
7576
+ var points = nearestIds.map(function(i) {return target.arcs.getVertex2(i);});
7577
+ return {
7578
+ ids: nearestIds,
7579
+ points: points
7580
+ };
7601
7581
  }
7602
7582
 
7603
7583
  hit.on('dragstart', function(e) {
7604
- if (!active(e)) return;
7584
+ if (!active()) return;
7605
7585
  if (activeMidpoint) {
7606
- insertMidpoint(activeMidpoint);
7607
- draggedVertexIds = [activeMidpoint.i];
7608
- // TODO: combine vertex insertion undo/redo actions with
7609
- // vertex_dragend undo/redo actions
7610
- gui.dispatchEvent('vertex_insert', {
7611
- FID: activeShapeId,
7612
- vertex_id: activeMidpoint.i,
7613
- coordinates: activeMidpoint.point
7614
- });
7586
+ var target = hit.getHitTarget();
7587
+ internal.insertVertex(target.arcs, activeMidpoint.i, activeMidpoint.point);
7588
+ dragInfo = {
7589
+ insertion: true,
7590
+ ids: [activeMidpoint.i],
7591
+ points: [activeMidpoint.point]
7592
+ };
7615
7593
  activeMidpoint = null;
7616
7594
  } else {
7617
- draggedVertexIds = findDraggableVertices(e);
7595
+ dragInfo = findDraggableVertices(e);
7596
+ }
7597
+ if (dragInfo) {
7598
+ setHoverVertex(dragInfo.ids[0]);
7618
7599
  }
7619
- if (!draggedVertexIds) return;
7620
- setHoverVertex(draggedVertexIds[0]);
7621
- activeShapeId = e.id;
7622
- fire('vertex_dragstart');
7623
7600
  });
7624
7601
 
7625
7602
  hit.on('drag', function(e) {
7626
- if (!active(e) || !draggedVertexIds) return;
7603
+ if (!dragging()) return;
7627
7604
  var target = hit.getHitTarget();
7628
7605
  var p = ext.translatePixelCoords(e.x, e.y);
7629
7606
  if (gui.keyboard.shiftIsPressed()) {
7630
- internal.snapPointToArcEndpoint(p, draggedVertexIds, target.arcs);
7607
+ internal.snapPointToArcEndpoint(p, dragInfo.ids, target.arcs);
7631
7608
  }
7632
- internal.snapVerticesToPoint(draggedVertexIds, p, target.arcs);
7633
- setHoverVertex(draggedVertexIds[0]);
7609
+ internal.snapVerticesToPoint(dragInfo.ids, p, target.arcs);
7610
+ setHoverVertex(dragInfo.ids[0]);
7634
7611
  // redrawing the whole map updates the data layer as well as the overlay layer
7635
7612
  // gui.dispatchEvent('map-needs-refresh');
7636
7613
  });
7637
7614
 
7638
7615
  hit.on('dragend', function(e) {
7639
- if (!active(e) || !draggedVertexIds) return;
7616
+ if (!dragging()) return;
7640
7617
  // kludge to get dataset to recalculate internal bounding boxes
7641
7618
  hit.getHitTarget().arcs.transformPoints(function() {});
7642
7619
  clearHoverVertex();
7643
-
7644
-
7645
-
7646
- fire('vertex_dragend');
7647
- draggedVertexIds = null;
7648
- activeShapeId = -1;
7649
- // redraw data layer
7620
+ gui.dispatchEvent('vertex_dragend', dragInfo);
7650
7621
  gui.dispatchEvent('map-needs-refresh');
7622
+ dragInfo = null;
7651
7623
  });
7652
7624
 
7653
- // select clicked vertices
7654
- hit.on('click', function(e) {
7655
- if (!active(e)) return;
7656
- var vertices = findDraggableVertices(e); // same selection criteria as for dragging
7657
-
7658
- // CASE: no draggable vertices
7659
- // if selected vertices, deselect, else no-op
7660
- // CASE: draggable vertices
7661
- // if vertex is arc endpoint, ignore
7662
- // if vertex is selected, deselect
7663
- // if vertex is not selected, select
7664
-
7665
- // if (vertices) {
7666
- // toggleVertexSelection(vertices);
7667
- // } else if (selectedVertexIds) {
7668
- // toggleVertexSelection(selectedVertexIds);
7669
- // }
7670
-
7625
+ hit.on('dblclick', function(e) {
7626
+ if (!active()) return;
7627
+ var info = findDraggableVertices(e); // same selection criteria as for dragging
7628
+ if (!info) return;
7629
+ var target = hit.getHitTarget();
7630
+ var vId = info.ids[0];
7631
+ if (internal.vertexIsArcStart(vId, target.arcs) ||
7632
+ internal.vertexIsArcEnd(vId, target.arcs)) {
7633
+ // TODO: support removing arc endpoints
7634
+ return;
7635
+ }
7636
+ gui.dispatchEvent('vertex_delete', {
7637
+ vertex_id: vId
7638
+ });
7639
+ internal.deleteVertex(target.arcs, vId);
7640
+ clearHoverVertex();
7641
+ gui.dispatchEvent('map-needs-refresh');
7671
7642
  });
7672
7643
 
7673
7644
  // highlight hit vertex in path edit mode
7674
7645
  hit.on('hover', function(e) {
7675
7646
  activeMidpoint = null;
7676
- if (!active(e) || draggedVertexIds) return; // no hover effect while dragging
7677
- var vertexIds = findDraggableVertices(e);
7678
- if (vertexIds) {
7679
- setHoverVertex(vertexIds[0]);
7647
+ if (!active() || dragging()) return; // no hover effect while dragging
7648
+ var info = findDraggableVertices(e);
7649
+ if (info) {
7650
+ // hovering near a vertex: highlight the vertex
7651
+ setHoverVertex(info.ids[0]);
7680
7652
  return;
7681
7653
  }
7654
+ // if hovering near a segment midpoint: show the midpoint and save midpoint info
7655
+ var p = ext.translatePixelCoords(e.x, e.y);
7682
7656
  var target = hit.getHitTarget();
7683
- // vertex insertion doesn't work yet with simplification applied
7684
- if (!target.arcs.isFlat()) return;
7685
7657
  var shp = target.layer.shapes[e.id];
7686
- var p = ext.translatePixelCoords(e.x, e.y);
7687
7658
  var midpoint = findNearestMidpoint(p, shp, target.arcs);
7688
- if (midpoint && midpoint.distance / ext.getPixelSize() < MIDPOINT_THRESHOLD) {
7659
+ if (midpoint &&
7660
+ midpoint.distance / ext.getPixelSize() < MIDPOINT_THRESHOLD &&
7661
+ target.arcs.isFlat()) { // vertex insertion not supported with simplification
7689
7662
  hit.setHoverVertex(midpoint.point);
7690
7663
  activeMidpoint = midpoint;
7691
- } else {
7692
- clearHoverVertex();
7664
+ return;
7693
7665
  }
7666
+ // pointer is not over a vertex or midpoint: clear hover effect
7667
+ clearHoverVertex();
7694
7668
  }, null, 100);
7695
7669
  }
7696
7670
 
7697
-
7698
7671
  // Given a location @p (e.g. corresponding to the mouse pointer location),
7699
7672
  // find the midpoint of two vertices on @shp suitable for inserting a new vertex,
7700
7673
  // but only if:
@@ -7928,7 +7901,7 @@
7928
7901
  var ids = o.ids.filter(function(i) {
7929
7902
  return i != o.id; // move selected id to the end
7930
7903
  });
7931
- if (o.id > -1) {
7904
+ if (o.id > -1) { // pinned or hover style
7932
7905
  topStyle = getSelectedFeatureStyle(lyr, o);
7933
7906
  topIdx = ids.length;
7934
7907
  ids.push(o.id); // put the pinned/hover feature last in the render order
@@ -8415,17 +8388,6 @@
8415
8388
  }
8416
8389
  _ctx.fill();
8417
8390
  _ctx.closePath();
8418
-
8419
- if (style.selected_points) {
8420
- _ctx.beginPath();
8421
- _ctx.fillStyle = 'magenta';
8422
- for (i=0; i<style.selected_points.length; i++) {
8423
- p = style.selected_points[i];
8424
- drawCircle(p[0] * t.mx + t.bx, p[1] * t.my + t.by, radius2, _ctx);
8425
- }
8426
- _ctx.fill();
8427
- _ctx.closePath();
8428
- }
8429
8391
  };
8430
8392
 
8431
8393
  // Optimized to draw paths in same-style batches (faster Canvas drawing)
package/www/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.5.92";
3
+ var VERSION = "0.5.94";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({