mapshaper 0.6.79 → 0.6.80

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 CHANGED
@@ -1612,6 +1612,7 @@
1612
1612
  this.ymin -= halfHeight * ky;
1613
1613
  this.xmax += halfWidth * kx;
1614
1614
  this.ymax += halfHeight * ky;
1615
+ return this;
1615
1616
  };
1616
1617
 
1617
1618
  // Return a bounding box with the same extent as this one.
@@ -5003,7 +5004,7 @@
5003
5004
  if (isLatLngCRS(P)) {
5004
5005
  return xy.concat();
5005
5006
  }
5006
- proj = getProjTransform(P, parseCrsString('wgs84'));
5007
+ proj = getProjTransform2(P, parseCrsString('wgs84'));
5007
5008
  return proj(xy[0], xy[1]);
5008
5009
  }
5009
5010
 
@@ -26664,7 +26665,7 @@ ${svg}
26664
26665
  codepage = lookupCodePage(ldid),
26665
26666
  samples = getNonAsciiSamples(),
26666
26667
  only7bit = samples.length === 0,
26667
- encoding, msg;
26668
+ encoding;
26668
26669
 
26669
26670
  // First, check the ldid (language driver id) (an obsolete way to specify which
26670
26671
  // codepage to use for text encoding.)
@@ -26684,10 +26685,12 @@ ${svg}
26684
26685
  // As a last resort, try to guess the encoding:
26685
26686
  if (!encoding) {
26686
26687
  var info = detectEncoding(samples);
26688
+ var msg;
26687
26689
  encoding = info.encoding;
26688
26690
  if (info.confidence < 2) {
26689
- msg = 'Warning: Unable to auto-detect the DBF file text encoding with high confidence.';
26690
- msg += '\n\nDefaulting to: ' + encoding + (encoding in encodingNames ? ' (' + encodingNames[encoding] + ')' : '');
26691
+ msg = 'Warning: Unable to auto-detect the DBF file text encoding' +
26692
+ (info.confidence == 1 ? ' with high confidence' : '') + '.';
26693
+ msg += ' Defaulting to ' + encoding + (encoding in encodingNames ? ' (' + encodingNames[encoding] + ').' : '.');
26691
26694
  msg += '\n\nSample of how non-ascii text was imported:\n';
26692
26695
  if (runningInBrowser()) {
26693
26696
  msg += '<pre>' + formatStringsAsGrid(decodeSamples(encoding, samples), 50) + '</pre>';
@@ -45532,7 +45535,7 @@ ${svg}
45532
45535
  });
45533
45536
  }
45534
45537
 
45535
- var version = "0.6.79";
45538
+ var version = "0.6.80";
45536
45539
 
45537
45540
  // Parse command line args into commands and run them
45538
45541
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.6.79",
3
+ "version": "0.6.80",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -2544,6 +2544,20 @@
2544
2544
  };
2545
2545
  }
2546
2546
 
2547
+ // p1: [x, y] coords
2548
+ // p2: [x, y] coords offset by 1x1 pixel
2549
+ function formatCoordsForDisplay(p1, p2) {
2550
+ var dx = Math.abs(p1[0] - p2[0]);
2551
+ var dy = Math.abs(p1[1] - p2[1]);
2552
+ var offs = (dx + dy) / 2;
2553
+ var decimals = 0;
2554
+ while (offs < 1 && decimals < 6) {
2555
+ offs *= 10;
2556
+ decimals++;
2557
+ }
2558
+ return [p1[0].toFixed(decimals), p1[1].toFixed(decimals)];
2559
+ }
2560
+
2547
2561
  // Convert a point from display CRS coordinates to data coordinates.
2548
2562
  // These are only different when using dynamic reprojection (basemap view).
2549
2563
  function translateDisplayPoint(lyr, p) {
@@ -2563,8 +2577,7 @@
2563
2577
  }
2564
2578
 
2565
2579
  function isProjectedLayer(lyr) {
2566
- // TODO: could do some validation on the layer's contents
2567
- return !!lyr.gui.invertPoint;
2580
+ return !!lyr?.gui.invertPoint;
2568
2581
  }
2569
2582
 
2570
2583
  var darkStroke = "#334",
@@ -2765,30 +2778,7 @@
2765
2778
 
2766
2779
 
2767
2780
  function getDefaultStyle(lyr, baseStyle) {
2768
- var style = Object.assign({}, baseStyle);
2769
- // reduce the dot size of large point layers
2770
- if (lyr.geometry_type == 'point' && style.dotSize > 0) {
2771
- style.dotSize *= getDotScale$1(lyr);
2772
- }
2773
- return style;
2774
- }
2775
-
2776
- function getDotScale$1(lyr) {
2777
- var topTier = 10000;
2778
- var n = countPoints(lyr.shapes, topTier); // short-circuit point counting above top threshold
2779
- var k = n < 200 && 4 || n < 2500 && 3 || n < topTier && 2 || 1;
2780
- return k;
2781
- }
2782
-
2783
- function countPoints(shapes, max) {
2784
- var count = 0;
2785
- var i, n, shp;
2786
- max = max || Infinity;
2787
- for (i=0, n=shapes.length; i<n && count<max; i++) {
2788
- shp = shapes[i];
2789
- count += shp ? shp.length : 0;
2790
- }
2791
- return count;
2781
+ return Object.assign({}, baseStyle);
2792
2782
  }
2793
2783
 
2794
2784
 
@@ -3232,6 +3222,58 @@
3232
3222
  return layers.reverse();
3233
3223
  }
3234
3224
 
3225
+
3226
+ function adjustPointSymbolSizes(layers, overlayLyr, ext) {
3227
+ var bbox = ext.getBounds().scale(1.5).toArray();
3228
+ var testInBounds = function(p) {
3229
+ return p[0] > bbox[0] && p[0] < bbox[2] && p[1] > bbox[1] && p[1] < bbox[3];
3230
+ };
3231
+ var topTier = 50000;
3232
+ var count = 0;
3233
+ layers = layers.filter(function(lyr) {
3234
+ return lyr.geometry_type == 'point' && lyr.gui.style.dotSize > 0;
3235
+ });
3236
+ layers.forEach(function(lyr) {
3237
+ // short-circuit point counting above top threshold
3238
+ count += countPoints(lyr.gui.displayLayer.shapes, topTier, testInBounds);
3239
+ });
3240
+ count = Math.min(topTier, count) || 1;
3241
+ var k = Math.pow(6 - utils$1.clamp(Math.log10(count), 1, 5), 1.3);
3242
+
3243
+ // zoom adjustments
3244
+ var mapScale = ext.scale();
3245
+ if (mapScale < 0.5) {
3246
+ k *= Math.pow(mapScale + 0.5, 0.35);
3247
+ } else if (mapScale > 1) {
3248
+ // scale faster at first
3249
+ k *= Math.pow(Math.min(mapScale, 4), 0.15);
3250
+ k *= Math.pow(mapScale, 0.05);
3251
+ }
3252
+
3253
+ // scale down when map is small
3254
+ var smallSide = Math.min(ext.width(), ext.height());
3255
+ k *= utils$1.clamp(smallSide / 500, 0.5, 1);
3256
+
3257
+ layers.forEach(function(lyr) {
3258
+ lyr.gui.style.dotScale = k;
3259
+ });
3260
+ if (overlayLyr && overlayLyr.geometry_type == 'point' && overlayLyr.gui.style.dotSize > 0) {
3261
+ overlayLyr.gui.style.dotScale = k;
3262
+ }
3263
+ }
3264
+
3265
+ function countPoints(shapes, max, filter) {
3266
+ var count = 0;
3267
+ var i, j, n, m, shp;
3268
+ for (i=0, n=shapes.length; i<n && count<max; i++) {
3269
+ shp = shapes[i];
3270
+ for (j=0, m=(shp ? shp.length : 0); j<m; j++) {
3271
+ count += filter(shp[j]) ? 1 : 0;
3272
+ }
3273
+ }
3274
+ return count;
3275
+ }
3276
+
3235
3277
  // lyr: a map layer with gui property
3236
3278
  // displayCRS: CRS to use for display, or null (which clears any current display CRS)
3237
3279
  function projectLayerForDisplay(lyr, displayCRS) {
@@ -3286,6 +3328,13 @@
3286
3328
  }
3287
3329
  }
3288
3330
 
3331
+ // make sure that every path layer has an associated arc collection
3332
+ // (if the layer is empty, its dataset may not have an arc collection).
3333
+ // this enables adding shapes using the drawing tools.
3334
+ if (!dataset.arcs && (layer.geometry_type == 'polygon' || layer.geometry_type == 'polyline')) {
3335
+ dataset.arcs = new internal.ArcCollection();
3336
+ }
3337
+
3289
3338
  // Assume that dataset.displayArcs is in the display CRS
3290
3339
  // (it must be deleted upstream if reprojection is needed)
3291
3340
  // if (!obj.empty && dataset.arcs && !displayArcs) {
@@ -3370,6 +3419,17 @@
3370
3419
  }
3371
3420
  }
3372
3421
 
3422
+ function pencilPointIsSkippable(p2, points) {
3423
+ var p1 = points[0];
3424
+ var dist;
3425
+ if (points.length < 2) return true;
3426
+ for (var i=1; i<points.length; i++) {
3427
+ dist = Math.sqrt(geom.pointSegDistSq(points[i][0], points[i][1], p1[0], p1[1], p2[0], p2[1]));
3428
+ if (dist > 1.5) return false;
3429
+ }
3430
+ return true;
3431
+ }
3432
+
3373
3433
  function setZ(lyr, z) {
3374
3434
  lyr.gui.source.dataset.arcs.setRetainedInterval(z);
3375
3435
  if (isProjectedLayer(lyr)) {
@@ -5620,7 +5680,6 @@
5620
5680
  gui.on('active', updateVisibility);
5621
5681
  gui.on('inactive', updateVisibility);
5622
5682
  gui.model.on('update', updateVisibility);
5623
- gui.on('mode', updateVisibility);
5624
5683
 
5625
5684
  // @iconRef: selector for an (svg) button icon
5626
5685
  this.addButton = function(iconRef) {
@@ -5649,10 +5708,7 @@
5649
5708
  };
5650
5709
 
5651
5710
  function updateVisibility() {
5652
- var noData = !gui.model.getActiveLayer();
5653
- if (GUI.isActiveInstance(gui) && !_hidden && !noData) {
5654
- buttons.show();
5655
- } else if (noData && gui.getMode() != 'import') {
5711
+ if (GUI.isActiveInstance(gui) && !_hidden) {
5656
5712
  buttons.show();
5657
5713
  } else {
5658
5714
  buttons.hide();
@@ -5746,29 +5802,37 @@
5746
5802
  var self = this;
5747
5803
  var shiftDown = false;
5748
5804
  var ctrlDown = false;
5805
+ var metaDown = false;
5806
+ var altDown = false;
5807
+
5808
+ function updateControlKeys(e) {
5809
+ shiftDown = e.shiftKey;
5810
+ ctrlDown = e.ctrlKey;
5811
+ metaDown = e.metaKey;
5812
+ altDown = e.altKey;
5813
+ }
5749
5814
  document.addEventListener('keyup', function(e) {
5750
5815
  if (!GUI.isActiveInstance(gui)) return;
5751
5816
  // this can fail to fire if keyup occurs over a context menu
5752
- shiftDown = e.shiftKey;
5753
- ctrlDown = e.ctrlKey;
5817
+ updateControlKeys(e);
5754
5818
  self.dispatchEvent('keyup', getEventData(e));
5755
5819
  });
5756
5820
 
5757
5821
  document.addEventListener('keydown', function(e) {
5758
5822
  if (!GUI.isActiveInstance(gui)) return;
5759
- shiftDown = e.shiftKey;
5760
- ctrlDown = e.ctrlKey;
5823
+ updateControlKeys(e);
5761
5824
  self.dispatchEvent('keydown', getEventData(e));
5762
5825
  });
5763
5826
 
5764
5827
  document.addEventListener('mousemove', function(e) {
5765
5828
  // refreshing these here to prevent problems when context menu opens
5766
- shiftDown = e.shiftKey;
5767
- ctrlDown = e.ctrlKey;
5829
+ updateControlKeys(e);
5768
5830
  });
5769
5831
 
5770
5832
  this.shiftIsPressed = function() { return shiftDown; };
5771
5833
  this.ctrlIsPressed = function() { return ctrlDown; };
5834
+ this.altIsPressed = function() { return altDown; };
5835
+ this.metaIsPressed = function() { return metaDown; };
5772
5836
 
5773
5837
  this.onMenuSubmit = function(menuEl, cb) {
5774
5838
  gui.on('enter_key', function(e) {
@@ -7999,7 +8063,9 @@
7999
8063
  return;
8000
8064
  }
8001
8065
  e.originalEvent.preventDefault();
8002
- if (!targetLayer) return; // TODO: enable menu on empty map
8066
+ if (!El('body').hasClass('map-view')) {
8067
+ return;
8068
+ }
8003
8069
  triggerHitEvent('contextmenu', e);
8004
8070
  }, false);
8005
8071
 
@@ -8423,7 +8489,9 @@
8423
8489
  mode: interactionMode
8424
8490
  };
8425
8491
  if (evt) {
8492
+ // data coordinates
8426
8493
  eventData.coordinates = translateDisplayPoint(targetLayer, ext.translatePixelCoords(evt.x, evt.y));
8494
+ eventData.display_coordinates = gui.map.pixelCoordsToDisplayCoords(evt.x, evt.y);
8427
8495
  eventData.originalEvent = evt;
8428
8496
  eventData.overMap = isOverMap(evt);
8429
8497
  }
@@ -9304,8 +9372,7 @@
9304
9372
 
9305
9373
  function useBoxZoom() {
9306
9374
  var mode = gui.getMode();
9307
- var disabled = ['selection_tool', 'box_tool', 'rectangle_tool'].includes(mode);
9308
- return !disabled;
9375
+ return !'selection_tool,box_tool,rectangle_tool,drawing_tool'.includes(mode);
9309
9376
  }
9310
9377
 
9311
9378
  function getBoxData(e) {
@@ -9838,7 +9905,7 @@
9838
9905
 
9839
9906
  hit.on('contextmenu', function(e) {
9840
9907
  var target = hit.getHitTarget();
9841
- if (!e.overMap || !target || e.mode == 'edit_lines' ||
9908
+ if (!e.overMap || e.mode == 'edit_lines' ||
9842
9909
  e.mode == 'edit_polygons' || e.mode == 'edit_points') {
9843
9910
  return;
9844
9911
  }
@@ -10265,6 +10332,7 @@
10265
10332
  var drawingId = -1; // feature id of path being drawn
10266
10333
  var sessionCount = 0;
10267
10334
  var alert;
10335
+ var pencilPoints;
10268
10336
  var _dragging = false;
10269
10337
 
10270
10338
  function active() {
@@ -10279,6 +10347,10 @@
10279
10347
  return drawingId > -1;
10280
10348
  }
10281
10349
 
10350
+ function usingPencil() {
10351
+ return (gui.keyboard.altIsPressed() || gui.keyboard.metaIsPressed()) && active() && !dragging();
10352
+ }
10353
+
10282
10354
  function polygonMode() {
10283
10355
  return active() && hit.getHitTarget().geometry_type == 'polygon';
10284
10356
  }
@@ -10360,11 +10432,12 @@
10360
10432
 
10361
10433
  function showInstructions() {
10362
10434
  var isMac = navigator.userAgent.includes('Mac');
10363
- var symbol = isMac ? '⌘' : '^';
10435
+ var undoKey = isMac ? '⌘' : '^';
10436
+ var drawKey = isMac ? '⌘' : 'Alt';
10364
10437
  var pathStr = polygonMode() ? 'closed paths' : 'paths';
10365
- var msg = `Instructions: Click on the map to draw ${pathStr}. Drag vertices to reshape a path. Type ${symbol}Z/${symbol}Y to undo/redo.`;
10438
+ var msg = `Instructions: Click to start a path or add a point. ${drawKey}-drag draws a path. Drag points to reshape. Type ${undoKey}Z/${undoKey}Y to undo/redo.`;
10366
10439
  alert = showPopupAlert(msg, null, {
10367
- non_blocking: true, max_width: '360px'});
10440
+ non_blocking: true, max_width: '388px'});
10368
10441
  }
10369
10442
 
10370
10443
  function hideInstructions() {
@@ -10449,9 +10522,28 @@
10449
10522
  hit.setHoverVertex(hoverVertexInfo.displayPoint, hoverVertexInfo.type);
10450
10523
  });
10451
10524
 
10525
+ gui.map.getMouse().on('drag', function(e) {
10526
+ if (!usingPencil()) return;
10527
+ e.stopPropagation();
10528
+ var xy = [e.x, e.y];
10529
+ var p = pixToDataCoords(e.x, e.y);
10530
+ if (!drawing()) {
10531
+ pencilPoints = [xy];
10532
+ startNewPath(p);
10533
+ } else if (!pencilPoints || !pencilPointIsSkippable(xy, pencilPoints)) {
10534
+ pencilPoints = [xy];
10535
+ extendCurrentPath(p);
10536
+ } else {
10537
+ // skip this point, update the hover line
10538
+ pencilPoints.push(xy);
10539
+ updatePathEndpoint(p);
10540
+ }
10541
+ }, null, 3); // higher priority than hit control
10542
+
10452
10543
  hit.on('drag', function(e) {
10453
10544
  if (!dragging() || drawing()) return;
10454
10545
  e.originalEvent.stopPropagation();
10546
+ // dragging a vertex
10455
10547
  var target = hit.getHitTarget();
10456
10548
  var p = ext.translatePixelCoords(e.x, e.y);
10457
10549
  if (gui.keyboard.shiftIsPressed()) {
@@ -10530,8 +10622,6 @@
10530
10622
  deleteActiveVertex(e);
10531
10623
  } else {
10532
10624
  startNewPath(p);
10533
- hideInstructions();
10534
- updateCursor();
10535
10625
  }
10536
10626
  prevClickEvent = e;
10537
10627
  });
@@ -10642,6 +10732,14 @@
10642
10732
  gui.dispatchEvent('path_add', {target, p1, p2});
10643
10733
  drawingId = target.shapes.length - 1;
10644
10734
  hit.setDrawingId(drawingId);
10735
+ hideInstructions();
10736
+ updateCursor();
10737
+ }
10738
+
10739
+ function pencilDraw(e) {
10740
+ var p = pixToDataCoords(e.x, e.y);
10741
+ extendCurrentPath(p);
10742
+
10645
10743
  }
10646
10744
 
10647
10745
  // p: [x, y] source data coordinates of new point on path
@@ -10662,7 +10760,6 @@
10662
10760
  gui.dispatchEvent('path_extend', {target, p, shapes1, shapes2});
10663
10761
  clearDrawingInfo();
10664
10762
  fullRedraw();
10665
-
10666
10763
  } else {
10667
10764
  appendVertex$1(target, p);
10668
10765
  gui.dispatchEvent('path_extend', {target, p});
@@ -10699,20 +10796,19 @@
10699
10796
  function findPathStartInfo(e) {
10700
10797
  var target = hit.getHitTarget();
10701
10798
  var arcId = target.gui.displayArcs.size() - 1;
10702
- var data = target.gui.displayArcs.getVertexData();
10799
+ var p1 = ext.translatePixelCoords(e.x, e.y); // mouse coords
10800
+ var p2 = internal.getArcStartCoords(arcId, target.gui.displayArcs); // vertex coords
10801
+ var p3 = internal.getArcStartCoords(arcId, target.gui.source.dataset.arcs);
10802
+ var dist = geom.distance2D(p1[0], p1[1], p2[0], p2[1]);
10803
+ var data = target.gui.source.dataset.arcs.getVertexData();
10703
10804
  var i = data.ii[arcId];
10704
- var x = data.xx[i];
10705
- var y = data.yy[i];
10706
- var p = ext.translatePixelCoords(e.x, e.y);
10707
- var dist = geom.distance2D(p[0], p[1], x, y);
10708
10805
  var pathLen = data.nn[arcId];
10709
10806
  var pixelDist = dist / ext.getPixelSize();
10710
10807
  if (pixelDist > HOVER_THRESHOLD || pathLen < 4) {
10711
10808
  return null;
10712
10809
  }
10713
- var point = translateDisplayPoint(target, [x, y]);
10714
10810
  return {
10715
- target, ids: [i], extendable: false, point, displayPoint: [x, y], type: 'vertex'
10811
+ target, ids: [i], extendable: false, displayPoint: p2, point: p3, type: 'vertex'
10716
10812
  };
10717
10813
  }
10718
10814
 
@@ -10948,6 +11044,7 @@
10948
11044
  }
10949
11045
  };
10950
11046
 
11047
+ // translate display CRS coords to pixel coords
10951
11048
  this.translateCoords = function(x, y) {
10952
11049
  return this.getTransform().transform(x, y);
10953
11050
  };
@@ -10967,6 +11064,7 @@
10967
11064
  return bounds2.width() / _frame.width;
10968
11065
  };
10969
11066
 
11067
+ // convert pixel coords (0,0 is top left corner of map) to display CRS coords
10970
11068
  this.translatePixelCoords = function(x, y) {
10971
11069
  return this.getTransform().invert().transform(x, y);
10972
11070
  };
@@ -11429,8 +11527,7 @@
11429
11527
 
11430
11528
  _self.drawSquareDots = function(shapes, style) {
11431
11529
  var t = getScaledTransform(_ext),
11432
- scaleRatio = getDotScale(_ext),
11433
- size = Math.round((style.dotSize || 1) * scaleRatio),
11530
+ size = getDotSize(style),
11434
11531
  styler = style.styler || null,
11435
11532
  xmax = _canvas.width + size,
11436
11533
  ymax = _canvas.height + size,
@@ -11450,7 +11547,7 @@
11450
11547
  for (i=0, n=shapes.length; i<n; i++) {
11451
11548
  if (styler !== null) { // e.g. selected points
11452
11549
  styler(style, i);
11453
- size = style.dotSize * scaleRatio;
11550
+ size = getDotSize(style);
11454
11551
  if (style.dotColor != color) {
11455
11552
  color = style.dotColor;
11456
11553
  _ctx.fillStyle = color;
@@ -11597,25 +11694,16 @@
11597
11694
  return s;
11598
11695
  }
11599
11696
 
11600
- function getDotScale(ext) {
11601
- var smallSide = Math.min(ext.width(), ext.height());
11602
- var mapScale = ext.scale();
11603
- // reduce size on smaller screens
11604
- var j = smallSide < 200 && 0.5 || smallSide < 400 && 0.75 || 1;
11605
- // grow dots as map zooms in
11606
- var k = 1;
11607
- if (mapScale < 0.5) {
11608
- k = Math.pow(mapScale + 0.5, 0.35);
11609
- } else if (mapScale > 1) {
11610
- // scale faster at first, so small dots in large datasets
11611
- // become easily visible and clickable after zooming in a bit
11612
- k *= Math.pow(Math.min(mapScale, 10), 0.3);
11613
- k *= Math.pow(mapScale, 0.1);
11614
- }
11615
- // grow pixels more slowly on retina displays (to reduce number of pixels to
11616
- // draw for large point datasets when slightly zoomed in)
11617
- var l = Math.pow(GUI.getPixelRatio(), 0.8);
11618
- return j * k * l;
11697
+ function getDotSize(style) {
11698
+ var size = style.dotSize || 1;
11699
+ // TODO: improve
11700
+ var scale = style.dotScale || 1;
11701
+ size += (scale - 1) / 2;
11702
+ size *= Math.pow(scale, 0.3);
11703
+
11704
+ // shrink dots slightly on retina displays, to adjust for greater clarity
11705
+ // and reduce number of pixels to draw on large datasets.
11706
+ return Math.round(Math.pow(GUI.getPixelRatio(), 0.8) * size);
11619
11707
  }
11620
11708
 
11621
11709
  function getScaledTransform(ext) {
@@ -12537,16 +12625,27 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
12537
12625
  return internal.toLngLat(p, _dynamicCRS);
12538
12626
  };
12539
12627
 
12540
- this.getCenterLngLat = function() {
12541
- var bounds = _ext.getBounds();
12628
+ this.pixelCoordsToDisplayCoords = function(x, y) {
12629
+ var p1 = _ext.translatePixelCoords(x, y);
12630
+ var p2 = _ext.translatePixelCoords(x+1, y+1);
12542
12631
  var crs = this.getDisplayCRS();
12543
- // TODO: handle case where active layer is a frame layer
12544
- if (!bounds.hasBounds() || !crs) {
12545
- return null;
12632
+ if (crs) {
12633
+ p1 = internal.toLngLat(p1, crs) || p1;
12634
+ p2 = internal.toLngLat(p2, crs) || p2;
12546
12635
  }
12547
- return internal.toLngLat([bounds.centerX(), bounds.centerY()], crs);
12636
+ return formatCoordsForDisplay(p1, p2);
12548
12637
  };
12549
12638
 
12639
+ // this.getCenterLngLat = function() {
12640
+ // var bounds = _ext.getBounds();
12641
+ // var crs = this.getDisplayCRS();
12642
+ // // TODO: handle case where active layer is a frame layer
12643
+ // if (!bounds.hasBounds() || !crs) {
12644
+ // return null;
12645
+ // }
12646
+ // return internal.toLngLat([bounds.centerX(), bounds.centerY()], crs);
12647
+ // };
12648
+
12550
12649
  this.getDisplayCRS = function() {
12551
12650
  if (!_activeLyr) {
12552
12651
  return _dynamicCRS || internal.parseCrsString('wgs84');
@@ -12613,7 +12712,6 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
12613
12712
  _ext.setFullBounds(calcFullBounds());
12614
12713
  _ext.resize();
12615
12714
  _renderer = new LayerRenderer(gui, el);
12616
- gui.buttons.show();
12617
12715
 
12618
12716
  if (opts.inspectorControl) {
12619
12717
  _hit = new HitControl(gui, _ext, _mouse),
@@ -12675,10 +12773,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
12675
12773
  }
12676
12774
 
12677
12775
  if (e.layer) {
12678
- enhanceLayerForDisplay(e.layer, e.dataset, getDisplayOptions());
12679
- _activeLyr = e.layer;
12680
- _activeLyr.gui.style = getActiveLayerStyle(_activeLyr.gui.displayLayer, getGlobalStyleOptions());
12681
- _activeLyr.active = true;
12776
+ _activeLyr = initActiveLayer(e.layer, e.dataset);
12682
12777
  } else {
12683
12778
  _activeLyr = null;
12684
12779
  }
@@ -12716,10 +12811,12 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
12716
12811
 
12717
12812
 
12718
12813
  function updateOverlayLayer(e) {
12719
- var style = getOverlayStyle(_activeLyr.gui.displayLayer, e, getGlobalStyleOptions());
12814
+ var style = !_activeLyr?.gui?.style ? null :
12815
+ getOverlayStyle(_activeLyr.gui.displayLayer, e, getGlobalStyleOptions());
12720
12816
  if (style) {
12721
12817
  var displayLayer = filterLayerByIds(_activeLyr.gui.displayLayer, style.ids);
12722
12818
  var gui = Object.assign({}, _activeLyr.gui, {style, displayLayer});
12819
+ style.dotScale = _activeLyr.gui.style.dotScale;
12723
12820
  _overlayLyr = utils$1.defaults({gui}, _activeLyr);
12724
12821
  } else {
12725
12822
  _overlayLyr = null;
@@ -12863,6 +12960,17 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
12863
12960
  });
12864
12961
  }
12865
12962
 
12963
+ function initActiveLayer(lyr, dataset) {
12964
+ enhanceLayerForDisplay(lyr, dataset, getDisplayOptions());
12965
+ lyr.gui.style = getActiveLayerStyle(lyr.gui.displayLayer, getGlobalStyleOptions());
12966
+ lyr.active = true;
12967
+ getVisibleMapLayers().forEach(function(lyr) {
12968
+ delete lyr.active;
12969
+ });
12970
+ lyr.active = true;
12971
+ return lyr;
12972
+ }
12973
+
12866
12974
  function getDrawableFurnitureLayers(layers) {
12867
12975
  if (!isPreviewView()) return [];
12868
12976
  return getVisibleMapLayers().filter(function(o) {
@@ -12929,6 +13037,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
12929
13037
  updateLayerStyles(contentLayers);
12930
13038
  updateLayerStackOrder(model.getLayers());// update menu_order property of all layers
12931
13039
  }
13040
+ adjustPointSymbolSizes(contentLayers, _overlayLyr, _ext);
12932
13041
  sortMapLayers(contentLayers);
12933
13042
  if (_intersectionLyr) {
12934
13043
  contentLayers = contentLayers.concat(_intersectionLyr);
@@ -12997,7 +13106,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
12997
13106
  menu.hide();
12998
13107
  _open = false;
12999
13108
  }
13000
- }, 300);
13109
+ }, 200);
13001
13110
  }
13002
13111
 
13003
13112
  function addMenuItem(label, func) {
@@ -13010,7 +13119,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13010
13119
  }
13011
13120
 
13012
13121
  this.open = function(e, lyr) {
13013
- if (!lyr || !lyr.gui.geographic) return;
13122
+ if (lyr && !lyr.gui.geographic) return; // no popup for tabular data
13014
13123
  _open = true;
13015
13124
  _openCount++;
13016
13125
  var rspace = body.clientWidth - e.pageX;
@@ -13026,8 +13135,9 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13026
13135
  menu.css('top', (e.pageY - 15) + 'px');
13027
13136
 
13028
13137
  // menu contents
13029
- if (e.coordinates) {
13030
- addCopyCoords();
13138
+ //
13139
+ if (e.display_coordinates) {
13140
+ addCoords(e.display_coordinates);
13031
13141
  }
13032
13142
  if (e.deleteVertex) {
13033
13143
  addMenuItem('Delete vertex', e.deleteVertex);
@@ -13039,9 +13149,8 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13039
13149
  addMenuItem('Copy as GeoJSON', copyGeoJSON);
13040
13150
  }
13041
13151
 
13042
- function addCopyCoords() {
13043
- var bbox = internal.getLayerBounds(lyr, lyr.gui.source.dataset.arcs).toArray();
13044
- var coordStr = internal.getRoundedCoordString(e.coordinates, internal.getBoundsPrecisionForDisplay(bbox));
13152
+ function addCoords(p) {
13153
+ var coordStr = p[0] + ',' + p[1];
13045
13154
  var displayStr = '• &nbsp;' + coordStr.replace(/-/g, '–').replace(',', ', ');
13046
13155
  addMenuItem(displayStr, function() {
13047
13156
  saveFileContentToClipboard(coordStr);
package/www/mapshaper.js CHANGED
@@ -1612,6 +1612,7 @@
1612
1612
  this.ymin -= halfHeight * ky;
1613
1613
  this.xmax += halfWidth * kx;
1614
1614
  this.ymax += halfHeight * ky;
1615
+ return this;
1615
1616
  };
1616
1617
 
1617
1618
  // Return a bounding box with the same extent as this one.
@@ -5003,7 +5004,7 @@
5003
5004
  if (isLatLngCRS(P)) {
5004
5005
  return xy.concat();
5005
5006
  }
5006
- proj = getProjTransform(P, parseCrsString('wgs84'));
5007
+ proj = getProjTransform2(P, parseCrsString('wgs84'));
5007
5008
  return proj(xy[0], xy[1]);
5008
5009
  }
5009
5010
 
@@ -26664,7 +26665,7 @@ ${svg}
26664
26665
  codepage = lookupCodePage(ldid),
26665
26666
  samples = getNonAsciiSamples(),
26666
26667
  only7bit = samples.length === 0,
26667
- encoding, msg;
26668
+ encoding;
26668
26669
 
26669
26670
  // First, check the ldid (language driver id) (an obsolete way to specify which
26670
26671
  // codepage to use for text encoding.)
@@ -26684,10 +26685,12 @@ ${svg}
26684
26685
  // As a last resort, try to guess the encoding:
26685
26686
  if (!encoding) {
26686
26687
  var info = detectEncoding(samples);
26688
+ var msg;
26687
26689
  encoding = info.encoding;
26688
26690
  if (info.confidence < 2) {
26689
- msg = 'Warning: Unable to auto-detect the DBF file text encoding with high confidence.';
26690
- msg += '\n\nDefaulting to: ' + encoding + (encoding in encodingNames ? ' (' + encodingNames[encoding] + ')' : '');
26691
+ msg = 'Warning: Unable to auto-detect the DBF file text encoding' +
26692
+ (info.confidence == 1 ? ' with high confidence' : '') + '.';
26693
+ msg += ' Defaulting to ' + encoding + (encoding in encodingNames ? ' (' + encodingNames[encoding] + ').' : '.');
26691
26694
  msg += '\n\nSample of how non-ascii text was imported:\n';
26692
26695
  if (runningInBrowser()) {
26693
26696
  msg += '<pre>' + formatStringsAsGrid(decodeSamples(encoding, samples), 50) + '</pre>';
@@ -45532,7 +45535,7 @@ ${svg}
45532
45535
  });
45533
45536
  }
45534
45537
 
45535
- var version = "0.6.79";
45538
+ var version = "0.6.80";
45536
45539
 
45537
45540
  // Parse command line args into commands and run them
45538
45541
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.
package/www/page.css CHANGED
@@ -348,12 +348,10 @@ div.alert-box {
348
348
  border-radius: 9px;
349
349
  font-size: 14px;
350
350
  line-height: 1.5;
351
- /* color: #555;*/
352
351
  padding: 9px 11px 6px 11px;
353
352
  margin: 9px -1px 3px -1px;
354
353
  min-height: 120px;
355
354
  background: #f8fdff;
356
- ;
357
355
  }
358
356
 
359
357
  .catalog-mode .file-catalog {