mapshaper 0.7.41 → 0.7.45
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 +2498 -63
- package/package.json +2 -2
- package/www/mapshaper-gui.js +119 -24
- package/www/mapshaper.js +2498 -63
- package/www/modules.js +294 -24
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mapshaper",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.45",
|
|
4
4
|
"description": "A tool for editing geospatial data for mapping and GIS.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"shapefile",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"idb-keyval": "^6.2.0",
|
|
72
72
|
"jpeg-js": "^0.4.4",
|
|
73
73
|
"kdbush": "^3.0.0",
|
|
74
|
-
"mproj": "0.1.
|
|
74
|
+
"mproj": "0.1.5",
|
|
75
75
|
"msgpackr": "^1.11.12",
|
|
76
76
|
"open": "^11.0.0",
|
|
77
77
|
"pngjs": "^7.0.0",
|
package/www/mapshaper-gui.js
CHANGED
|
@@ -18294,7 +18294,7 @@
|
|
|
18294
18294
|
var mode = gui.getMode();
|
|
18295
18295
|
var interactionMode = gui.interaction && gui.interaction.getMode();
|
|
18296
18296
|
return !'selection_tool,box_tool,rectangle_tool,drawing_tool'.includes(mode) &&
|
|
18297
|
-
!'label_style,point_style,line_style,polygon_style'.includes(interactionMode);
|
|
18297
|
+
!'label_style,point_style,line_style,polygon_style,ruler'.includes(interactionMode);
|
|
18298
18298
|
}
|
|
18299
18299
|
|
|
18300
18300
|
function getBoxData(e1, e2) {
|
|
@@ -22669,6 +22669,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
22669
22669
|
var geodesicPath = createSvgNode('path');
|
|
22670
22670
|
var startMarker = createSvgNode('circle');
|
|
22671
22671
|
var endMarker = createSvgNode('circle');
|
|
22672
|
+
var vertexMarkers = [];
|
|
22672
22673
|
var popup = El('div').addClass('ruler-popup rollover').appendTo(parent).hide();
|
|
22673
22674
|
var content = El('div').addClass('ruler-popup-content').appendTo(popup);
|
|
22674
22675
|
var closeBtn = El('button').addClass('label-style-close ruler-close-btn').appendTo(popup).text('×');
|
|
@@ -22676,6 +22677,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
22676
22677
|
var _on = false;
|
|
22677
22678
|
var startPoint = null;
|
|
22678
22679
|
var pointerPoint = null;
|
|
22680
|
+
var rulerPoints = [];
|
|
22679
22681
|
var placed = false;
|
|
22680
22682
|
var draggingEndpoint = null;
|
|
22681
22683
|
var lastValidDragPoint = null;
|
|
@@ -22803,8 +22805,13 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
22803
22805
|
}
|
|
22804
22806
|
if (!startPoint || placed) {
|
|
22805
22807
|
startPoint = point;
|
|
22808
|
+
rulerPoints = [point];
|
|
22806
22809
|
pointerPoint = null;
|
|
22807
22810
|
placed = false;
|
|
22811
|
+
} else if (e.shiftKey) {
|
|
22812
|
+
rulerPoints.push(point);
|
|
22813
|
+
startPoint = rulerPoints[0];
|
|
22814
|
+
pointerPoint = null;
|
|
22808
22815
|
} else {
|
|
22809
22816
|
pointerPoint = point;
|
|
22810
22817
|
placed = true;
|
|
@@ -22819,6 +22826,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
22819
22826
|
function clearRuler() {
|
|
22820
22827
|
startPoint = null;
|
|
22821
22828
|
pointerPoint = null;
|
|
22829
|
+
rulerPoints = [];
|
|
22822
22830
|
placed = false;
|
|
22823
22831
|
draggingEndpoint = null;
|
|
22824
22832
|
lastValidDragPoint = null;
|
|
@@ -22827,6 +22835,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
22827
22835
|
clearSvgPath(geodesicPath);
|
|
22828
22836
|
hideMarker(startMarker);
|
|
22829
22837
|
hideMarker(endMarker);
|
|
22838
|
+
hideVertexMarkers();
|
|
22830
22839
|
popup.hide();
|
|
22831
22840
|
}
|
|
22832
22841
|
|
|
@@ -22837,30 +22846,31 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
22837
22846
|
}
|
|
22838
22847
|
|
|
22839
22848
|
function render() {
|
|
22840
|
-
var
|
|
22849
|
+
var path = getRulerPath();
|
|
22850
|
+
var endPoint = path[path.length - 1];
|
|
22841
22851
|
var measurement;
|
|
22842
22852
|
syncOverlaySize();
|
|
22843
22853
|
if (!startPoint || !endPoint) {
|
|
22844
22854
|
clearSvgPath(directPath);
|
|
22845
22855
|
clearSvgPath(geodesicPath);
|
|
22846
|
-
|
|
22856
|
+
drawRulerPointMarkers(false);
|
|
22847
22857
|
hideMarker(endMarker);
|
|
22848
22858
|
popup.hide();
|
|
22849
22859
|
return;
|
|
22850
22860
|
}
|
|
22851
22861
|
|
|
22852
|
-
if (!
|
|
22862
|
+
if (!path.every(pointIsValid)) {
|
|
22853
22863
|
clearSvgPath(directPath);
|
|
22854
22864
|
clearSvgPath(geodesicPath);
|
|
22855
|
-
|
|
22865
|
+
drawRulerPointMarkers(false);
|
|
22856
22866
|
drawMarker(endMarker, placed && endPoint.valid ? endPoint : null, false);
|
|
22857
22867
|
showOutOfRangeNote();
|
|
22858
22868
|
return;
|
|
22859
22869
|
}
|
|
22860
22870
|
|
|
22861
|
-
measurement = getMeasurement(
|
|
22862
|
-
drawRulerLines(
|
|
22863
|
-
|
|
22871
|
+
measurement = getMeasurement(path);
|
|
22872
|
+
drawRulerLines(path, measurement);
|
|
22873
|
+
drawRulerPointMarkers(measurement.isLatLng);
|
|
22864
22874
|
if (placed) {
|
|
22865
22875
|
drawMarker(endMarker, endPoint, measurement.isLatLng);
|
|
22866
22876
|
} else {
|
|
@@ -22869,13 +22879,21 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
22869
22879
|
showPopup(measurement);
|
|
22870
22880
|
}
|
|
22871
22881
|
|
|
22872
|
-
function
|
|
22882
|
+
function getRulerPath() {
|
|
22883
|
+
return rulerPoints.concat(pointerPoint || []);
|
|
22884
|
+
}
|
|
22885
|
+
|
|
22886
|
+
function pointIsValid(point) {
|
|
22887
|
+
return !!point && point.valid;
|
|
22888
|
+
}
|
|
22889
|
+
|
|
22890
|
+
function drawRulerLines(path, measurement) {
|
|
22873
22891
|
if (measurement.isLatLng) {
|
|
22874
|
-
drawPath(geodesicPath,
|
|
22892
|
+
drawPath(geodesicPath, getGeodesicPathPixels(path));
|
|
22875
22893
|
clearSvgPath(directPath);
|
|
22876
22894
|
} else {
|
|
22877
|
-
drawPath(directPath,
|
|
22878
|
-
drawPath(geodesicPath, measurement.greatCircleMeters ?
|
|
22895
|
+
drawPath(directPath, path.map(function(point) { return point.display; }));
|
|
22896
|
+
drawPath(geodesicPath, measurement.greatCircleMeters ? getGeodesicPathPixels(path) : null);
|
|
22879
22897
|
}
|
|
22880
22898
|
}
|
|
22881
22899
|
|
|
@@ -22904,10 +22922,21 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
22904
22922
|
}
|
|
22905
22923
|
|
|
22906
22924
|
function getHitEndpoint(x, y) {
|
|
22907
|
-
var
|
|
22925
|
+
var endpoint = null;
|
|
22926
|
+
var minDist = Infinity;
|
|
22927
|
+
rulerPoints.forEach(function(point, i) {
|
|
22928
|
+
var dist = getEndpointPixelDistance(point, x, y);
|
|
22929
|
+
if (dist < minDist) {
|
|
22930
|
+
minDist = dist;
|
|
22931
|
+
endpoint = {type: 'fixed', index: i};
|
|
22932
|
+
}
|
|
22933
|
+
});
|
|
22908
22934
|
var endDist = getEndpointPixelDistance(pointerPoint, x, y);
|
|
22909
|
-
if (
|
|
22910
|
-
|
|
22935
|
+
if (endDist < minDist) {
|
|
22936
|
+
minDist = endDist;
|
|
22937
|
+
endpoint = {type: 'end'};
|
|
22938
|
+
}
|
|
22939
|
+
return minDist <= ENDPOINT_HIT_RADIUS ? endpoint : null;
|
|
22911
22940
|
}
|
|
22912
22941
|
|
|
22913
22942
|
function getEndpointPixelDistance(point, x, y) {
|
|
@@ -22918,12 +22947,13 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
22918
22947
|
}
|
|
22919
22948
|
|
|
22920
22949
|
function getEndpoint(endpoint) {
|
|
22921
|
-
return endpoint == '
|
|
22950
|
+
return endpoint.type == 'fixed' ? rulerPoints[endpoint.index] : pointerPoint;
|
|
22922
22951
|
}
|
|
22923
22952
|
|
|
22924
22953
|
function setEndpoint(endpoint, point) {
|
|
22925
|
-
if (endpoint == '
|
|
22926
|
-
|
|
22954
|
+
if (endpoint.type == 'fixed') {
|
|
22955
|
+
rulerPoints[endpoint.index] = point;
|
|
22956
|
+
startPoint = rulerPoints[0] || null;
|
|
22927
22957
|
} else {
|
|
22928
22958
|
pointerPoint = point;
|
|
22929
22959
|
}
|
|
@@ -22955,9 +22985,10 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
22955
22985
|
}
|
|
22956
22986
|
|
|
22957
22987
|
function reprojectStoredRulerPoints() {
|
|
22958
|
-
|
|
22988
|
+
rulerPoints = rulerPoints.map(reprojectRulerPoint);
|
|
22989
|
+
startPoint = rulerPoints[0] || null;
|
|
22959
22990
|
pointerPoint = reprojectRulerPoint(pointerPoint);
|
|
22960
|
-
if (
|
|
22991
|
+
if (!getRulerPath().every(pointIsValid)) {
|
|
22961
22992
|
showOutOfRangeNote();
|
|
22962
22993
|
}
|
|
22963
22994
|
render();
|
|
@@ -23043,10 +23074,10 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
23043
23074
|
geom.distance2D(data[0], data[1], fwd[0], fwd[1]) <= tolerance;
|
|
23044
23075
|
}
|
|
23045
23076
|
|
|
23046
|
-
function getMeasurement(
|
|
23047
|
-
var isLatLng = internal.isLatLngCRS(
|
|
23048
|
-
var projectedMeters = isLatLng ? null :
|
|
23049
|
-
var greatCircleMeters =
|
|
23077
|
+
function getMeasurement(path) {
|
|
23078
|
+
var isLatLng = internal.isLatLngCRS(path[0].sourceCRS);
|
|
23079
|
+
var projectedMeters = isLatLng ? null : getProjectedPathDistanceMeters(path);
|
|
23080
|
+
var greatCircleMeters = getGreatCirclePathDistanceMeters(path);
|
|
23050
23081
|
var unit = getDistanceUnit(projectedMeters || greatCircleMeters || 0);
|
|
23051
23082
|
var labels = [];
|
|
23052
23083
|
|
|
@@ -23066,17 +23097,56 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
23066
23097
|
};
|
|
23067
23098
|
}
|
|
23068
23099
|
|
|
23100
|
+
function getProjectedPathDistanceMeters(path) {
|
|
23101
|
+
return sumPathDistance(path, getProjectedDistanceMeters);
|
|
23102
|
+
}
|
|
23103
|
+
|
|
23069
23104
|
function getProjectedDistanceMeters(a, b) {
|
|
23070
23105
|
var toMeter = a.sourceCRS && a.sourceCRS.to_meter || 1;
|
|
23071
23106
|
if (!a.data || !b.data) return null;
|
|
23072
23107
|
return geom.distance2D(a.data[0], a.data[1], b.data[0], b.data[1]) * toMeter;
|
|
23073
23108
|
}
|
|
23074
23109
|
|
|
23110
|
+
function getGreatCirclePathDistanceMeters(path) {
|
|
23111
|
+
return sumPathDistance(path, getGreatCircleDistanceMeters);
|
|
23112
|
+
}
|
|
23113
|
+
|
|
23075
23114
|
function getGreatCircleDistanceMeters(a, b) {
|
|
23076
23115
|
if (!a.lngLat || !b.lngLat) return null;
|
|
23077
23116
|
return geom.greatCircleDistance(a.lngLat[0], a.lngLat[1], b.lngLat[0], b.lngLat[1]);
|
|
23078
23117
|
}
|
|
23079
23118
|
|
|
23119
|
+
function sumPathDistance(path, calcSegmentDistance) {
|
|
23120
|
+
var sum = 0;
|
|
23121
|
+
var dist;
|
|
23122
|
+
for (var i = 1; i < path.length; i++) {
|
|
23123
|
+
dist = calcSegmentDistance(path[i - 1], path[i]);
|
|
23124
|
+
if (dist === null) return null;
|
|
23125
|
+
sum += dist;
|
|
23126
|
+
}
|
|
23127
|
+
return sum;
|
|
23128
|
+
}
|
|
23129
|
+
|
|
23130
|
+
function getGeodesicPathPixels(path) {
|
|
23131
|
+
var points = [];
|
|
23132
|
+
var segment;
|
|
23133
|
+
for (var i = 1; i < path.length; i++) {
|
|
23134
|
+
segment = getGeodesicPixels(path[i - 1], path[i]);
|
|
23135
|
+
appendPathSegment(points, segment);
|
|
23136
|
+
}
|
|
23137
|
+
return points.length > 1 ? points : null;
|
|
23138
|
+
}
|
|
23139
|
+
|
|
23140
|
+
function appendPathSegment(points, segment) {
|
|
23141
|
+
if (!segment) return;
|
|
23142
|
+
segment.forEach(function(point, i) {
|
|
23143
|
+
if (i === 0 && points.length > 0 && point && points[points.length - 1]) {
|
|
23144
|
+
return;
|
|
23145
|
+
}
|
|
23146
|
+
points.push(point);
|
|
23147
|
+
});
|
|
23148
|
+
}
|
|
23149
|
+
|
|
23080
23150
|
function getGeodesicPixels(a, b) {
|
|
23081
23151
|
var displayCRS = gui.map.getDisplayCRS() || a.sourceCRS;
|
|
23082
23152
|
var project = displayCRS ? internal.getProjTransform2(wgs84, displayCRS) : null;
|
|
@@ -23264,6 +23334,31 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
23264
23334
|
path.removeAttribute('d');
|
|
23265
23335
|
}
|
|
23266
23336
|
|
|
23337
|
+
function drawRulerPointMarkers(useGreatCircleStyle) {
|
|
23338
|
+
drawMarker(startMarker, startPoint && startPoint.valid ? startPoint : null, useGreatCircleStyle);
|
|
23339
|
+
rulerPoints.slice(1).forEach(function(point, i) {
|
|
23340
|
+
drawMarker(getVertexMarker(i), point && point.valid ? point : null, useGreatCircleStyle);
|
|
23341
|
+
});
|
|
23342
|
+
for (var i = Math.max(0, rulerPoints.length - 1); i < vertexMarkers.length; i++) {
|
|
23343
|
+
hideMarker(vertexMarkers[i]);
|
|
23344
|
+
}
|
|
23345
|
+
}
|
|
23346
|
+
|
|
23347
|
+
function getVertexMarker(i) {
|
|
23348
|
+
var marker;
|
|
23349
|
+
while (vertexMarkers.length <= i) {
|
|
23350
|
+
marker = createSvgNode('circle');
|
|
23351
|
+
marker.classList.add('ruler-endpoint');
|
|
23352
|
+
svg.insertBefore(marker, endMarker);
|
|
23353
|
+
vertexMarkers.push(marker);
|
|
23354
|
+
}
|
|
23355
|
+
return vertexMarkers[i];
|
|
23356
|
+
}
|
|
23357
|
+
|
|
23358
|
+
function hideVertexMarkers() {
|
|
23359
|
+
vertexMarkers.forEach(hideMarker);
|
|
23360
|
+
}
|
|
23361
|
+
|
|
23267
23362
|
function drawMarker(marker, point, useGreatCircleStyle) {
|
|
23268
23363
|
var p;
|
|
23269
23364
|
if (!point) {
|