mapshaper 0.5.93 → 0.5.96
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 +1323 -0
- package/mapshaper.js +421 -383
- package/package.json +1 -1
- package/www/mapshaper-gui.js +139 -104
- package/www/mapshaper.js +421 -383
- package/www/nacis/Makefile +0 -22
- package/www/nacis/Makefile.txt +0 -22
- package/www/nacis/images/close.png +0 -0
- package/www/nacis/images/eye.png +0 -0
- package/www/nacis/images/eye2.png +0 -0
- package/www/nacis/index.html +0 -262
- package/www/nacis/manifest.js +0 -27
- package/www/nacis/map.svg +0 -12308
package/package.json
CHANGED
package/www/mapshaper-gui.js
CHANGED
|
@@ -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
|
|
3738
|
-
|
|
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('
|
|
3752
|
+
gui.on('vertex_delete', function(e) {
|
|
3742
3753
|
var target = gui.model.getActiveLayer();
|
|
3743
3754
|
var arcs = target.dataset.arcs;
|
|
3744
|
-
var
|
|
3755
|
+
var p = arcs.getVertex2(e.vertex_id);
|
|
3756
|
+
var redo = function() {
|
|
3745
3757
|
internal.deleteVertex(arcs, e.vertex_id);
|
|
3746
3758
|
};
|
|
3747
|
-
var
|
|
3748
|
-
internal.insertVertex(arcs, e.vertex_id,
|
|
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(
|
|
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);
|
|
@@ -5611,14 +5623,11 @@
|
|
|
5611
5623
|
}
|
|
5612
5624
|
|
|
5613
5625
|
function vertexTest(x, y) {
|
|
5614
|
-
var maxDist = getZoomAdjustedHitBuffer(
|
|
5615
|
-
bufDist = getZoomAdjustedHitBuffer(0.05), // tiny threshold for hitting almost-identical lines
|
|
5626
|
+
var maxDist = getZoomAdjustedHitBuffer(25, 2),
|
|
5616
5627
|
cands = findHitCandidates(x, y, maxDist);
|
|
5617
5628
|
sortByDistance(x, y, cands, displayLayer.arcs);
|
|
5618
|
-
cands = pickNearestCandidates(cands,
|
|
5619
|
-
var arcs = cands.map(function(cand) { return absArcId(cand.info.arcId); });
|
|
5629
|
+
cands = pickNearestCandidates(cands, 0, maxDist);
|
|
5620
5630
|
return {
|
|
5621
|
-
arcs: utils$1.uniq(arcs),
|
|
5622
5631
|
ids: utils$1.pluck(cands, 'id')
|
|
5623
5632
|
};
|
|
5624
5633
|
}
|
|
@@ -6170,9 +6179,11 @@
|
|
|
6170
6179
|
newData = noHitData();
|
|
6171
6180
|
selectionIds = [];
|
|
6172
6181
|
}
|
|
6182
|
+
|
|
6173
6183
|
if (!testHitChange(storedData, newData)) {
|
|
6174
6184
|
return;
|
|
6175
6185
|
}
|
|
6186
|
+
|
|
6176
6187
|
storedData = newData;
|
|
6177
6188
|
gui.container.findChild('.map-layers').classed('symbol-hit', nonEmpty);
|
|
6178
6189
|
if (active) {
|
|
@@ -7522,25 +7533,20 @@
|
|
|
7522
7533
|
}
|
|
7523
7534
|
}
|
|
7524
7535
|
|
|
7536
|
+
// pointer thresholds for hovering near a vertex or segment midpoint
|
|
7525
7537
|
var HOVER_THRESHOLD = 8;
|
|
7526
|
-
var MIDPOINT_THRESHOLD =
|
|
7527
|
-
|
|
7538
|
+
var MIDPOINT_THRESHOLD = 11;
|
|
7528
7539
|
|
|
7529
7540
|
function initVertexDragging(gui, ext, hit) {
|
|
7530
|
-
var
|
|
7531
|
-
var
|
|
7532
|
-
var selectedVertexIds = null;
|
|
7533
|
-
var activeMidpoint; // {point, segment}
|
|
7541
|
+
var insertionPoint;
|
|
7542
|
+
var dragInfo;
|
|
7534
7543
|
|
|
7535
|
-
function active(
|
|
7536
|
-
return
|
|
7544
|
+
function active() {
|
|
7545
|
+
return gui.interaction.getMode() == 'vertices';
|
|
7537
7546
|
}
|
|
7538
7547
|
|
|
7539
|
-
function
|
|
7540
|
-
|
|
7541
|
-
FID: activeShapeId,
|
|
7542
|
-
vertex_ids: draggedVertexIds
|
|
7543
|
-
});
|
|
7548
|
+
function dragging() {
|
|
7549
|
+
return active() && !!dragInfo;
|
|
7544
7550
|
}
|
|
7545
7551
|
|
|
7546
7552
|
function setHoverVertex(id) {
|
|
@@ -7550,7 +7556,6 @@
|
|
|
7550
7556
|
|
|
7551
7557
|
function clearHoverVertex() {
|
|
7552
7558
|
hit.clearVertexOverlay();
|
|
7553
|
-
// gui.state.vertex_overlay = null;
|
|
7554
7559
|
}
|
|
7555
7560
|
|
|
7556
7561
|
function findDraggableVertices(e) {
|
|
@@ -7562,90 +7567,103 @@
|
|
|
7562
7567
|
var dist = geom.distance2D(p[0], p[1], p2[0], p2[1]);
|
|
7563
7568
|
var pixelDist = dist / ext.getPixelSize();
|
|
7564
7569
|
if (pixelDist > HOVER_THRESHOLD) {
|
|
7565
|
-
draggedVertexIds = null;
|
|
7566
7570
|
return null;
|
|
7567
7571
|
}
|
|
7568
|
-
return
|
|
7572
|
+
var points = nearestIds.map(function(i) {return target.arcs.getVertex2(i);});
|
|
7573
|
+
return {
|
|
7574
|
+
ids: nearestIds,
|
|
7575
|
+
points: points
|
|
7576
|
+
};
|
|
7569
7577
|
}
|
|
7570
7578
|
|
|
7571
|
-
function
|
|
7579
|
+
function findVertexInsertionPoint(e) {
|
|
7572
7580
|
var target = hit.getHitTarget();
|
|
7573
|
-
|
|
7581
|
+
if (!target.arcs.isFlat()) return null; // vertex insertion not supported with simplification
|
|
7582
|
+
var p = ext.translatePixelCoords(e.x, e.y);
|
|
7583
|
+
var shp = target.layer.shapes[e.id];
|
|
7584
|
+
var midpoint = findNearestMidpoint(p, shp, target.arcs);
|
|
7585
|
+
if (!midpoint ||
|
|
7586
|
+
midpoint.distance / ext.getPixelSize() > MIDPOINT_THRESHOLD) return null;
|
|
7587
|
+
return midpoint;
|
|
7574
7588
|
}
|
|
7575
7589
|
|
|
7576
7590
|
hit.on('dragstart', function(e) {
|
|
7577
|
-
if (!active(
|
|
7578
|
-
if (
|
|
7579
|
-
|
|
7580
|
-
|
|
7581
|
-
|
|
7582
|
-
|
|
7583
|
-
|
|
7584
|
-
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
});
|
|
7588
|
-
activeMidpoint = null;
|
|
7591
|
+
if (!active()) return;
|
|
7592
|
+
if (insertionPoint) {
|
|
7593
|
+
var target = hit.getHitTarget();
|
|
7594
|
+
internal.insertVertex(target.arcs, insertionPoint.i, insertionPoint.point);
|
|
7595
|
+
dragInfo = {
|
|
7596
|
+
insertion: true,
|
|
7597
|
+
ids: [insertionPoint.i],
|
|
7598
|
+
points: [insertionPoint.point]
|
|
7599
|
+
};
|
|
7600
|
+
insertionPoint = null;
|
|
7589
7601
|
} else {
|
|
7590
|
-
|
|
7602
|
+
dragInfo = findDraggableVertices(e);
|
|
7603
|
+
}
|
|
7604
|
+
if (dragInfo) {
|
|
7605
|
+
setHoverVertex(dragInfo.ids[0]);
|
|
7591
7606
|
}
|
|
7592
|
-
if (!draggedVertexIds) return;
|
|
7593
|
-
setHoverVertex(draggedVertexIds[0]);
|
|
7594
|
-
activeShapeId = e.id;
|
|
7595
|
-
fire('vertex_dragstart');
|
|
7596
7607
|
});
|
|
7597
7608
|
|
|
7598
7609
|
hit.on('drag', function(e) {
|
|
7599
|
-
if (!
|
|
7610
|
+
if (!dragging()) return;
|
|
7600
7611
|
var target = hit.getHitTarget();
|
|
7601
7612
|
var p = ext.translatePixelCoords(e.x, e.y);
|
|
7602
7613
|
if (gui.keyboard.shiftIsPressed()) {
|
|
7603
|
-
internal.snapPointToArcEndpoint(p,
|
|
7614
|
+
internal.snapPointToArcEndpoint(p, dragInfo.ids, target.arcs);
|
|
7604
7615
|
}
|
|
7605
|
-
internal.snapVerticesToPoint(
|
|
7606
|
-
setHoverVertex(
|
|
7616
|
+
internal.snapVerticesToPoint(dragInfo.ids, p, target.arcs);
|
|
7617
|
+
setHoverVertex(dragInfo.ids[0]);
|
|
7607
7618
|
// redrawing the whole map updates the data layer as well as the overlay layer
|
|
7608
7619
|
// gui.dispatchEvent('map-needs-refresh');
|
|
7609
7620
|
});
|
|
7610
7621
|
|
|
7611
7622
|
hit.on('dragend', function(e) {
|
|
7612
|
-
if (!
|
|
7623
|
+
if (!dragging()) return;
|
|
7613
7624
|
// kludge to get dataset to recalculate internal bounding boxes
|
|
7614
7625
|
hit.getHitTarget().arcs.transformPoints(function() {});
|
|
7615
7626
|
clearHoverVertex();
|
|
7616
|
-
|
|
7617
|
-
draggedVertexIds = null;
|
|
7618
|
-
activeShapeId = -1;
|
|
7619
|
-
// redraw data layer
|
|
7627
|
+
gui.dispatchEvent('vertex_dragend', dragInfo);
|
|
7620
7628
|
gui.dispatchEvent('map-needs-refresh');
|
|
7629
|
+
dragInfo = null;
|
|
7621
7630
|
});
|
|
7622
7631
|
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7632
|
+
hit.on('dblclick', function(e) {
|
|
7633
|
+
if (!active()) return;
|
|
7634
|
+
var info = findDraggableVertices(e); // same selection criteria as for dragging
|
|
7635
|
+
if (!info) return;
|
|
7636
|
+
var target = hit.getHitTarget();
|
|
7637
|
+
var vId = info.ids[0];
|
|
7638
|
+
if (internal.vertexIsArcStart(vId, target.arcs) ||
|
|
7639
|
+
internal.vertexIsArcEnd(vId, target.arcs)) {
|
|
7640
|
+
// TODO: support removing arc endpoints
|
|
7641
|
+
return;
|
|
7642
|
+
}
|
|
7643
|
+
gui.dispatchEvent('vertex_delete', {
|
|
7644
|
+
vertex_id: vId
|
|
7645
|
+
});
|
|
7646
|
+
internal.deleteVertex(target.arcs, vId);
|
|
7647
|
+
clearHoverVertex();
|
|
7648
|
+
gui.dispatchEvent('map-needs-refresh');
|
|
7628
7649
|
});
|
|
7629
7650
|
|
|
7630
7651
|
// highlight hit vertex in path edit mode
|
|
7631
7652
|
hit.on('hover', function(e) {
|
|
7632
|
-
|
|
7633
|
-
if (!active(
|
|
7634
|
-
var
|
|
7635
|
-
if (
|
|
7636
|
-
|
|
7653
|
+
insertionPoint = null;
|
|
7654
|
+
if (!active() || dragging()) return; // no hover effect while dragging
|
|
7655
|
+
var info = findDraggableVertices(e);
|
|
7656
|
+
if (info) {
|
|
7657
|
+
// hovering near a vertex: highlight the vertex
|
|
7658
|
+
setHoverVertex(info.ids[0]);
|
|
7637
7659
|
return;
|
|
7638
7660
|
}
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
if (
|
|
7642
|
-
|
|
7643
|
-
var p = ext.translatePixelCoords(e.x, e.y);
|
|
7644
|
-
var midpoint = findNearestMidpoint(p, shp, target.arcs);
|
|
7645
|
-
if (midpoint && midpoint.distance / ext.getPixelSize() < MIDPOINT_THRESHOLD) {
|
|
7646
|
-
hit.setHoverVertex(midpoint.point);
|
|
7647
|
-
activeMidpoint = midpoint;
|
|
7661
|
+
// if hovering near a segment midpoint: show the midpoint and save midpoint info
|
|
7662
|
+
insertionPoint = findVertexInsertionPoint(e);
|
|
7663
|
+
if (insertionPoint) {
|
|
7664
|
+
hit.setHoverVertex(insertionPoint.point);
|
|
7648
7665
|
} else {
|
|
7666
|
+
// pointer is not over a vertex: clear any hover effect
|
|
7649
7667
|
clearHoverVertex();
|
|
7650
7668
|
}
|
|
7651
7669
|
}, null, 100);
|
|
@@ -7653,15 +7671,8 @@
|
|
|
7653
7671
|
|
|
7654
7672
|
|
|
7655
7673
|
// Given a location @p (e.g. corresponding to the mouse pointer location),
|
|
7656
|
-
// find the midpoint of two vertices on @shp suitable for inserting a new vertex
|
|
7657
|
-
// but only if:
|
|
7658
|
-
// 1. point @p is closer to the midpoint than either adjacent vertex
|
|
7659
|
-
// 2. the segment containing @p is longer than a minimum distance in pixels.
|
|
7660
|
-
//
|
|
7674
|
+
// find the midpoint of two vertices on @shp suitable for inserting a new vertex
|
|
7661
7675
|
function findNearestMidpoint(p, shp, arcs) {
|
|
7662
|
-
// var v1 = internal.findNearestVertex(p[0], p[1], shp, arcs);
|
|
7663
|
-
// var v0 = internal.findAdjacentVertex(v1, shp, arcs, -1);
|
|
7664
|
-
// var v2 = internal.findAdjacentVertex(v1, shp, arcs, 1);
|
|
7665
7676
|
var minDist = Infinity, v;
|
|
7666
7677
|
internal.forEachSegmentInShape(shp, arcs, function(i, j, xx, yy) {
|
|
7667
7678
|
var x1 = xx[i],
|
|
@@ -7676,6 +7687,7 @@
|
|
|
7676
7687
|
v = {
|
|
7677
7688
|
i: (i < j ? i : j) + 1, // insertion point
|
|
7678
7689
|
segment: [i, j],
|
|
7690
|
+
segmentLen: geom.distance2D(x1, y1, x2, y2),
|
|
7679
7691
|
point: [cx, cy],
|
|
7680
7692
|
distance: dist
|
|
7681
7693
|
};
|
|
@@ -7858,6 +7870,20 @@
|
|
|
7858
7870
|
return style;
|
|
7859
7871
|
}
|
|
7860
7872
|
|
|
7873
|
+
// style for vertex edit mode
|
|
7874
|
+
function getVertexStyle(lyr, o) {
|
|
7875
|
+
return {
|
|
7876
|
+
ids: o.ids,
|
|
7877
|
+
overlay: true,
|
|
7878
|
+
strokeColor: black,
|
|
7879
|
+
strokeWidth: 1.5,
|
|
7880
|
+
vertices: true,
|
|
7881
|
+
vertex_overlay: o.hit_coordinates || null,
|
|
7882
|
+
selected_points: o.selected_points || null,
|
|
7883
|
+
fillColor: null
|
|
7884
|
+
};
|
|
7885
|
+
}
|
|
7886
|
+
|
|
7861
7887
|
// Returns a display style for the overlay layer.
|
|
7862
7888
|
// The overlay layer renders several kinds of feature, each of which is displayed
|
|
7863
7889
|
// with a different style.
|
|
@@ -7867,40 +7893,45 @@
|
|
|
7867
7893
|
// * pinned shapes
|
|
7868
7894
|
//
|
|
7869
7895
|
function getOverlayStyle(lyr, o) {
|
|
7896
|
+
if (o.mode == 'vertices') {
|
|
7897
|
+
return getVertexStyle(lyr, o);
|
|
7898
|
+
}
|
|
7870
7899
|
var geomType = lyr.geometry_type;
|
|
7871
7900
|
var topId = o.id; // pinned id (if pinned) or hover id
|
|
7872
7901
|
var topIdx = -1;
|
|
7873
7902
|
var styler = function(style, i) {
|
|
7874
7903
|
utils$1.extend(style, i === topIdx ? topStyle: baseStyle);
|
|
7875
|
-
// kludge to show vertices when editing path shapes
|
|
7876
|
-
if (o.mode == 'vertices') {
|
|
7877
|
-
style.vertices = true;
|
|
7878
|
-
style.vertex_overlay = o.hit_coordinates || null;
|
|
7879
|
-
style.fillColor = null;
|
|
7880
|
-
}
|
|
7881
7904
|
};
|
|
7882
7905
|
var baseStyle = getDefaultStyle(lyr, selectionStyles[geomType]);
|
|
7883
7906
|
var topStyle;
|
|
7884
7907
|
var ids = o.ids.filter(function(i) {
|
|
7885
7908
|
return i != o.id; // move selected id to the end
|
|
7886
7909
|
});
|
|
7887
|
-
if (o.id > -1) {
|
|
7910
|
+
if (o.id > -1) { // pinned or hover style
|
|
7888
7911
|
topStyle = getSelectedFeatureStyle(lyr, o);
|
|
7889
7912
|
topIdx = ids.length;
|
|
7890
7913
|
ids.push(o.id); // put the pinned/hover feature last in the render order
|
|
7891
7914
|
}
|
|
7892
|
-
var
|
|
7915
|
+
var style = {
|
|
7893
7916
|
styler: styler,
|
|
7894
7917
|
ids: ids,
|
|
7895
7918
|
overlay: true
|
|
7896
7919
|
};
|
|
7920
|
+
// kludge to show vertices when editing path shapes
|
|
7921
|
+
if (o.mode == 'vertices') {
|
|
7922
|
+
style.vertices = true;
|
|
7923
|
+
style.vertex_overlay = o.hit_coordinates || null;
|
|
7924
|
+
style.selected_points = o.selected_points || null;
|
|
7925
|
+
style.fillColor = null;
|
|
7926
|
+
}
|
|
7927
|
+
|
|
7897
7928
|
if (layerHasCanvasDisplayStyle(lyr)) {
|
|
7898
7929
|
if (geomType == 'point') {
|
|
7899
|
-
|
|
7930
|
+
style.styler = getOverlayPointStyler(getCanvasDisplayStyle(lyr).styler, styler);
|
|
7900
7931
|
}
|
|
7901
|
-
|
|
7932
|
+
style.type = 'styled';
|
|
7902
7933
|
}
|
|
7903
|
-
return ids.length > 0 ?
|
|
7934
|
+
return ids.length > 0 ? style : null;
|
|
7904
7935
|
}
|
|
7905
7936
|
|
|
7906
7937
|
function getSelectedFeatureStyle(lyr, o) {
|
|
@@ -8348,24 +8379,28 @@
|
|
|
8348
8379
|
_self.drawVertices = function(shapes, arcs, style, filter) {
|
|
8349
8380
|
var iter = new internal.ShapeIter(arcs);
|
|
8350
8381
|
var t = getScaledTransform(_ext);
|
|
8382
|
+
var bounds = _ext.getBounds();
|
|
8351
8383
|
var radius = (style.strokeWidth > 2 ? style.strokeWidth * 0.9 : 2) * GUI.getPixelRatio() * getScaledLineScale(_ext);
|
|
8352
8384
|
var color = style.strokeColor || 'black';
|
|
8353
|
-
|
|
8385
|
+
|
|
8386
|
+
var i, j, p;
|
|
8354
8387
|
_ctx.beginPath();
|
|
8355
8388
|
_ctx.fillStyle = color;
|
|
8356
|
-
for (
|
|
8389
|
+
for (i=0; i<shapes.length; i++) {
|
|
8357
8390
|
var shp = shapes[i];
|
|
8358
8391
|
if (!shp || filter && !filter(shp)) continue;
|
|
8359
|
-
for (
|
|
8392
|
+
for (j=0; j<shp.length; j++) {
|
|
8360
8393
|
iter.init(shp[j]);
|
|
8361
8394
|
while (iter.hasNext()) {
|
|
8395
|
+
if (!bounds.containsPoint(iter.x, iter.y)) continue;
|
|
8362
8396
|
drawCircle(iter.x * t.mx + t.bx, iter.y * t.my + t.by, radius, _ctx);
|
|
8363
8397
|
}
|
|
8364
8398
|
}
|
|
8365
8399
|
}
|
|
8400
|
+
|
|
8366
8401
|
if (style.vertex_overlay) {
|
|
8367
|
-
|
|
8368
|
-
drawCircle(p[0] * t.mx + t.bx, p[1] * t.my + t.by,
|
|
8402
|
+
p = style.vertex_overlay;
|
|
8403
|
+
drawCircle(p[0] * t.mx + t.bx, p[1] * t.my + t.by, radius * 1.5, _ctx);
|
|
8369
8404
|
}
|
|
8370
8405
|
_ctx.fill();
|
|
8371
8406
|
_ctx.closePath();
|