mapshaper 0.5.99 → 0.5.102

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,12 @@
1
+ v0.5.102
2
+ * Fix for bug in -v/--version command.
3
+
4
+ v0.5.101
5
+ * Update dependency.
6
+
7
+ v0.5.100
8
+ * Added support for using the basemap feature with datasets in a wide variety of projections.
9
+
1
10
  v0.5.99
2
11
  * Added support for viewing data against a Mapbox basemap (enabled on the mapshaper.org site).
3
12
 
package/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.5.96";
3
+ var VERSION = "0.5.102";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -4820,6 +4820,11 @@
4820
4820
  return !isLatLngCRS(P);
4821
4821
  }
4822
4822
 
4823
+ function isInvertibleCRS(P) {
4824
+ if (!P || !P.inv) return false;
4825
+ return true;
4826
+ }
4827
+
4823
4828
  function isLatLngCRS(P) {
4824
4829
  return P && P.is_latlong || false;
4825
4830
  }
@@ -4892,6 +4897,7 @@
4892
4897
  requireDatasetsHaveCompatibleCRS: requireDatasetsHaveCompatibleCRS,
4893
4898
  getScaleFactorAtXY: getScaleFactorAtXY,
4894
4899
  isProjectedCRS: isProjectedCRS,
4900
+ isInvertibleCRS: isInvertibleCRS,
4895
4901
  isLatLngCRS: isLatLngCRS,
4896
4902
  isWGS84: isWGS84,
4897
4903
  isWebMercator: isWebMercator,
@@ -34141,7 +34147,7 @@ ${svg}
34141
34147
  isCentered = ['tmerc', 'etmerc'].includes(str);
34142
34148
  proj4 = '+proj=' + str;
34143
34149
  if (isConic2SP || isCentered) {
34144
- bbox = getBBox(dataset);
34150
+ bbox = getBBox(dataset); // TODO: support projected datasets
34145
34151
  decimals = getBoundsPrecisionForDisplay(bbox);
34146
34152
  params = isCentered ? getCenterParams(bbox, decimals) : getConicParams(bbox, decimals);
34147
34153
  proj4 += ' ' + params;
@@ -34351,6 +34357,7 @@ ${svg}
34351
34357
 
34352
34358
  for (var i=0, n=xx.length; i<n; i++) {
34353
34359
  p = proj(xx[i], yy[i]);
34360
+ if (!p) error('Unprojectable point:', xx[i], yy[i]);
34354
34361
  xx[i] = p[0];
34355
34362
  yy[i] = p[1];
34356
34363
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.5.99",
3
+ "version": "0.5.102",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
package/www/index.html CHANGED
@@ -151,8 +151,8 @@
151
151
  <div class="basemap-options main-area popup-dialog">
152
152
  <div class="info-box">
153
153
  <h3>Basemap options</h3>
154
- <p>Basemaps are only displayed if the active layer has WGS84 or Web Mercator coordinates.</p>
155
- <p class="basemap-error"></p>
154
+ <p class="basemap-note">Your data will be displayed using the Mercator projection.</p>
155
+ <p class="basemap-warning"></p>
156
156
  <div class="basemap-styles"></div>
157
157
  <div>
158
158
  <div class="close-btn btn dialog-btn">Close</div>
@@ -1850,18 +1850,52 @@
1850
1850
 
1851
1851
  function projectArcsForDisplay(arcs, src, dest) {
1852
1852
  var copy = arcs.getCopy(); // need to flatten first?
1853
- var proj = internal.getProjTransform2(src, dest);
1854
- // TODO: think about densification
1853
+ var destIsWebMerc = internal.isWebMercator(dest);
1854
+ if (destIsWebMerc && internal.isWebMercator(src)) {
1855
+ return copy;
1856
+ }
1857
+
1858
+ var wgs84 = internal.getCRS('wgs84');
1859
+ var toWGS84 = internal.getProjTransform2(src, wgs84);
1860
+ var fromWGS84 = internal.getProjTransform2(wgs84, dest);
1861
+
1855
1862
  try {
1856
- // fast and preserves Z values, but throws on first unprojectable point
1857
- internal.projectArcs(copy, proj);
1863
+ // first try projectArcs() -- it's fast and preserves arc ids
1864
+ // (so vertex editing doesn't break)
1865
+ if (!internal.isWGS84(src)) {
1866
+ // use wgs84 as a pivot CRS, so we can handle polar coordinates
1867
+ // that can't be projected to Mercator
1868
+ internal.projectArcs(copy, toWGS84);
1869
+ }
1870
+ if (destIsWebMerc) {
1871
+ // handle polar points by clamping them to they will project
1872
+ // (downside: may cause unexpected behavior when editing vertices interactively)
1873
+ clampY(copy);
1874
+ }
1875
+ internal.projectArcs(copy, fromWGS84);
1858
1876
  } catch(e) {
1859
1877
  console.error(e);
1860
- internal.projectArcs2(copy, proj);
1878
+ // use the more robust projectArcs2 if projectArcs throws an error
1879
+ // downside: projectArcs2 discards Z values and changes arc indexing,
1880
+ // which will break vertex editing.
1881
+ var reproject = internal.getProjTransform2(src, dest);
1882
+ copy = arcs.getCopy();
1883
+ internal.projectArcs2(copy, reproject);
1861
1884
  }
1862
1885
  return copy;
1863
1886
  }
1864
1887
 
1888
+ function clampY(arcs) {
1889
+ var max = 89.9,
1890
+ min = -89.9,
1891
+ bbox = arcs.getBounds().toArray();
1892
+ if (bbox[1] >= min && bbox[3] <= max) return;
1893
+ arcs.transformPoints(function(x, y) {
1894
+ if (y > max) return [x, max];
1895
+ if (y < min) return [x, min];
1896
+ });
1897
+ }
1898
+
1865
1899
  function projectPointsForDisplay(lyr, src, dest) {
1866
1900
  var copy = utils$1.extend({}, lyr);
1867
1901
  var proj = internal.getProjTransform2(src, dest);
@@ -1870,6 +1904,33 @@
1870
1904
  return copy;
1871
1905
  }
1872
1906
 
1907
+ function toWebMercator(lng, lat) {
1908
+ var R = 6378137;
1909
+ var D2R = Math.PI / 180;
1910
+ var k = Math.cos(lat * D2R);
1911
+ var x = R * lng * D2R;
1912
+ var y = R * Math.log(Math.tan(Math.PI * 0.25 + lat * D2R * 0.5));
1913
+ return [x, y];
1914
+ }
1915
+
1916
+ function fromWebMercator(x, y) {
1917
+ var R = 6378137;
1918
+ var R2D = 180 / Math.PI;
1919
+ var lon = x / R * R2D;
1920
+ var lat = R2D * (Math.PI * 0.5 - 2 * Math.atan(Math.exp(-y / R)));
1921
+ return [lon, lat];
1922
+ }
1923
+
1924
+ function clampToMapboxBounds(bounds) {
1925
+ var ymax = toWebMercator(0, 84)[1];
1926
+ var ymin = toWebMercator(0, -84)[1];
1927
+ var hmin = 1000;
1928
+ bounds.ymin = Math.max(bounds.ymin, ymin);
1929
+ bounds.ymax = Math.max(bounds.ymax, ymin + hmin);
1930
+ bounds.ymin = Math.min(bounds.ymin, ymax - hmin);
1931
+ bounds.ymax = Math.min(bounds.ymax, ymax);
1932
+ }
1933
+
1873
1934
 
1874
1935
  // Update map extent and trigger redraw, after a new display CRS has been applied
1875
1936
  function projectMapExtent(ext, src, dest, newBounds) {
@@ -1877,6 +1938,10 @@
1877
1938
  var oldScale = ext.scale();
1878
1939
  var newCP, proj;
1879
1940
 
1941
+ if (dest && internal.isWebMercator(dest)) {
1942
+ clampToMapboxBounds(newBounds);
1943
+ }
1944
+
1880
1945
  // if source or destination CRS is unknown, show full extent
1881
1946
  // if map is at full extent, show full extent
1882
1947
  // TODO: handle case that scale is 1 and map is panned away from center
@@ -9577,9 +9642,10 @@
9577
9642
  var list = menu.findChild('.basemap-styles');
9578
9643
  var container = gui.container.findChild('.basemap-container');
9579
9644
  var basemapBtn = gui.container.findChild('.basemap-btn');
9580
- var basemapMsg = gui.container.findChild('.basemap-error');
9645
+ var basemapNote = gui.container.findChild('.basemap-note');
9646
+ var basemapWarning = gui.container.findChild('.basemap-warning');
9581
9647
  var mapEl = gui.container.findChild('.basemap');
9582
- var extentNote = El('div').addClass('basemap-note').appendTo(container).hide();
9648
+ var extentNote = El('div').addClass('basemap-prompt').appendTo(container).hide();
9583
9649
  var params = window.mapboxParams;
9584
9650
  var map;
9585
9651
  var activeStyle;
@@ -9638,15 +9704,24 @@
9638
9704
  }
9639
9705
 
9640
9706
  function turnOn() {
9641
- var crs = gui.map.getDisplayCRS();
9642
- if (!internal.isWebMercator(crs) && !internal.isWGS84(crs)) {
9643
- basemapMsg.html('The current projection is not compatible.');
9707
+ var activeLyr = gui.model.getActiveLayer();
9708
+ var dataCRS = internal.getDatasetCRS(activeLyr.dataset);
9709
+ var displayCRS = gui.map.getDisplayCRS();
9710
+ var warning;
9711
+
9712
+ if (!crsIsUsable(displayCRS) || !crsIsUsable(dataCRS)) {
9713
+ warning = 'The current layer is not compatible with the projection used by the basemaps.';
9714
+ basemapWarning.html(warning).show();
9715
+ basemapNote.hide();
9716
+ } else {
9717
+ basemapNote.show();
9644
9718
  }
9645
9719
  menu.show();
9646
9720
  }
9647
9721
 
9648
9722
  function turnOff() {
9649
- basemapMsg.html('');
9723
+ basemapWarning.hide();
9724
+ basemapNote.hide();
9650
9725
  menu.hide();
9651
9726
  }
9652
9727
 
@@ -9664,20 +9739,13 @@
9664
9739
  mapEl.node().style.display = 'none';
9665
9740
  }
9666
9741
 
9667
- function getBounds() {
9742
+ function getLonLatBounds() {
9668
9743
  var bbox = ext.getBounds().toArray();
9669
- var tr = getLonLat(bbox[2], bbox[3]);
9670
- var bl = getLonLat(bbox[0], bbox[1]);
9744
+ var tr = fromWebMercator(bbox[2], bbox[3]);
9745
+ var bl = fromWebMercator(bbox[0], bbox[1]);
9671
9746
  return bl.concat(tr);
9672
9747
  }
9673
9748
 
9674
- function getLonLat(x, y) {
9675
- var R = 6378137;
9676
- var R2D = 180 / Math.PI;
9677
- var lon = x / R * R2D;
9678
- var lat = R2D * (Math.PI * 0.5 - 2 * Math.atan(Math.exp(-y / R)));
9679
- return [lon, lat];
9680
- }
9681
9749
 
9682
9750
  function initMap() {
9683
9751
  if (!enabled() || map || loading) return;
@@ -9689,7 +9757,7 @@
9689
9757
  logoPosition: 'bottom-left',
9690
9758
  container: mapEl.node(),
9691
9759
  style: activeStyle.url,
9692
- bounds: getBounds(),
9760
+ bounds: getLonLatBounds(),
9693
9761
  doubleClickZoom: false,
9694
9762
  dragPan: false,
9695
9763
  dragRotate: false,
@@ -9719,15 +9787,23 @@
9719
9787
  return false;
9720
9788
  }
9721
9789
 
9790
+ function crsIsUsable(crs) {
9791
+ if (!crs) return false;
9792
+ if (!internal.isInvertibleCRS(crs)) return false;
9793
+ return true;
9794
+ }
9795
+
9722
9796
  function refresh() {
9723
9797
  if (!enabled() || !map || loading || !activeStyle) return;
9724
9798
  var crs = gui.map.getDisplayCRS();
9725
- if (internal.isWGS84(crs)) {
9726
- gui.map.setDisplayCRS(internal.getCRS('webmercator'));
9727
- } else if (!internal.isWebMercator(crs)) {
9799
+ if (!crsIsUsable(crs)) {
9800
+ hide();
9728
9801
  return;
9729
9802
  }
9730
- var bbox = getBounds();
9803
+ if (!internal.isWebMercator(crs)) {
9804
+ gui.map.setDisplayCRS(internal.getCRS('webmercator'));
9805
+ }
9806
+ var bbox = getLonLatBounds();
9731
9807
  if (!checkBounds(bbox)) {
9732
9808
  // map does not display outside these bounds
9733
9809
  hide();
package/www/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.5.96";
3
+ var VERSION = "0.5.102";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -4820,6 +4820,11 @@
4820
4820
  return !isLatLngCRS(P);
4821
4821
  }
4822
4822
 
4823
+ function isInvertibleCRS(P) {
4824
+ if (!P || !P.inv) return false;
4825
+ return true;
4826
+ }
4827
+
4823
4828
  function isLatLngCRS(P) {
4824
4829
  return P && P.is_latlong || false;
4825
4830
  }
@@ -4892,6 +4897,7 @@
4892
4897
  requireDatasetsHaveCompatibleCRS: requireDatasetsHaveCompatibleCRS,
4893
4898
  getScaleFactorAtXY: getScaleFactorAtXY,
4894
4899
  isProjectedCRS: isProjectedCRS,
4900
+ isInvertibleCRS: isInvertibleCRS,
4895
4901
  isLatLngCRS: isLatLngCRS,
4896
4902
  isWGS84: isWGS84,
4897
4903
  isWebMercator: isWebMercator,
@@ -34141,7 +34147,7 @@ ${svg}
34141
34147
  isCentered = ['tmerc', 'etmerc'].includes(str);
34142
34148
  proj4 = '+proj=' + str;
34143
34149
  if (isConic2SP || isCentered) {
34144
- bbox = getBBox(dataset);
34150
+ bbox = getBBox(dataset); // TODO: support projected datasets
34145
34151
  decimals = getBoundsPrecisionForDisplay(bbox);
34146
34152
  params = isCentered ? getCenterParams(bbox, decimals) : getConicParams(bbox, decimals);
34147
34153
  proj4 += ' ' + params;
@@ -34351,6 +34357,7 @@ ${svg}
34351
34357
 
34352
34358
  for (var i=0, n=xx.length; i<n; i++) {
34353
34359
  p = proj(xx[i], yy[i]);
34360
+ if (!p) error('Unprojectable point:', xx[i], yy[i]);
34354
34361
  xx[i] = p[0];
34355
34362
  yy[i] = p[1];
34356
34363
  }
package/www/page.css CHANGED
@@ -1015,11 +1015,11 @@ img.close-btn:hover,
1015
1015
  white-space: nowrap;
1016
1016
  }
1017
1017
 
1018
- .basemap-error {
1018
+ .basemap-warning {
1019
1019
  color: #cc0000;
1020
1020
  }
1021
1021
 
1022
- .basemap-note {
1022
+ .basemap-prompt {
1023
1023
  width: 100%;
1024
1024
  text-align: center;
1025
1025
  z-index: -2;