mapshaper 0.6.77 → 0.6.78
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 +14 -12
- package/package.json +1 -1
- package/www/mapshaper-gui.js +152 -97
- package/www/mapshaper.js +14 -12
- package/www/page.css +4 -2
package/mapshaper.js
CHANGED
|
@@ -4278,6 +4278,10 @@
|
|
|
4278
4278
|
return data;
|
|
4279
4279
|
}
|
|
4280
4280
|
|
|
4281
|
+
function layerHasAttributeData(lyr) {
|
|
4282
|
+
return lyr.data && lyr.data.getFields().length > 0;
|
|
4283
|
+
}
|
|
4284
|
+
|
|
4281
4285
|
function layerHasNonNullData(lyr) {
|
|
4282
4286
|
return lyr.data && getFirstNonEmptyRecord(lyr.data.getRecords()) ? true : false;
|
|
4283
4287
|
}
|
|
@@ -4551,6 +4555,7 @@
|
|
|
4551
4555
|
__proto__: null,
|
|
4552
4556
|
insertFieldValues: insertFieldValues,
|
|
4553
4557
|
getLayerDataTable: getLayerDataTable,
|
|
4558
|
+
layerHasAttributeData: layerHasAttributeData,
|
|
4554
4559
|
layerHasNonNullData: layerHasNonNullData,
|
|
4555
4560
|
layerHasGeometry: layerHasGeometry,
|
|
4556
4561
|
layerIsGeometric: layerIsGeometric,
|
|
@@ -18025,11 +18030,10 @@
|
|
|
18025
18030
|
opts = utils.extend({}, opts);
|
|
18026
18031
|
opts.rfc7946 = !opts.gj2008; // use RFC 7946 as the default
|
|
18027
18032
|
var extension = opts.extension || "json";
|
|
18028
|
-
var layerGroups
|
|
18033
|
+
var layerGroups;
|
|
18029
18034
|
|
|
18030
18035
|
if (opts.rfc7946) {
|
|
18031
|
-
|
|
18032
|
-
if (warn) message(warn);
|
|
18036
|
+
warnIfNotWgs84(dataset);
|
|
18033
18037
|
}
|
|
18034
18038
|
|
|
18035
18039
|
if (opts.file) {
|
|
@@ -18120,14 +18124,12 @@
|
|
|
18120
18124
|
return feat;
|
|
18121
18125
|
}
|
|
18122
18126
|
|
|
18123
|
-
function
|
|
18127
|
+
function warnIfNotWgs84(dataset) {
|
|
18124
18128
|
var P = getDatasetCRS(dataset);
|
|
18125
|
-
|
|
18126
|
-
|
|
18127
|
-
|
|
18128
|
-
|
|
18129
|
-
}
|
|
18130
|
-
return str;
|
|
18129
|
+
if (P && isLatLngCRS(P) || datasetIsEmpty(dataset)) return;
|
|
18130
|
+
var str = 'RFC 7946 warning: non-WGS84 GeoJSON output.';
|
|
18131
|
+
if (P) str += ' Tip: use "-proj wgs84" to convert.';
|
|
18132
|
+
message(str);
|
|
18131
18133
|
}
|
|
18132
18134
|
|
|
18133
18135
|
function getDatasetBbox(dataset, rfc7946) {
|
|
@@ -18397,7 +18399,7 @@
|
|
|
18397
18399
|
'default': GeoJSON,
|
|
18398
18400
|
exportGeoJSON: exportGeoJSON,
|
|
18399
18401
|
exportLayerAsGeoJSON: exportLayerAsGeoJSON,
|
|
18400
|
-
|
|
18402
|
+
warnIfNotWgs84: warnIfNotWgs84,
|
|
18401
18403
|
getDatasetBbox: getDatasetBbox,
|
|
18402
18404
|
exportDatasetAsGeoJSON: exportDatasetAsGeoJSON,
|
|
18403
18405
|
preserveOriginalCRS: preserveOriginalCRS,
|
|
@@ -45530,7 +45532,7 @@ ${svg}
|
|
|
45530
45532
|
});
|
|
45531
45533
|
}
|
|
45532
45534
|
|
|
45533
|
-
var version = "0.6.
|
|
45535
|
+
var version = "0.6.78";
|
|
45534
45536
|
|
|
45535
45537
|
// Parse command line args into commands and run them
|
|
45536
45538
|
// Function takes an optional Node-style callback. A Promise is returned if no callback is given.
|
package/package.json
CHANGED
package/www/mapshaper-gui.js
CHANGED
|
@@ -1738,12 +1738,12 @@
|
|
|
1738
1738
|
var btn = el.findChild('.btn').on('click', function() {
|
|
1739
1739
|
var nameStr = name.node().value.trim();
|
|
1740
1740
|
var type = el.findChild('input:checked').node().value;
|
|
1741
|
-
|
|
1741
|
+
addEmptyLayer(gui, nameStr, type);
|
|
1742
1742
|
popup.close();
|
|
1743
1743
|
});
|
|
1744
1744
|
}
|
|
1745
1745
|
|
|
1746
|
-
function
|
|
1746
|
+
function addEmptyLayer(gui, name, type) {
|
|
1747
1747
|
var targ = gui.model.getActiveLayer();
|
|
1748
1748
|
var crsInfo = targ && internal.getDatasetCrsInfo(targ.dataset);
|
|
1749
1749
|
var dataset = {
|
|
@@ -2716,7 +2716,8 @@
|
|
|
2716
2716
|
if (opts.interactionMode == 'vertices') {
|
|
2717
2717
|
return getVertexStyle(baseLyr, o);
|
|
2718
2718
|
}
|
|
2719
|
-
if (opts.interactionMode == '
|
|
2719
|
+
if (opts.interactionMode == 'edit_lines' ||
|
|
2720
|
+
opts.interactionMode == 'edit_polygons') {
|
|
2720
2721
|
return getLineEditingStyle(o);
|
|
2721
2722
|
}
|
|
2722
2723
|
var geomType = baseLyr.geometry_type;
|
|
@@ -3501,10 +3502,6 @@
|
|
|
3501
3502
|
return internal.getUnfilteredArcLength(arcId, target.gui.source.dataset.arcs);
|
|
3502
3503
|
}
|
|
3503
3504
|
|
|
3504
|
-
function getPointCoords(lyr, fid) {
|
|
3505
|
-
return internal.cloneShape(lyr.shapes[fid]);
|
|
3506
|
-
}
|
|
3507
|
-
|
|
3508
3505
|
function getVertexCoords(lyr, id) {
|
|
3509
3506
|
return lyr.gui.source.dataset.arcs.getVertex2(id);
|
|
3510
3507
|
}
|
|
@@ -3518,14 +3515,6 @@
|
|
|
3518
3515
|
}
|
|
3519
3516
|
}
|
|
3520
3517
|
|
|
3521
|
-
// coords: [x, y] point in data CRS (not display CRS)
|
|
3522
|
-
function setPointCoords(lyr, fid, coords) {
|
|
3523
|
-
lyr.shapes[fid] = coords;
|
|
3524
|
-
if (isProjectedLayer(lyr)) {
|
|
3525
|
-
lyr.shapes[fid] = projectPointCoords(coords, lyr.gui.projectPoint);
|
|
3526
|
-
}
|
|
3527
|
-
}
|
|
3528
|
-
|
|
3529
3518
|
function updateVertexCoords(lyr, ids) {
|
|
3530
3519
|
if (!isProjectedLayer(lyr)) return;
|
|
3531
3520
|
var p = lyr.gui.displayArcs.getVertex2(ids[0]);
|
|
@@ -3545,10 +3534,31 @@
|
|
|
3545
3534
|
// Update source data coordinates by projecting display coordinates
|
|
3546
3535
|
function updatePointCoords(lyr, fid) {
|
|
3547
3536
|
if (!isProjectedLayer(lyr)) return;
|
|
3548
|
-
var displayShp = lyr.shapes[fid];
|
|
3537
|
+
var displayShp = lyr.gui.displayLayer.shapes[fid];
|
|
3549
3538
|
lyr.shapes[fid] = projectPointCoords(displayShp, lyr.gui.invertPoint);
|
|
3550
3539
|
}
|
|
3551
3540
|
|
|
3541
|
+
// coords: [[x, y]] point in data CRS (not display CRS)
|
|
3542
|
+
function setPointCoords(lyr, fid, coords) {
|
|
3543
|
+
lyr.shapes[fid] = coords;
|
|
3544
|
+
if (isProjectedLayer(lyr)) {
|
|
3545
|
+
lyr.gui.displayLayer.shapes[fid] = projectPointCoords(coords, lyr.gui.projectPoint);
|
|
3546
|
+
}
|
|
3547
|
+
}
|
|
3548
|
+
|
|
3549
|
+
// return an [[x, y]] point in data CRS
|
|
3550
|
+
function getPointCoords(lyr, fid) {
|
|
3551
|
+
var coords = lyr.geometry_type == 'point' && lyr.shapes[fid];
|
|
3552
|
+
if (!coords || coords.length != 1) {
|
|
3553
|
+
return null;
|
|
3554
|
+
}
|
|
3555
|
+
return internal.cloneShape(coords);
|
|
3556
|
+
}
|
|
3557
|
+
|
|
3558
|
+
// export function getPointCoords(lyr, fid) {
|
|
3559
|
+
// return internal.cloneShape(lyr.shapes[fid]);
|
|
3560
|
+
// }
|
|
3561
|
+
|
|
3552
3562
|
function projectPointCoords(src, proj) {
|
|
3553
3563
|
var dest = [], p;
|
|
3554
3564
|
for (var i=0; i<src.length; i++) {
|
|
@@ -5609,7 +5619,10 @@
|
|
|
5609
5619
|
};
|
|
5610
5620
|
|
|
5611
5621
|
function updateVisibility() {
|
|
5612
|
-
|
|
5622
|
+
var noData = !gui.model.getActiveLayer();
|
|
5623
|
+
if (GUI.isActiveInstance(gui) && !_hidden && !noData) {
|
|
5624
|
+
buttons.show();
|
|
5625
|
+
} else if (noData && gui.getMode() != 'import') {
|
|
5613
5626
|
buttons.show();
|
|
5614
5627
|
} else {
|
|
5615
5628
|
buttons.hide();
|
|
@@ -5758,12 +5771,13 @@
|
|
|
5758
5771
|
|
|
5759
5772
|
var menus = {
|
|
5760
5773
|
standard: ['info', 'selection', 'box'],
|
|
5761
|
-
|
|
5774
|
+
empty: ['edit_points', 'edit_lines', 'edit_polygons'],
|
|
5775
|
+
polygons: ['info', 'selection', 'box', 'edit_polygons'],
|
|
5762
5776
|
rectangles: ['info', 'selection', 'box', 'rectangles'],
|
|
5763
|
-
lines: ['info', 'selection', 'box' , '
|
|
5777
|
+
lines: ['info', 'selection', 'box' , 'edit_lines'],
|
|
5764
5778
|
table: ['info', 'selection'],
|
|
5765
|
-
labels: ['info', 'selection', 'box', 'labels', '
|
|
5766
|
-
points: ['info', 'selection', 'box', '
|
|
5779
|
+
labels: ['info', 'selection', 'box', 'labels', 'edit_points'],
|
|
5780
|
+
points: ['info', 'selection', 'box', 'edit_points'] // , 'add-points'
|
|
5767
5781
|
};
|
|
5768
5782
|
|
|
5769
5783
|
var prompts = {
|
|
@@ -5778,11 +5792,12 @@
|
|
|
5778
5792
|
box: 'shift-drag box tool',
|
|
5779
5793
|
data: 'edit attributes',
|
|
5780
5794
|
labels: 'position labels',
|
|
5781
|
-
|
|
5795
|
+
edit_points: 'draw/edit points',
|
|
5796
|
+
edit_lines: 'draw/edit lines',
|
|
5797
|
+
edit_polygons: 'draw/edit polygons',
|
|
5782
5798
|
vertices: 'edit vertices',
|
|
5783
5799
|
selection: 'selection tool',
|
|
5784
5800
|
'add-points': 'add points',
|
|
5785
|
-
drawing: 'draw/reshape tool',
|
|
5786
5801
|
rectangles: 'drag-to-resize',
|
|
5787
5802
|
off: 'turn off'
|
|
5788
5803
|
};
|
|
@@ -5791,6 +5806,7 @@
|
|
|
5791
5806
|
|
|
5792
5807
|
// state variables
|
|
5793
5808
|
var _editMode = 'off';
|
|
5809
|
+
var _prevMode;
|
|
5794
5810
|
var _menuOpen = false;
|
|
5795
5811
|
|
|
5796
5812
|
// Only render edit mode button/menu if this option is present
|
|
@@ -5838,11 +5854,11 @@
|
|
|
5838
5854
|
};
|
|
5839
5855
|
|
|
5840
5856
|
this.modeUsesHitDetection = function(mode) {
|
|
5841
|
-
return ['info', 'selection', 'data', 'labels', '
|
|
5857
|
+
return ['info', 'selection', 'data', 'labels', 'edit_points', 'vertices', 'rectangles', 'edit_lines', 'edit_polygons'].includes(mode);
|
|
5842
5858
|
};
|
|
5843
5859
|
|
|
5844
5860
|
this.modeUsesPopup = function(mode) {
|
|
5845
|
-
return ['info', 'selection', 'data', 'box', 'labels', '
|
|
5861
|
+
return ['info', 'selection', 'data', 'box', 'labels', 'edit_points', 'rectangles'].includes(mode);
|
|
5846
5862
|
};
|
|
5847
5863
|
|
|
5848
5864
|
this.getMode = getInteractionMode;
|
|
@@ -5869,7 +5885,7 @@
|
|
|
5869
5885
|
function getAvailableModes() {
|
|
5870
5886
|
var o = gui.model.getActiveLayer();
|
|
5871
5887
|
if (!o || !o.layer) {
|
|
5872
|
-
return menus.
|
|
5888
|
+
return menus.empty; // TODO: more sensible handling of missing layer
|
|
5873
5889
|
}
|
|
5874
5890
|
if (!o.layer.geometry_type) {
|
|
5875
5891
|
return menus.table;
|
|
@@ -5952,6 +5968,7 @@
|
|
|
5952
5968
|
var changed = mode != _editMode;
|
|
5953
5969
|
if (changed) {
|
|
5954
5970
|
menu.classed('active', mode != 'off');
|
|
5971
|
+
_prevMode = _editMode;
|
|
5955
5972
|
_editMode = mode;
|
|
5956
5973
|
onModeChange();
|
|
5957
5974
|
updateArrowButton();
|
|
@@ -5962,7 +5979,7 @@
|
|
|
5962
5979
|
function onModeChange() {
|
|
5963
5980
|
var mode = getInteractionMode();
|
|
5964
5981
|
gui.state.interaction_mode = mode;
|
|
5965
|
-
gui.dispatchEvent('interaction_mode_change', {mode: mode});
|
|
5982
|
+
gui.dispatchEvent('interaction_mode_change', {mode: mode, prev_mode: _prevMode});
|
|
5966
5983
|
}
|
|
5967
5984
|
|
|
5968
5985
|
// Update button highlight and selected menu item highlight (if any)
|
|
@@ -7580,11 +7597,11 @@
|
|
|
7580
7597
|
test = getGraduatedCircleTest(getRadiusFunction(layer.gui.style));
|
|
7581
7598
|
} else if (geoType == 'point') {
|
|
7582
7599
|
test = pointTest;
|
|
7583
|
-
} else if (interactionMode == '
|
|
7600
|
+
} else if (interactionMode == 'edit_polygons') {
|
|
7584
7601
|
test = polygonVertexTest;
|
|
7585
7602
|
} else if (
|
|
7586
7603
|
interactionMode == 'vertices' ||
|
|
7587
|
-
interactionMode == '
|
|
7604
|
+
interactionMode == 'edit_lines') {
|
|
7588
7605
|
test = vertexTest;
|
|
7589
7606
|
} else if (geoType == 'polyline') {
|
|
7590
7607
|
test = polylineTest;
|
|
@@ -7684,7 +7701,8 @@
|
|
|
7684
7701
|
|
|
7685
7702
|
function pointTest(x, y) {
|
|
7686
7703
|
var bullseyeDist = 2, // hit all points w/in 2 px
|
|
7687
|
-
|
|
7704
|
+
// use small threshold when adding points
|
|
7705
|
+
hitThreshold = interactionMode == 'edit_points' ? 12 : 25,
|
|
7688
7706
|
toPx = ext.getTransform().mx,
|
|
7689
7707
|
hits = [];
|
|
7690
7708
|
|
|
@@ -7899,7 +7917,9 @@
|
|
|
7899
7917
|
|
|
7900
7918
|
function getPointerHitTest(mapLayer, ext, interactionMode, featureFilter) {
|
|
7901
7919
|
var shapeTest, targetLayer;
|
|
7902
|
-
|
|
7920
|
+
// need hit test on empty layers, in case we are drawing shapes
|
|
7921
|
+
// if (!mapLayer || !internal.layerHasGeometry(mapLayer.gui?.displayLayer)) {
|
|
7922
|
+
if (!mapLayer || !mapLayer.gui?.displayLayer.geometry_type) {
|
|
7903
7923
|
return function() {return {ids: []};};
|
|
7904
7924
|
}
|
|
7905
7925
|
shapeTest = getShapeHitTest(mapLayer, ext, interactionMode, featureFilter);
|
|
@@ -8021,20 +8041,29 @@
|
|
|
8021
8041
|
}
|
|
8022
8042
|
|
|
8023
8043
|
function draggable() {
|
|
8024
|
-
return interactionMode == 'vertices' || interactionMode == '
|
|
8025
|
-
interactionMode == 'labels' || interactionMode == '
|
|
8044
|
+
return interactionMode == 'vertices' || interactionMode == 'edit_points' ||
|
|
8045
|
+
interactionMode == 'labels' || interactionMode == 'edit_lines' ||
|
|
8046
|
+
interactionMode == 'edit_polygons';
|
|
8026
8047
|
}
|
|
8027
8048
|
|
|
8028
8049
|
function clickable() {
|
|
8029
8050
|
// click used to pin popup and select features
|
|
8030
8051
|
return interactionMode == 'data' || interactionMode == 'info' ||
|
|
8031
|
-
interactionMode == 'selection' || interactionMode == 'rectangles'
|
|
8052
|
+
interactionMode == 'selection' || interactionMode == 'rectangles' ||
|
|
8053
|
+
interactionMode == 'edit_points';
|
|
8032
8054
|
}
|
|
8033
8055
|
|
|
8034
8056
|
self.getHitId = function() {
|
|
8035
8057
|
return hitTest ? storedData.id : -1;
|
|
8036
8058
|
};
|
|
8037
8059
|
|
|
8060
|
+
self.setHitId = function(id) {
|
|
8061
|
+
if (storedData.id == id) return;
|
|
8062
|
+
storedData.id = id;
|
|
8063
|
+
storedData.ids = [id];
|
|
8064
|
+
triggerHitEvent('change');
|
|
8065
|
+
};
|
|
8066
|
+
|
|
8038
8067
|
// Get a reference to the active layer, so listeners to hit events can interact
|
|
8039
8068
|
// with data and shapes
|
|
8040
8069
|
self.getHitTarget = function() {
|
|
@@ -8169,9 +8198,9 @@
|
|
|
8169
8198
|
|
|
8170
8199
|
|
|
8171
8200
|
mouse.on('click', function(e) {
|
|
8201
|
+
var pinned = storedData.pinned;
|
|
8172
8202
|
if (!hitTest || !active) return;
|
|
8173
8203
|
if (!eventIsEnabled('click')) return;
|
|
8174
|
-
|
|
8175
8204
|
e.stopPropagation();
|
|
8176
8205
|
|
|
8177
8206
|
// TODO: move pinning to inspection control?
|
|
@@ -8179,6 +8208,11 @@
|
|
|
8179
8208
|
updateSelectionState(convertClickDataToSelectionData(hitTest(e)));
|
|
8180
8209
|
}
|
|
8181
8210
|
|
|
8211
|
+
if (pinned && interactionMode == 'edit_points') {
|
|
8212
|
+
// kludge: intercept the click event if popup is turning off, so
|
|
8213
|
+
// a new point doesn't get made
|
|
8214
|
+
return;
|
|
8215
|
+
}
|
|
8182
8216
|
triggerHitEvent('click', e);
|
|
8183
8217
|
}, null, priority);
|
|
8184
8218
|
|
|
@@ -8306,11 +8340,15 @@
|
|
|
8306
8340
|
if (type == 'click' && gui.contextMenu.isOpen()) {
|
|
8307
8341
|
return false;
|
|
8308
8342
|
}
|
|
8309
|
-
if (type == 'click' &&
|
|
8343
|
+
if (type == 'click' &&
|
|
8344
|
+
(interactionMode == 'edit_lines' || interactionMode == 'edit_polygons')) {
|
|
8310
8345
|
return true; // click events are triggered even if no shape is hit
|
|
8311
8346
|
}
|
|
8312
|
-
|
|
8313
|
-
|
|
8347
|
+
if (type == 'click' && interactionMode == 'edit_points') {
|
|
8348
|
+
return true;
|
|
8349
|
+
}
|
|
8350
|
+
if ((interactionMode == 'edit_lines' || interactionMode == 'edit_polygons') &&
|
|
8351
|
+
(type == 'hover' || type == 'dblclick')) {
|
|
8314
8352
|
return true; // special case -- using hover for line drawing animation
|
|
8315
8353
|
}
|
|
8316
8354
|
|
|
@@ -8330,7 +8368,7 @@
|
|
|
8330
8368
|
}
|
|
8331
8369
|
|
|
8332
8370
|
function possiblyStopPropagation(e) {
|
|
8333
|
-
if (interactionMode == '
|
|
8371
|
+
if (interactionMode == 'edit_lines' || interactionMode == 'edit_polygons') {
|
|
8334
8372
|
// handled conditionally in the control
|
|
8335
8373
|
return;
|
|
8336
8374
|
}
|
|
@@ -9527,7 +9565,7 @@
|
|
|
9527
9565
|
});
|
|
9528
9566
|
|
|
9529
9567
|
self.show = function(id, ids, lyr, pinned, edit) {
|
|
9530
|
-
var singleEdit = edit || pinned &&
|
|
9568
|
+
var singleEdit = edit || pinned && !internal.layerHasAttributeData(lyr);
|
|
9531
9569
|
var multiEdit = pinned && gui.interaction.getMode() == 'selection';
|
|
9532
9570
|
var maxHeight = parent.node().clientHeight - 36;
|
|
9533
9571
|
|
|
@@ -9759,16 +9797,16 @@
|
|
|
9759
9797
|
gui.session.dataValueUpdated(e.ids, e.field, e.value);
|
|
9760
9798
|
// Refresh the display if a style variable has been changed interactively
|
|
9761
9799
|
if (internal.isSupportedSvgStyleProperty(e.field)) {
|
|
9762
|
-
// drawLayers();
|
|
9763
9800
|
gui.dispatchEvent('map-needs-refresh');
|
|
9764
9801
|
}
|
|
9765
9802
|
});
|
|
9766
9803
|
|
|
9767
9804
|
hit.on('contextmenu', function(e) {
|
|
9768
9805
|
var target = hit.getHitTarget();
|
|
9769
|
-
if (!e.overMap || !target
|
|
9770
|
-
|
|
9771
|
-
|
|
9806
|
+
if (!e.overMap || !target || e.mode == 'edit_lines' ||
|
|
9807
|
+
e.mode == 'edit_polygons') {
|
|
9808
|
+
return;
|
|
9809
|
+
}
|
|
9772
9810
|
gui.contextMenu.open(e, hit.getHitTarget());
|
|
9773
9811
|
});
|
|
9774
9812
|
|
|
@@ -10060,14 +10098,43 @@
|
|
|
10060
10098
|
}
|
|
10061
10099
|
}
|
|
10062
10100
|
|
|
10063
|
-
function
|
|
10101
|
+
function initPointEditing(gui, ext, hit) {
|
|
10064
10102
|
var symbolInfo;
|
|
10065
10103
|
function active(e) {
|
|
10066
|
-
return
|
|
10104
|
+
return gui.interaction.getMode() == 'edit_points';
|
|
10067
10105
|
}
|
|
10068
10106
|
|
|
10069
|
-
|
|
10107
|
+
function overPoint(e) {
|
|
10108
|
+
return active(e) && e.id > -1;
|
|
10109
|
+
}
|
|
10110
|
+
|
|
10111
|
+
gui.on('interaction_mode_change', function(e) {
|
|
10112
|
+
if (e.mode == 'edit_points' && !gui.model.getActiveLayer()) {
|
|
10113
|
+
addEmptyLayer(gui, undefined, 'point');
|
|
10114
|
+
} else if (e.prev_mode == 'edit_points') {
|
|
10115
|
+
gui.container.findChild('.map-layers').classed('add-points', false);
|
|
10116
|
+
}
|
|
10117
|
+
|
|
10118
|
+
});
|
|
10119
|
+
|
|
10120
|
+
hit.on('click', function(e) {
|
|
10121
|
+
if (overPoint(e) || !active(e)) return;
|
|
10122
|
+
// add point
|
|
10123
|
+
var p = pixToDataCoords(e.x, e.y);
|
|
10124
|
+
var target = hit.getHitTarget();
|
|
10125
|
+
appendNewPoint(target, p);
|
|
10126
|
+
gui.dispatchEvent('point_add', {p, target});
|
|
10127
|
+
gui.dispatchEvent('map-needs-refresh');
|
|
10128
|
+
hit.setHitId(target.shapes.length - 1); // highlight new point
|
|
10129
|
+
});
|
|
10130
|
+
|
|
10131
|
+
hit.on('change', function(e) {
|
|
10070
10132
|
if (!active(e)) return;
|
|
10133
|
+
gui.container.findChild('.map-layers').classed('add-points', !overPoint(e));
|
|
10134
|
+
});
|
|
10135
|
+
|
|
10136
|
+
hit.on('dragstart', function(e) {
|
|
10137
|
+
if (!overPoint(e)) return;
|
|
10071
10138
|
var target = hit.getHitTarget();
|
|
10072
10139
|
symbolInfo = {
|
|
10073
10140
|
FID: e.id,
|
|
@@ -10077,37 +10144,36 @@
|
|
|
10077
10144
|
});
|
|
10078
10145
|
|
|
10079
10146
|
hit.on('drag', function(e) {
|
|
10080
|
-
if (!
|
|
10147
|
+
if (!overPoint(e)) return;
|
|
10081
10148
|
// TODO: support multi points... get id of closest part to the pointer
|
|
10082
|
-
var p = getPointCoordsById(e.id, symbolInfo.target);
|
|
10083
|
-
|
|
10149
|
+
// var p = getPointCoordsById(e.id, symbolInfo.target);
|
|
10150
|
+
var id = symbolInfo.FID;
|
|
10151
|
+
var shp = symbolInfo.target.gui.displayLayer.shapes[id];
|
|
10152
|
+
if (!shp) return;
|
|
10084
10153
|
var diff = translateDeltaDisplayCoords(e.dx, e.dy, ext);
|
|
10085
|
-
|
|
10086
|
-
|
|
10154
|
+
shp[0][0] += diff[0];
|
|
10155
|
+
shp[0][1] += diff[1];
|
|
10087
10156
|
gui.dispatchEvent('map-needs-refresh');
|
|
10088
10157
|
});
|
|
10089
10158
|
|
|
10090
10159
|
hit.on('dragend', function(e) {
|
|
10091
|
-
if (!
|
|
10092
|
-
updatePointCoords(symbolInfo.target,
|
|
10160
|
+
if (!overPoint(e) || !symbolInfo ) return;
|
|
10161
|
+
updatePointCoords(symbolInfo.target, symbolInfo.FID);
|
|
10093
10162
|
symbolInfo.endCoords = getPointCoords(symbolInfo.target, e.id);
|
|
10094
10163
|
gui.dispatchEvent('symbol_dragend', symbolInfo);
|
|
10095
10164
|
symbolInfo = null;
|
|
10096
10165
|
});
|
|
10097
10166
|
|
|
10167
|
+
function pixToDataCoords(x, y) {
|
|
10168
|
+
var target = hit.getHitTarget();
|
|
10169
|
+
return translateDisplayPoint(target, ext.translatePixelCoords(x, y));
|
|
10170
|
+
}
|
|
10171
|
+
|
|
10098
10172
|
function translateDeltaDisplayCoords(dx, dy, ext) {
|
|
10099
10173
|
var a = ext.translatePixelCoords(0, 0);
|
|
10100
10174
|
var b = ext.translatePixelCoords(dx, dy);
|
|
10101
10175
|
return [b[0] - a[0], b[1] - a[1]];
|
|
10102
10176
|
}
|
|
10103
|
-
|
|
10104
|
-
function getPointCoordsById(id, layer) {
|
|
10105
|
-
var coords = layer && layer.geometry_type == 'point' && layer.shapes[id];
|
|
10106
|
-
if (!coords || coords.length != 1) {
|
|
10107
|
-
return null;
|
|
10108
|
-
}
|
|
10109
|
-
return coords[0];
|
|
10110
|
-
}
|
|
10111
10177
|
}
|
|
10112
10178
|
|
|
10113
10179
|
// pixel distance threshold for hovering near a vertex or segment midpoint
|
|
@@ -10148,13 +10214,17 @@
|
|
|
10148
10214
|
gui.addMode('drawing_tool', turnOn, turnOff);
|
|
10149
10215
|
|
|
10150
10216
|
gui.on('interaction_mode_change', function(e) {
|
|
10151
|
-
|
|
10152
|
-
|
|
10153
|
-
|
|
10217
|
+
if (e.mode == 'edit_lines' || e.mode == 'edit_polygons') {
|
|
10218
|
+
if (!gui.model.getActiveLayer()) {
|
|
10219
|
+
addEmptyLayer(gui, undefined, e.mode == 'edit_lines' ? 'polyline' : 'polygon');
|
|
10220
|
+
}
|
|
10154
10221
|
gui.enterMode('drawing_tool');
|
|
10222
|
+
} else if (gui.getMode() == 'drawing_tool') {
|
|
10223
|
+
gui.clearMode();
|
|
10155
10224
|
} else if (active()) {
|
|
10156
10225
|
turnOff();
|
|
10157
10226
|
}
|
|
10227
|
+
updateCursor();
|
|
10158
10228
|
}, null, 10); // higher priority than hit control, so turnOff() has correct hit target
|
|
10159
10229
|
|
|
10160
10230
|
gui.on('redo_path_add', function(e) {
|
|
@@ -10201,6 +10271,7 @@
|
|
|
10201
10271
|
});
|
|
10202
10272
|
|
|
10203
10273
|
function turnOn() {
|
|
10274
|
+
if (active()) return;
|
|
10204
10275
|
var target = hit.getHitTarget();
|
|
10205
10276
|
initialArcCount = target.gui.displayArcs.size();
|
|
10206
10277
|
initialShapeCount = target.shapes.length;
|
|
@@ -10227,6 +10298,7 @@
|
|
|
10227
10298
|
|
|
10228
10299
|
function turnOff() {
|
|
10229
10300
|
var removed = 0;
|
|
10301
|
+
var mode = gui.interaction.getMode();
|
|
10230
10302
|
finishCurrentPath();
|
|
10231
10303
|
if (polygonMode()) {
|
|
10232
10304
|
removed = removeOpenPolygons();
|
|
@@ -10235,10 +10307,11 @@
|
|
|
10235
10307
|
hideInstructions();
|
|
10236
10308
|
initialArcCount = -1;
|
|
10237
10309
|
initialShapeCount = -1;
|
|
10238
|
-
if (
|
|
10310
|
+
if (mode == 'edit_lines' || mode == 'edit_polygons') {
|
|
10239
10311
|
// mode change was not initiated by interactive menu -- turn off interactivity
|
|
10240
10312
|
gui.interaction.turnOff();
|
|
10241
10313
|
}
|
|
10314
|
+
updateCursor();
|
|
10242
10315
|
if (removed > 0) {
|
|
10243
10316
|
fullRedraw();
|
|
10244
10317
|
}
|
|
@@ -10406,6 +10479,7 @@
|
|
|
10406
10479
|
}
|
|
10407
10480
|
|
|
10408
10481
|
function updateCursor() {
|
|
10482
|
+
gui.container.findChild('.map-layers').classed('drawing', active());
|
|
10409
10483
|
var useArrow = hoverVertexInfo && !hoverVertexInfo.extendable && !drawing();
|
|
10410
10484
|
gui.container.findChild('.map-layers').classed('dragging', useArrow);
|
|
10411
10485
|
}
|
|
@@ -10664,38 +10738,9 @@
|
|
|
10664
10738
|
}
|
|
10665
10739
|
}
|
|
10666
10740
|
|
|
10667
|
-
function initPointDrawing(gui, ext, hit) {
|
|
10668
|
-
var mouse = gui.map.getMouse();
|
|
10669
|
-
|
|
10670
|
-
gui.on('interaction_mode_change', function(e) {
|
|
10671
|
-
gui.container.findChild('.map-layers').classed('add-points', e.mode === 'add-points');
|
|
10672
|
-
});
|
|
10673
|
-
|
|
10674
|
-
function active() {
|
|
10675
|
-
return gui.interaction.getMode() == 'add-points';
|
|
10676
|
-
}
|
|
10677
|
-
|
|
10678
|
-
mouse.on('click', function(e) {
|
|
10679
|
-
if (!active()) return;
|
|
10680
|
-
var p = pixToDataCoords(e.x, e.y);
|
|
10681
|
-
var target = hit.getHitTarget();
|
|
10682
|
-
appendNewPoint(target, p);
|
|
10683
|
-
gui.dispatchEvent('point_add', {p, target});
|
|
10684
|
-
gui.dispatchEvent('map-needs-refresh');
|
|
10685
|
-
});
|
|
10686
|
-
|
|
10687
|
-
|
|
10688
|
-
function pixToDataCoords(x, y) {
|
|
10689
|
-
var target = hit.getHitTarget();
|
|
10690
|
-
return translateDisplayPoint(target, ext.translatePixelCoords(x, y));
|
|
10691
|
-
}
|
|
10692
|
-
|
|
10693
|
-
}
|
|
10694
|
-
|
|
10695
10741
|
function initInteractiveEditing(gui, ext, hit) {
|
|
10696
10742
|
initLabelDragging(gui, ext, hit);
|
|
10697
|
-
|
|
10698
|
-
initPointDrawing(gui, ext, hit);
|
|
10743
|
+
initPointEditing(gui, ext, hit);
|
|
10699
10744
|
initLineEditing(gui, ext, hit);
|
|
10700
10745
|
}
|
|
10701
10746
|
|
|
@@ -12133,8 +12178,10 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
12133
12178
|
if (activeStyle) {
|
|
12134
12179
|
turnOffBasemap();
|
|
12135
12180
|
updateButtons();
|
|
12181
|
+
closeMenu();
|
|
12136
12182
|
}
|
|
12137
12183
|
});
|
|
12184
|
+
|
|
12138
12185
|
fadeBtn.on('click', function() {
|
|
12139
12186
|
if (faded) {
|
|
12140
12187
|
mapEl.css('opacity', 1);
|
|
@@ -12161,11 +12208,19 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
12161
12208
|
showBasemap(style);
|
|
12162
12209
|
}
|
|
12163
12210
|
updateButtons();
|
|
12211
|
+
closeMenu();
|
|
12164
12212
|
});
|
|
12165
12213
|
btn.appendTo(list);
|
|
12166
12214
|
});
|
|
12167
12215
|
}
|
|
12168
12216
|
|
|
12217
|
+
// close and turn off mode
|
|
12218
|
+
function closeMenu() {
|
|
12219
|
+
setTimeout(function() {
|
|
12220
|
+
gui.clearMode();
|
|
12221
|
+
}, 200);
|
|
12222
|
+
}
|
|
12223
|
+
|
|
12169
12224
|
function turnOffBasemap() {
|
|
12170
12225
|
activeStyle = null;
|
|
12171
12226
|
gui.map.setDisplayCRS(null);
|
|
@@ -12923,7 +12978,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
12923
12978
|
var layer = mapshaper.cmd.filterFeatures(lyr, dataset.arcs, opts);
|
|
12924
12979
|
// the drawing tool can send open paths with 'polygon' geometry type,
|
|
12925
12980
|
// should be changed to 'polyline'
|
|
12926
|
-
if (layerHasOpenPaths(layer, dataset.arcs)) {
|
|
12981
|
+
if (layer.geometry_type == 'polygon' && layerHasOpenPaths(layer, dataset.arcs)) {
|
|
12927
12982
|
layer.geometry_type = 'polyline';
|
|
12928
12983
|
}
|
|
12929
12984
|
var features = internal.exportLayerAsGeoJSON(layer, dataset, {rfc7946: true, prettify: true}, true, 'string');
|
package/www/mapshaper.js
CHANGED
|
@@ -4278,6 +4278,10 @@
|
|
|
4278
4278
|
return data;
|
|
4279
4279
|
}
|
|
4280
4280
|
|
|
4281
|
+
function layerHasAttributeData(lyr) {
|
|
4282
|
+
return lyr.data && lyr.data.getFields().length > 0;
|
|
4283
|
+
}
|
|
4284
|
+
|
|
4281
4285
|
function layerHasNonNullData(lyr) {
|
|
4282
4286
|
return lyr.data && getFirstNonEmptyRecord(lyr.data.getRecords()) ? true : false;
|
|
4283
4287
|
}
|
|
@@ -4551,6 +4555,7 @@
|
|
|
4551
4555
|
__proto__: null,
|
|
4552
4556
|
insertFieldValues: insertFieldValues,
|
|
4553
4557
|
getLayerDataTable: getLayerDataTable,
|
|
4558
|
+
layerHasAttributeData: layerHasAttributeData,
|
|
4554
4559
|
layerHasNonNullData: layerHasNonNullData,
|
|
4555
4560
|
layerHasGeometry: layerHasGeometry,
|
|
4556
4561
|
layerIsGeometric: layerIsGeometric,
|
|
@@ -18025,11 +18030,10 @@
|
|
|
18025
18030
|
opts = utils.extend({}, opts);
|
|
18026
18031
|
opts.rfc7946 = !opts.gj2008; // use RFC 7946 as the default
|
|
18027
18032
|
var extension = opts.extension || "json";
|
|
18028
|
-
var layerGroups
|
|
18033
|
+
var layerGroups;
|
|
18029
18034
|
|
|
18030
18035
|
if (opts.rfc7946) {
|
|
18031
|
-
|
|
18032
|
-
if (warn) message(warn);
|
|
18036
|
+
warnIfNotWgs84(dataset);
|
|
18033
18037
|
}
|
|
18034
18038
|
|
|
18035
18039
|
if (opts.file) {
|
|
@@ -18120,14 +18124,12 @@
|
|
|
18120
18124
|
return feat;
|
|
18121
18125
|
}
|
|
18122
18126
|
|
|
18123
|
-
function
|
|
18127
|
+
function warnIfNotWgs84(dataset) {
|
|
18124
18128
|
var P = getDatasetCRS(dataset);
|
|
18125
|
-
|
|
18126
|
-
|
|
18127
|
-
|
|
18128
|
-
|
|
18129
|
-
}
|
|
18130
|
-
return str;
|
|
18129
|
+
if (P && isLatLngCRS(P) || datasetIsEmpty(dataset)) return;
|
|
18130
|
+
var str = 'RFC 7946 warning: non-WGS84 GeoJSON output.';
|
|
18131
|
+
if (P) str += ' Tip: use "-proj wgs84" to convert.';
|
|
18132
|
+
message(str);
|
|
18131
18133
|
}
|
|
18132
18134
|
|
|
18133
18135
|
function getDatasetBbox(dataset, rfc7946) {
|
|
@@ -18397,7 +18399,7 @@
|
|
|
18397
18399
|
'default': GeoJSON,
|
|
18398
18400
|
exportGeoJSON: exportGeoJSON,
|
|
18399
18401
|
exportLayerAsGeoJSON: exportLayerAsGeoJSON,
|
|
18400
|
-
|
|
18402
|
+
warnIfNotWgs84: warnIfNotWgs84,
|
|
18401
18403
|
getDatasetBbox: getDatasetBbox,
|
|
18402
18404
|
exportDatasetAsGeoJSON: exportDatasetAsGeoJSON,
|
|
18403
18405
|
preserveOriginalCRS: preserveOriginalCRS,
|
|
@@ -45530,7 +45532,7 @@ ${svg}
|
|
|
45530
45532
|
});
|
|
45531
45533
|
}
|
|
45532
45534
|
|
|
45533
|
-
var version = "0.6.
|
|
45535
|
+
var version = "0.6.78";
|
|
45534
45536
|
|
|
45535
45537
|
// Parse command line args into commands and run them
|
|
45536
45538
|
// Function takes an optional Node-style callback. A Promise is returned if no callback is given.
|
package/www/page.css
CHANGED
|
@@ -60,8 +60,6 @@ body.map-view {
|
|
|
60
60
|
|
|
61
61
|
.selectable,.selectable * {
|
|
62
62
|
user-select: default;
|
|
63
|
-
-webkit-user-select: text;
|
|
64
|
-
-moz-user-select: text;
|
|
65
63
|
cursor: text;
|
|
66
64
|
}
|
|
67
65
|
|
|
@@ -526,6 +524,10 @@ div.alert-box {
|
|
|
526
524
|
/* border: 1px solid #aaa; */
|
|
527
525
|
}
|
|
528
526
|
|
|
527
|
+
.info-box label {
|
|
528
|
+
cursor: pointer;
|
|
529
|
+
}
|
|
530
|
+
|
|
529
531
|
.sidebar-buttons {
|
|
530
532
|
display: none;
|
|
531
533
|
position: absolute;
|