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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.7.41",
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.3",
74
+ "mproj": "0.1.5",
75
75
  "msgpackr": "^1.11.12",
76
76
  "open": "^11.0.0",
77
77
  "pngjs": "^7.0.0",
@@ -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 endPoint = pointerPoint;
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
- drawMarker(startMarker, startPoint);
22856
+ drawRulerPointMarkers(false);
22847
22857
  hideMarker(endMarker);
22848
22858
  popup.hide();
22849
22859
  return;
22850
22860
  }
22851
22861
 
22852
- if (!startPoint.valid || !endPoint.valid) {
22862
+ if (!path.every(pointIsValid)) {
22853
22863
  clearSvgPath(directPath);
22854
22864
  clearSvgPath(geodesicPath);
22855
- drawMarker(startMarker, startPoint.valid ? startPoint : null, false);
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(startPoint, endPoint);
22862
- drawRulerLines(startPoint, endPoint, measurement);
22863
- drawMarker(startMarker, startPoint, measurement.isLatLng);
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 drawRulerLines(a, b, measurement) {
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, getGeodesicPixels(a, b));
22892
+ drawPath(geodesicPath, getGeodesicPathPixels(path));
22875
22893
  clearSvgPath(directPath);
22876
22894
  } else {
22877
- drawPath(directPath, [a.display, b.display]);
22878
- drawPath(geodesicPath, measurement.greatCircleMeters ? getGeodesicPixels(a, b) : null);
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 startDist = getEndpointPixelDistance(startPoint, x, y);
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 (startDist > ENDPOINT_HIT_RADIUS && endDist > ENDPOINT_HIT_RADIUS) return null;
22910
- return startDist <= endDist ? 'start' : 'end';
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 == 'start' ? startPoint : pointerPoint;
22950
+ return endpoint.type == 'fixed' ? rulerPoints[endpoint.index] : pointerPoint;
22922
22951
  }
22923
22952
 
22924
22953
  function setEndpoint(endpoint, point) {
22925
- if (endpoint == 'start') {
22926
- startPoint = point;
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
- startPoint = reprojectRulerPoint(startPoint);
22988
+ rulerPoints = rulerPoints.map(reprojectRulerPoint);
22989
+ startPoint = rulerPoints[0] || null;
22959
22990
  pointerPoint = reprojectRulerPoint(pointerPoint);
22960
- if (startPoint && !startPoint.valid || pointerPoint && !pointerPoint.valid) {
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(a, b) {
23047
- var isLatLng = internal.isLatLngCRS(a.sourceCRS);
23048
- var projectedMeters = isLatLng ? null : getProjectedDistanceMeters(a, b);
23049
- var greatCircleMeters = getGreatCircleDistanceMeters(a, b);
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) {