mapshaper 0.6.86 → 0.6.88

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
@@ -4236,12 +4236,16 @@
4236
4236
  function pathIsRectangle(ids, arcs) {
4237
4237
  var bbox = arcs.getSimpleShapeBounds(ids).toArray();
4238
4238
  var iter = arcs.getShapeIter(ids);
4239
+ var count = 0;
4239
4240
  while (iter.hasNext()) {
4240
4241
  if (iter.x != bbox[0] && iter.x != bbox[2] ||
4241
4242
  iter.y != bbox[1] && iter.y != bbox[3]) {
4242
4243
  return false;
4243
4244
  }
4245
+ count++;
4244
4246
  }
4247
+ if (count < 5) return false;
4248
+ if (bbox[2] > bbox[0] === false || bbox[3] > bbox[1] === false) return false;
4245
4249
  return true;
4246
4250
  }
4247
4251
 
@@ -5000,11 +5004,12 @@
5000
5004
  }
5001
5005
 
5002
5006
  function toLngLat(xy, P) {
5003
- var proj;
5004
- if (isLatLngCRS(P)) {
5005
- return xy.concat();
5006
- }
5007
- proj = getProjTransform2(P, parseCrsString('wgs84'));
5007
+ return projectPoint(xy, P, parseCrsString('wgs84'));
5008
+ }
5009
+
5010
+ function projectPoint(xy, crsFrom, crsTo) {
5011
+ if (crsAreEqual(crsFrom, crsTo)) return xy.concat();
5012
+ var proj = getProjTransform2(crsFrom, crsTo);
5008
5013
  return proj(xy[0], xy[1]);
5009
5014
  }
5010
5015
 
@@ -5238,6 +5243,7 @@
5238
5243
  getProjTransform: getProjTransform,
5239
5244
  getProjTransform2: getProjTransform2,
5240
5245
  toLngLat: toLngLat,
5246
+ projectPoint: projectPoint,
5241
5247
  getProjInfo: getProjInfo,
5242
5248
  crsToProj4: crsToProj4,
5243
5249
  crsToPrj: crsToPrj,
@@ -5578,6 +5584,7 @@
5578
5584
  var arcOffs = _ii[i];
5579
5585
  var j = i * 4;
5580
5586
  var b = calcArcBounds(_xx, _yy, arcOffs, arcLen);
5587
+ // NOTE: if arcLen is 0, bounds coords are undefined, coerced to NaN in _bb.
5581
5588
  _bb[j++] = b[0];
5582
5589
  _bb[j++] = b[1];
5583
5590
  _bb[j++] = b[2];
@@ -5990,12 +5997,14 @@
5990
5997
  this.arcIntersectsBBox = function(i, b1) {
5991
5998
  var b2 = _bb,
5992
5999
  j = i * 4;
6000
+ // returns false if _bb bounds are NaN
5993
6001
  return b2[j] <= b1[2] && b2[j+2] >= b1[0] && b2[j+3] >= b1[1] && b2[j+1] <= b1[3];
5994
6002
  };
5995
6003
 
5996
6004
  this.arcIsContained = function(i, b1) {
5997
6005
  var b2 = _bb,
5998
6006
  j = i * 4;
6007
+ // returns false if _bb bounds are NaN
5999
6008
  return b2[j] >= b1[0] && b2[j+2] <= b1[2] && b2[j+1] >= b1[1] && b2[j+3] <= b1[3];
6000
6009
  };
6001
6010
 
@@ -6032,22 +6041,21 @@
6032
6041
  return bounds;
6033
6042
  };
6034
6043
 
6035
- this.getSimpleShapeBounds2 = function(arcIds, arr) {
6044
+ this.getSimpleShapeBbox = function(arcIds, arr) {
6036
6045
  var bbox = arr || [],
6037
6046
  bb = _bb,
6038
- id = absArcId(arcIds[0]) * 4;
6039
- bbox[0] = bb[id];
6040
- bbox[1] = bb[++id];
6041
- bbox[2] = bb[++id];
6042
- bbox[3] = bb[++id];
6043
- for (var i=1, n=arcIds.length; i<n; i++) {
6044
- id = absArcId(arcIds[i]) * 4;
6045
- if (bb[id] < bbox[0]) bbox[0] = bb[id];
6046
- if (bb[++id] < bbox[1]) bbox[1] = bb[id];
6047
- if (bb[++id] > bbox[2]) bbox[2] = bb[id];
6048
- if (bb[++id] > bbox[3]) bbox[3] = bb[id];
6047
+ arcId, offs;
6048
+ bbox[0] = bbox[1] = Infinity;
6049
+ bbox[2] = bbox[3] = -Infinity;
6050
+ for (var i=0, n=arcIds.length; i<n; i++) {
6051
+ arcId = absArcId(arcIds[i]);
6052
+ offs = arcId * 4;
6053
+ if (bb[offs] < bbox[0]) bbox[0] = bb[offs];
6054
+ if (bb[++offs] < bbox[1]) bbox[1] = bb[offs];
6055
+ if (bb[++offs] > bbox[2]) bbox[2] = bb[offs];
6056
+ if (bb[++offs] > bbox[3]) bbox[3] = bb[offs];
6049
6057
  }
6050
- return bbox;
6058
+ return bbox[0] == Infinity ? [] : bbox;
6051
6059
  };
6052
6060
 
6053
6061
  // TODO: move this and similar methods out of ArcCollection
@@ -6064,7 +6072,9 @@
6064
6072
  this.mergeArcBounds = function(arcId, bounds) {
6065
6073
  if (arcId < 0) arcId = ~arcId;
6066
6074
  var offs = arcId * 4;
6067
- bounds.mergeBounds(_bb[offs], _bb[offs+1], _bb[offs+2], _bb[offs+3]);
6075
+ if (_nn[arcId] > 0) {
6076
+ bounds.mergeBounds(_bb[offs], _bb[offs+1], _bb[offs+2], _bb[offs+3]);
6077
+ }
6068
6078
  };
6069
6079
  }
6070
6080
 
@@ -17250,7 +17260,7 @@
17250
17260
  }
17251
17261
 
17252
17262
  function procShapeRing(path) {
17253
- currRingBbox = arcs.getSimpleShapeBounds2(path);
17263
+ currRingBbox = arcs.getSimpleShapeBbox(path);
17254
17264
  ringIndex.setIds(path);
17255
17265
  procArcIds(path);
17256
17266
  ringIndex.clear();
@@ -38145,7 +38155,7 @@ ${svg}
38145
38155
 
38146
38156
  // Assumes that ring boundaries to not cross
38147
38157
  function ringHasHoles(ring, rings, arcs) {
38148
- var bbox = arcs.getSimpleShapeBounds2(ring);
38158
+ var bbox = arcs.getSimpleShapeBbox(ring);
38149
38159
  var sibling, p;
38150
38160
  for (var i=0, n=rings.length; i<n; i++) {
38151
38161
  sibling = rings[i];
@@ -45574,7 +45584,7 @@ ${svg}
45574
45584
  });
45575
45585
  }
45576
45586
 
45577
- var version = "0.6.86";
45587
+ var version = "0.6.88";
45578
45588
 
45579
45589
  // Parse command line args into commands and run them
45580
45590
  // 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.86",
3
+ "version": "0.6.88",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -5811,11 +5811,14 @@
5811
5811
  var altDown = false;
5812
5812
  var spaceDown = false;
5813
5813
 
5814
- function updateControlKeys(e) {
5814
+ function updateControlKeys(e, evtName) {
5815
5815
  shiftDown = e.shiftKey;
5816
5816
  ctrlDown = e.ctrlKey;
5817
5817
  metaDown = e.metaKey;
5818
5818
  altDown = e.altKey;
5819
+ if (e.keyCode == 32) {
5820
+ spaceDown = evtName == 'keydown';
5821
+ }
5819
5822
  }
5820
5823
 
5821
5824
  function mouseIsPressed() {
@@ -5823,17 +5826,14 @@
5823
5826
  }
5824
5827
 
5825
5828
  document.addEventListener('keyup', function(e) {
5826
- if (!GUI.isActiveInstance(gui) || e.repeat) return;
5827
- // this can fail to fire if keyup occurs over a context menu
5828
- if (e.keyCode == 32) spaceDown = false;
5829
- updateControlKeys(e);
5829
+ if (!GUI.isActiveInstance(gui) || e.repeat && e.keyCode == 32) return;
5830
+ updateControlKeys(e, 'keyup');
5830
5831
  self.dispatchEvent('keyup', getEventData(e));
5831
5832
  });
5832
5833
 
5833
5834
  document.addEventListener('keydown', function(e) {
5834
- if (!GUI.isActiveInstance(gui) || e.repeat) return;
5835
- if (e.keyCode == 32) spaceDown = true;
5836
- updateControlKeys(e);
5835
+ if (!GUI.isActiveInstance(gui) || e.repeat && e.keyCode == 32) return;
5836
+ updateControlKeys(e, 'keydown');
5837
5837
  self.dispatchEvent('keydown', getEventData(e));
5838
5838
  });
5839
5839
 
@@ -5886,7 +5886,7 @@
5886
5886
  standard: ['info', 'selection', 'box'],
5887
5887
  empty: ['edit_points', 'edit_lines', 'edit_polygons', 'box'],
5888
5888
  polygons: ['info', 'selection', 'box', 'edit_polygons'],
5889
- rectangles: ['info', 'selection', 'box', 'rectangles'],
5889
+ rectangles: ['info', 'selection', 'box', 'rectangles', 'edit_polygons'],
5890
5890
  lines: ['info', 'selection', 'box' , 'edit_lines'],
5891
5891
  table: ['info', 'selection'],
5892
5892
  labels: ['info', 'selection', 'box', 'labels', 'edit_points'],
@@ -7904,7 +7904,7 @@
7904
7904
  return;
7905
7905
  }
7906
7906
  for (var i = 0, n = shp && shp.length; i < n; i++) {
7907
- arcs.getSimpleShapeBounds2(shp[i], bbox);
7907
+ arcs.getSimpleShapeBbox(shp[i], bbox);
7908
7908
  if (x + dist < bbox[0] || x - dist > bbox[2] ||
7909
7909
  y + dist < bbox[1] || y - dist > bbox[3]) {
7910
7910
  continue; // bbox non-intersection
@@ -8497,8 +8497,8 @@
8497
8497
  };
8498
8498
  if (evt) {
8499
8499
  // data coordinates
8500
- eventData.coordinates = translateDisplayPoint(targetLayer, ext.translatePixelCoords(evt.x, evt.y));
8501
- eventData.display_coordinates = gui.map.pixelCoordsToDisplayCoords(evt.x, evt.y);
8500
+ eventData.projected_coordinates = gui.map.pixelCoordsToProjectedCoords(evt.x, evt.y);
8501
+ eventData.lonlat_coordinates = gui.map.pixelCoordsToLngLatCoords(evt.x, evt.y);
8502
8502
  eventData.originalEvent = evt;
8503
8503
  eventData.overMap = isOverMap(evt);
8504
8504
  }
@@ -10316,7 +10316,7 @@
10316
10316
 
10317
10317
  function initLineEditing(gui, ext, hit) {
10318
10318
  var hoverVertexInfo;
10319
- var prevClickEvent;
10319
+ var prevVertexAddedEvent;
10320
10320
  var prevHoverEvent;
10321
10321
  var initialArcCount = -1;
10322
10322
  var initialShapeCount = -1;
@@ -10387,6 +10387,7 @@
10387
10387
 
10388
10388
  gui.on('redo_path_extend', function(e) {
10389
10389
  var target = hit.getHitTarget();
10390
+
10390
10391
  if (pathDrawing() && prevHoverEvent) {
10391
10392
  updatePathEndpoint(e.p);
10392
10393
  appendVertex$1(target, pixToDataCoords(prevHoverEvent.x, prevHoverEvent.y));
@@ -10486,7 +10487,7 @@
10486
10487
  hit.clearDrawingId();
10487
10488
  drawingId = -1;
10488
10489
  hoverVertexInfo = null;
10489
- prevClickEvent = prevHoverEvent = null;
10490
+ prevVertexAddedEvent = prevHoverEvent = null;
10490
10491
  updateCursor();
10491
10492
  }
10492
10493
 
@@ -10543,6 +10544,7 @@
10543
10544
  hoverVertexInfo = findPathStartInfo(e);
10544
10545
  var xy = [e.x, e.y], xy2;
10545
10546
  var p = pixToDataCoords(e.x, e.y);
10547
+ var addedToPath = true;
10546
10548
  if (!pathDrawing()) {
10547
10549
  pencilPoints = [xy];
10548
10550
  startNewPath(p);
@@ -10556,7 +10558,7 @@
10556
10558
  appendVertex$1(hit.getHitTarget(), p);
10557
10559
  extendCurrentPath(p);
10558
10560
  pencilPoints = null; // stop drawing
10559
- } else if (pencilPoints.length >= 2 && pointExceedsTolerance(xy, pencilPoints, 1.4)) {
10561
+ } else if (pencilPoints.length >= 2 && pointExceedsTolerance(xy, pencilPoints, 1.2)) {
10560
10562
  xy2 = pencilPoints.pop();
10561
10563
  p = pixToDataCoords(xy2[0], xy2[1]);
10562
10564
  extendCurrentPath(p);
@@ -10568,6 +10570,11 @@
10568
10570
  // skip this point, update the hover line
10569
10571
  pencilPoints.push(xy);
10570
10572
  updatePathEndpoint(p);
10573
+ addedToPath = false;
10574
+ }
10575
+ if (addedToPath) {
10576
+ //
10577
+ prevVertexAddedEvent = e;
10571
10578
  }
10572
10579
  }, null, 3); // higher priority than hit control
10573
10580
 
@@ -10624,7 +10631,7 @@
10624
10631
  return;
10625
10632
  }
10626
10633
  if (gui.keyboard.shiftIsPressed()) {
10627
- alignPointerPosition(e, prevClickEvent);
10634
+ alignPointerPosition(e, prevVertexAddedEvent);
10628
10635
  }
10629
10636
  updatePathEndpoint(pixToDataCoords(e.x, e.y));
10630
10637
  }
@@ -10651,15 +10658,13 @@
10651
10658
  var p = pixToDataCoords(e.x, e.y);
10652
10659
  if (pathDrawing()) {
10653
10660
  extendCurrentPath(hoverVertexInfo?.point || p);
10654
- } else if (gui.keyboard.shiftIsPressed()) {
10655
- deleteActiveVertex(e);
10656
10661
  } else if (hoverVertexInfo?.type == 'interpolated') {
10657
10662
  // don't start new path if hovering along a segment -- this is
10658
10663
  // likely to be an attempt to add a new vertex, not start a new path
10659
10664
  } else {
10660
10665
  startNewPath(p);
10661
10666
  }
10662
- prevClickEvent = e;
10667
+ prevVertexAddedEvent = e;
10663
10668
  });
10664
10669
 
10665
10670
  // esc or enter key finishes a path
@@ -10673,10 +10678,10 @@
10673
10678
 
10674
10679
  // detect second 'click' event of a double-click action
10675
10680
  function detectDoubleClick(evt) {
10676
- if (!prevClickEvent) return false;
10677
- var elapsed = evt.time - prevClickEvent.time;
10678
- var dx = Math.abs(evt.x - prevClickEvent.x);
10679
- var dy = Math.abs(evt.y - prevClickEvent.y);
10681
+ if (!prevVertexAddedEvent) return false;
10682
+ var elapsed = evt.time - prevVertexAddedEvent.time;
10683
+ var dx = Math.abs(evt.x - prevVertexAddedEvent.x);
10684
+ var dy = Math.abs(evt.y - prevVertexAddedEvent.y);
10680
10685
  var dbl = elapsed < 500 && dx <= 2 && dy <= 2;
10681
10686
  return dbl;
10682
10687
  }
@@ -10754,7 +10759,8 @@
10754
10759
  if (!pathDrawing()) return;
10755
10760
  var target = hit.getHitTarget();
10756
10761
  if (getLastArcLength(target) <= 2) { // includes hover point
10757
- deleteLastPath(target);
10762
+ // deleteLastPath(target);
10763
+ gui.undo.undo(); // assume previous undo event was path_add
10758
10764
  } else {
10759
10765
  deleteLastVertex(target);
10760
10766
  }
@@ -12394,21 +12400,23 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
12394
12400
  target.layer.pinned = !!pinned;
12395
12401
  };
12396
12402
 
12397
- this.translatePixelCoords = function(x, y) {
12398
- var p = _ext.translatePixelCoords(x, y);
12399
- if (!_dynamicCRS) return p;
12400
- return internal.toLngLat(p, _dynamicCRS);
12403
+ this.pixelCoordsToLngLatCoords = function(x, y) {
12404
+ var crsFrom = this.getDisplayCRS();
12405
+ var p1 = internal.toLngLat(_ext.translatePixelCoords(x, y), crsFrom);
12406
+ var p2 = internal.toLngLat(_ext.translatePixelCoords(x+1, y+1), crsFrom);
12407
+ return p1 && p2 && p1[1] <= 90 && p1[1] >= -90 ?
12408
+ formatCoordsForDisplay(p1, p2) : null;
12401
12409
  };
12402
12410
 
12403
- this.pixelCoordsToDisplayCoords = function(x, y) {
12404
- var p1 = _ext.translatePixelCoords(x, y);
12405
- var p2 = _ext.translatePixelCoords(x+1, y+1);
12406
- var crs = this.getDisplayCRS();
12407
- if (crs) {
12408
- p1 = internal.toLngLat(p1, crs) || p1;
12409
- p2 = internal.toLngLat(p2, crs) || p2;
12411
+ this.pixelCoordsToProjectedCoords = function(x, y) {
12412
+ if (!_activeLyr) return null;
12413
+ var info = getDatasetCrsInfo(_activeLyr.gui.source.dataset);
12414
+ if (info && internal.isLatLngCRS(info.crs)) {
12415
+ return null; // latlon dataset
12410
12416
  }
12411
- return formatCoordsForDisplay(p1, p2);
12417
+ var p1 = translateDisplayPoint(_activeLyr, _ext.translatePixelCoords(x, y));
12418
+ var p2 = translateDisplayPoint(_activeLyr, _ext.translatePixelCoords(x+1, y+1));
12419
+ return p1 && p2 ? formatCoordsForDisplay(p1, p2) : null;
12412
12420
  };
12413
12421
 
12414
12422
  // this.getCenterLngLat = function() {
@@ -12893,27 +12901,19 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
12893
12901
  .show();
12894
12902
  }
12895
12903
 
12904
+ function addMenuLabel(label) {
12905
+ El('div')
12906
+ .appendTo(menu)
12907
+ .addClass('contextmenu-label')
12908
+ .html(label);
12909
+ }
12910
+
12896
12911
  this.open = function(e, lyr) {
12897
12912
  if (lyr && !lyr.gui.geographic) return; // no popup for tabular data
12898
- _open = true;
12899
- _openCount++;
12900
- var rspace = body.clientWidth - e.pageX;
12901
- var xoffs = 10;
12902
- menu.empty().show();
12903
- if (rspace > 150) {
12904
- menu.css('left', e.pageX + xoffs + 'px');
12905
- menu.css('right', null);
12906
- } else {
12907
- menu.css('right', (body.clientWidth - e.pageX + xoffs) + 'px');
12908
- menu.css('left', null);
12909
- }
12910
- menu.css('top', (e.pageY - 15) + 'px');
12913
+ menu.empty();
12911
12914
 
12912
12915
  // menu contents
12913
12916
  //
12914
- if (e.display_coordinates) {
12915
- addCoords(e.display_coordinates);
12916
- }
12917
12917
  if (e.deleteVertex) {
12918
12918
  addMenuItem('Delete vertex', e.deleteVertex);
12919
12919
  }
@@ -12926,14 +12926,42 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
12926
12926
  if (e.deleteFeature) {
12927
12927
  addMenuItem(getDeleteLabel(), e.deleteFeature);
12928
12928
  }
12929
+ if (e.lonlat_coordinates) {
12930
+ addCoords(e.lonlat_coordinates, 'longitude, latitude');
12931
+ }
12932
+ if (e.projected_coordinates) {
12933
+ addCoords(e.projected_coordinates, 'easting, northing');
12934
+ }
12935
+
12936
+ if (menu.node().childNodes.length === 0) {
12937
+ return;
12938
+ }
12939
+
12940
+ _open = true;
12941
+ _openCount++;
12942
+ var rspace = body.clientWidth - e.pageX;
12943
+ var xoffs = 10;
12944
+ if (rspace > 150) {
12945
+ menu.css('left', e.pageX + xoffs + 'px');
12946
+ menu.css('right', null);
12947
+ } else {
12948
+ menu.css('right', (body.clientWidth - e.pageX + xoffs) + 'px');
12949
+ menu.css('left', null);
12950
+ }
12951
+ menu.css('top', (e.pageY - 15) + 'px');
12952
+ menu.show();
12929
12953
 
12930
12954
  function getDeleteLabel() {
12931
12955
  return 'Delete ' + (lyr.geometry_type == 'point' ? 'point' : 'shape');
12932
12956
  }
12933
12957
 
12934
- function addCoords(p) {
12958
+ function addCoords(p, label) {
12935
12959
  var coordStr = p[0] + ',' + p[1];
12936
- var displayStr = '• &nbsp;' + coordStr.replace(/-/g, '–').replace(',', ', ');
12960
+ // var displayStr = '• &nbsp;' + coordStr.replace(/-/g, '–').replace(',', ', ');
12961
+ var displayStr = coordStr.replace(/-/g, '–').replace(',', ', ');
12962
+ if (label) {
12963
+ addMenuLabel(label);
12964
+ }
12937
12965
  addMenuItem(displayStr, function() {
12938
12966
  saveFileContentToClipboard(coordStr);
12939
12967
  });
package/www/mapshaper.js CHANGED
@@ -4236,12 +4236,16 @@
4236
4236
  function pathIsRectangle(ids, arcs) {
4237
4237
  var bbox = arcs.getSimpleShapeBounds(ids).toArray();
4238
4238
  var iter = arcs.getShapeIter(ids);
4239
+ var count = 0;
4239
4240
  while (iter.hasNext()) {
4240
4241
  if (iter.x != bbox[0] && iter.x != bbox[2] ||
4241
4242
  iter.y != bbox[1] && iter.y != bbox[3]) {
4242
4243
  return false;
4243
4244
  }
4245
+ count++;
4244
4246
  }
4247
+ if (count < 5) return false;
4248
+ if (bbox[2] > bbox[0] === false || bbox[3] > bbox[1] === false) return false;
4245
4249
  return true;
4246
4250
  }
4247
4251
 
@@ -5000,11 +5004,12 @@
5000
5004
  }
5001
5005
 
5002
5006
  function toLngLat(xy, P) {
5003
- var proj;
5004
- if (isLatLngCRS(P)) {
5005
- return xy.concat();
5006
- }
5007
- proj = getProjTransform2(P, parseCrsString('wgs84'));
5007
+ return projectPoint(xy, P, parseCrsString('wgs84'));
5008
+ }
5009
+
5010
+ function projectPoint(xy, crsFrom, crsTo) {
5011
+ if (crsAreEqual(crsFrom, crsTo)) return xy.concat();
5012
+ var proj = getProjTransform2(crsFrom, crsTo);
5008
5013
  return proj(xy[0], xy[1]);
5009
5014
  }
5010
5015
 
@@ -5238,6 +5243,7 @@
5238
5243
  getProjTransform: getProjTransform,
5239
5244
  getProjTransform2: getProjTransform2,
5240
5245
  toLngLat: toLngLat,
5246
+ projectPoint: projectPoint,
5241
5247
  getProjInfo: getProjInfo,
5242
5248
  crsToProj4: crsToProj4,
5243
5249
  crsToPrj: crsToPrj,
@@ -5578,6 +5584,7 @@
5578
5584
  var arcOffs = _ii[i];
5579
5585
  var j = i * 4;
5580
5586
  var b = calcArcBounds(_xx, _yy, arcOffs, arcLen);
5587
+ // NOTE: if arcLen is 0, bounds coords are undefined, coerced to NaN in _bb.
5581
5588
  _bb[j++] = b[0];
5582
5589
  _bb[j++] = b[1];
5583
5590
  _bb[j++] = b[2];
@@ -5990,12 +5997,14 @@
5990
5997
  this.arcIntersectsBBox = function(i, b1) {
5991
5998
  var b2 = _bb,
5992
5999
  j = i * 4;
6000
+ // returns false if _bb bounds are NaN
5993
6001
  return b2[j] <= b1[2] && b2[j+2] >= b1[0] && b2[j+3] >= b1[1] && b2[j+1] <= b1[3];
5994
6002
  };
5995
6003
 
5996
6004
  this.arcIsContained = function(i, b1) {
5997
6005
  var b2 = _bb,
5998
6006
  j = i * 4;
6007
+ // returns false if _bb bounds are NaN
5999
6008
  return b2[j] >= b1[0] && b2[j+2] <= b1[2] && b2[j+1] >= b1[1] && b2[j+3] <= b1[3];
6000
6009
  };
6001
6010
 
@@ -6032,22 +6041,21 @@
6032
6041
  return bounds;
6033
6042
  };
6034
6043
 
6035
- this.getSimpleShapeBounds2 = function(arcIds, arr) {
6044
+ this.getSimpleShapeBbox = function(arcIds, arr) {
6036
6045
  var bbox = arr || [],
6037
6046
  bb = _bb,
6038
- id = absArcId(arcIds[0]) * 4;
6039
- bbox[0] = bb[id];
6040
- bbox[1] = bb[++id];
6041
- bbox[2] = bb[++id];
6042
- bbox[3] = bb[++id];
6043
- for (var i=1, n=arcIds.length; i<n; i++) {
6044
- id = absArcId(arcIds[i]) * 4;
6045
- if (bb[id] < bbox[0]) bbox[0] = bb[id];
6046
- if (bb[++id] < bbox[1]) bbox[1] = bb[id];
6047
- if (bb[++id] > bbox[2]) bbox[2] = bb[id];
6048
- if (bb[++id] > bbox[3]) bbox[3] = bb[id];
6047
+ arcId, offs;
6048
+ bbox[0] = bbox[1] = Infinity;
6049
+ bbox[2] = bbox[3] = -Infinity;
6050
+ for (var i=0, n=arcIds.length; i<n; i++) {
6051
+ arcId = absArcId(arcIds[i]);
6052
+ offs = arcId * 4;
6053
+ if (bb[offs] < bbox[0]) bbox[0] = bb[offs];
6054
+ if (bb[++offs] < bbox[1]) bbox[1] = bb[offs];
6055
+ if (bb[++offs] > bbox[2]) bbox[2] = bb[offs];
6056
+ if (bb[++offs] > bbox[3]) bbox[3] = bb[offs];
6049
6057
  }
6050
- return bbox;
6058
+ return bbox[0] == Infinity ? [] : bbox;
6051
6059
  };
6052
6060
 
6053
6061
  // TODO: move this and similar methods out of ArcCollection
@@ -6064,7 +6072,9 @@
6064
6072
  this.mergeArcBounds = function(arcId, bounds) {
6065
6073
  if (arcId < 0) arcId = ~arcId;
6066
6074
  var offs = arcId * 4;
6067
- bounds.mergeBounds(_bb[offs], _bb[offs+1], _bb[offs+2], _bb[offs+3]);
6075
+ if (_nn[arcId] > 0) {
6076
+ bounds.mergeBounds(_bb[offs], _bb[offs+1], _bb[offs+2], _bb[offs+3]);
6077
+ }
6068
6078
  };
6069
6079
  }
6070
6080
 
@@ -17250,7 +17260,7 @@
17250
17260
  }
17251
17261
 
17252
17262
  function procShapeRing(path) {
17253
- currRingBbox = arcs.getSimpleShapeBounds2(path);
17263
+ currRingBbox = arcs.getSimpleShapeBbox(path);
17254
17264
  ringIndex.setIds(path);
17255
17265
  procArcIds(path);
17256
17266
  ringIndex.clear();
@@ -38145,7 +38155,7 @@ ${svg}
38145
38155
 
38146
38156
  // Assumes that ring boundaries to not cross
38147
38157
  function ringHasHoles(ring, rings, arcs) {
38148
- var bbox = arcs.getSimpleShapeBounds2(ring);
38158
+ var bbox = arcs.getSimpleShapeBbox(ring);
38149
38159
  var sibling, p;
38150
38160
  for (var i=0, n=rings.length; i<n; i++) {
38151
38161
  sibling = rings[i];
@@ -45574,7 +45584,7 @@ ${svg}
45574
45584
  });
45575
45585
  }
45576
45586
 
45577
- var version = "0.6.86";
45587
+ var version = "0.6.88";
45578
45588
 
45579
45589
  // Parse command line args into commands and run them
45580
45590
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.
package/www/page.css CHANGED
@@ -1206,8 +1206,9 @@ div.basemap-style-btn.active {
1206
1206
  }
1207
1207
 
1208
1208
  .basemap-overlay-btn img {
1209
- margin-left: -21px;
1210
- width: 70px;
1209
+ margin-left: -31px;
1210
+ margin-top: -5px;
1211
+ width: 90px;
1211
1212
  }
1212
1213
 
1213
1214
  .mapbox-improve-map {
@@ -1379,11 +1380,20 @@ body.pan.panning .map-layers:not(.drawing) {
1379
1380
  .contextmenu-item {
1380
1381
  background-color: #fff;
1381
1382
  white-space: nowrap;
1382
- padding: 6px 10px 7px 10px;
1383
+ padding: 5px 10px 6px 10px;
1383
1384
  line-height: 11px;
1384
1385
  cursor: pointer;
1385
1386
  }
1386
1387
 
1388
+ .contextmenu-label {
1389
+ color: #999;
1390
+ font-size: 82%;
1391
+ white-space: nowrap;
1392
+ padding: 6px 10px 1px 10px;
1393
+ line-height: 9px;
1394
+ margin-top: -2px;
1395
+ }
1396
+
1387
1397
  .nav-menu-item:hover,
1388
1398
  .contextmenu-item:hover,
1389
1399
  .nav-btn:hover .nav-sub-menu:not(.active):not(:hover) .nav-menu-item[data-name=info] {