mapshaper 0.6.73 → 0.6.75

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/www/mapshaper.js CHANGED
@@ -749,7 +749,7 @@
749
749
  }
750
750
 
751
751
  function getGenericComparator(asc) {
752
- asc = asc !== false;
752
+ asc = asc !== false && asc != 'descending'; // ascending is the default
753
753
  return function(a, b) {
754
754
  var retn = 0;
755
755
  if (b == null) {
@@ -1362,13 +1362,13 @@
1362
1362
  }
1363
1363
 
1364
1364
  // Format an array of (preferably short) strings in columns for console logging.
1365
- function formatStringsAsGrid(arr) {
1365
+ function formatStringsAsGrid(arr, width) {
1366
1366
  // TODO: variable column width
1367
1367
  var longest = arr.reduce(function(len, str) {
1368
1368
  return Math.max(len, str.length);
1369
1369
  }, 0),
1370
1370
  colWidth = longest + 2,
1371
- perLine = Math.floor(80 / colWidth) || 1;
1371
+ perLine = Math.floor((width || 80) / colWidth) || 1;
1372
1372
  return arr.reduce(function(memo, name, i) {
1373
1373
  var col = i % perLine;
1374
1374
  if (i > 0 && col === 0) memo += '\n';
@@ -3720,8 +3720,6 @@
3720
3720
  }
3721
3721
  var require$1 = f;
3722
3722
 
3723
- // import { createRequire } from "module";
3724
-
3725
3723
  var iconv = require$1('iconv-lite');
3726
3724
 
3727
3725
  // import iconv from 'iconv-lite';
@@ -4289,6 +4287,10 @@
4289
4287
  return layerHasPaths(lyr) || layerHasPoints(lyr);
4290
4288
  }
4291
4289
 
4290
+ function layerIsGeometric(lyr) {
4291
+ return !!lyr.geometry_type; // only checks type, includes empty layers
4292
+ }
4293
+
4292
4294
  function layerHasPaths(lyr) {
4293
4295
  return (lyr.geometry_type == 'polygon' || lyr.geometry_type == 'polyline') &&
4294
4296
  layerHasNonNullShapes(lyr);
@@ -4552,6 +4554,7 @@
4552
4554
  getLayerDataTable: getLayerDataTable,
4553
4555
  layerHasNonNullData: layerHasNonNullData,
4554
4556
  layerHasGeometry: layerHasGeometry,
4557
+ layerIsGeometric: layerIsGeometric,
4555
4558
  layerHasPaths: layerHasPaths,
4556
4559
  layerHasPoints: layerHasPoints,
4557
4560
  layerIsRectangle: layerIsRectangle,
@@ -5493,6 +5496,8 @@
5493
5496
  initLegacyArcs(arguments[0]); // want to phase this out
5494
5497
  } else if (arguments.length == 3) {
5495
5498
  initXYData.apply(this, arguments);
5499
+ } else if (arguments.length === 0) {
5500
+ initLegacyArcs([]); // empty collection
5496
5501
  } else {
5497
5502
  error("ArcCollection() Invalid arguments");
5498
5503
  }
@@ -5553,43 +5558,35 @@
5553
5558
  }
5554
5559
 
5555
5560
  function initBounds() {
5556
- var data = calcArcBounds2(_xx, _yy, _nn);
5557
- _bb = data.bb;
5558
- _allBounds = data.bounds;
5559
- }
5560
-
5561
- function calcArcBounds2(xx, yy, nn) {
5562
- var numArcs = nn.length,
5563
- bb = new Float64Array(numArcs * 4),
5564
- bounds = new Bounds(),
5565
- arcOffs = 0,
5566
- arcLen,
5567
- j, b;
5561
+ var numArcs = _nn.length;
5562
+ _bb = new Float64Array(numArcs * 4);
5563
+ _allBounds = new Bounds();
5568
5564
  for (var i=0; i<numArcs; i++) {
5569
- arcLen = nn[i];
5570
- if (arcLen > 0) {
5571
- j = i * 4;
5572
- b = calcArcBounds(xx, yy, arcOffs, arcLen);
5573
- bb[j++] = b[0];
5574
- bb[j++] = b[1];
5575
- bb[j++] = b[2];
5576
- bb[j] = b[3];
5577
- arcOffs += arcLen;
5578
- bounds.mergeBounds(b);
5579
- }
5565
+ initArcBounds(i);
5580
5566
  }
5581
- return {
5582
- bb: bb,
5583
- bounds: bounds
5584
- };
5585
5567
  }
5586
5568
 
5569
+ function initArcBounds(i) {
5570
+ var arcLen = _nn[i];
5571
+ var arcOffs = _ii[i];
5572
+ var j = i * 4;
5573
+ var b = calcArcBounds(_xx, _yy, arcOffs, arcLen);
5574
+ _bb[j++] = b[0];
5575
+ _bb[j++] = b[1];
5576
+ _bb[j++] = b[2];
5577
+ _bb[j] = b[3];
5578
+ _allBounds.mergeBounds(b);
5579
+ }
5580
+
5581
+ this.updateArcBounds = function(arcId) {
5582
+ initArcBounds(arcId);
5583
+ };
5584
+
5587
5585
  this.updateVertexData = function(nn, xx, yy, zz) {
5588
5586
  initXYData(nn, xx, yy);
5589
5587
  initZData(zz || null);
5590
5588
  };
5591
5589
 
5592
-
5593
5590
  this.getCopy = function() {
5594
5591
  var copy = new ArcCollection(new Int32Array(_nn), new Float64Array(_xx),
5595
5592
  new Float64Array(_yy));
@@ -13192,15 +13189,15 @@
13192
13189
  return findVertexIds(p2.x, p2.y, arcs);
13193
13190
  }
13194
13191
 
13195
-
13196
13192
  function snapVerticesToPoint(ids, p, arcs, final) {
13193
+ var data = arcs.getVertexData();
13197
13194
  ids.forEach(function(idx) {
13195
+ if (final) {
13196
+ // recalculate bounding box for arc
13197
+ arcs.updateArcBounds(findArcIdFromVertexId(idx, data.ii));
13198
+ }
13198
13199
  setVertexCoords(p[0], p[1], idx, arcs);
13199
13200
  });
13200
- if (final) {
13201
- // kludge to get dataset to recalculate internal bounding boxes
13202
- arcs.transformPoints(function() {});
13203
- }
13204
13201
  }
13205
13202
 
13206
13203
 
@@ -23053,28 +23050,30 @@ ${svg}
23053
23050
  // @samples Array of buffers containing sample text fields
23054
23051
  // TODO: Improve reliability and number of detectable encodings.
23055
23052
  function detectEncoding(samples) {
23056
- var encoding = null;
23057
- var utf8 = looksLikeUtf8(samples);
23058
- var win1252 = looksLikeWin1252(samples);
23059
- if (utf8 == 2 || utf8 > win1252) {
23060
- encoding = 'utf8';
23061
- } else if (win1252 > 0) {
23062
- encoding = 'win1252';
23063
- } else {
23064
- encoding = 'latin1'; // the original Shapefile encoding, using as an (imperfect) fallback
23065
- }
23066
-
23067
- return {
23068
- encoding: encoding,
23069
- confidence: Math.max(utf8, win1252)
23070
- };
23053
+ // score each encoding as 2 (high confidence) 1 (low confidence) or 0 (fail)
23054
+ var candidates = [{
23055
+ // latin1 is the original Shapefile encoding, using as an imperfect fallback
23056
+ // (sorts to the top only if all other encodings score 0)
23057
+ encoding: 'latin1',
23058
+ confidence: 0
23059
+ },{
23060
+ encoding: 'win1252',
23061
+ confidence: looksLikeWin1252(samples)
23062
+ }, {
23063
+ encoding: 'utf8',
23064
+ confidence: looksLikeUtf8(samples)
23065
+ }, {
23066
+ encoding: 'gb18030',
23067
+ confidence: looksLikeGB18030(samples)
23068
+ }];
23069
+ utils.sortOn(candidates, 'confidence', 'descending');
23070
+ return candidates[0];
23071
23071
  }
23072
23072
 
23073
- // Convert an array of text samples to a single string using a given encoding
23074
23073
  function decodeSamples(enc, samples) {
23075
23074
  return samples.map(function(buf) {
23076
23075
  return decodeString(buf, enc).trim();
23077
- }).join('\n');
23076
+ });
23078
23077
  }
23079
23078
 
23080
23079
  // Win1252 is the same as Latin1, except it replaces a block of control
@@ -23089,45 +23088,67 @@ ${svg}
23089
23088
  //
23090
23089
  function looksLikeWin1252(samples) {
23091
23090
  //common l.c. ascii chars
23092
- var ascii = 'abcdefghijklmnopqrstuvwxyz0123456789.()\'"?+-\n,:;/|_$% ',
23093
- // common extended + NBS (found in the wild)
23094
- extended = 'ßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿ°–±’‘' + '\xA0',
23095
- str = decodeSamples('win1252', samples),
23096
- asciiScore = getCharScore(str, ascii),
23097
- totalScore = getCharScore(str, extended + ascii);
23098
- return totalScore > 0.98 && asciiScore >= 0.8 && 2 ||
23099
- totalScore > 0.97 && asciiScore >= 0.6 && 1 || 0;
23091
+ var commonAscii = 'abcdefghijklmnopqrstuvwxyz0123456789.()\'"?+-\n,:;/|_$% ',
23092
+ // more common extended chars + NBS (found in the wild)
23093
+ moreChars = 'ßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿ°–±’‘' + '\xA0',
23094
+ str = decodeSamples('win1252', samples).join(''),
23095
+ commonAsciiPct = calcCharPct(str, commonAscii),
23096
+ expandedPct = calcCharPct(str, moreChars) + commonAsciiPct;
23097
+ var high = expandedPct > 0.98 && commonAsciiPct >= 0.8;
23098
+ var low = expandedPct > 0.97 && commonAsciiPct >= 0.6;
23099
+ return getScore(high, low);
23100
23100
  }
23101
23101
 
23102
- // Reject string if it contains the "replacement character" after decoding to UTF-8
23103
23102
  function looksLikeUtf8(samples) {
23104
- // Remove the byte sequence for the utf-8-encoded replacement char before decoding,
23105
- // in case the file is in utf-8, but contains some previously corrupted text.
23106
- // samples = samples.map(internal.replaceUtf8ReplacementChar);
23107
- var str = decodeSamples('utf8', samples);
23108
- var count = (str.match(/\ufffd/g) || []).length;
23109
- var score = 1 - count / str.length;
23110
- return score == 1 && 2 || score > 0.97 && 1 || 0;
23111
- }
23112
-
23113
- // function replaceUtf8ReplacementChar(buf) {
23114
- // var isCopy = false;
23115
- // for (var i=0, n=buf.length; i<n; i++) {
23116
- // // Check for UTF-8 encoded replacement char (0xEF 0xBF 0xBD)
23117
- // if (buf[i] == 0xef && i + 2 < n && buf[i+1] == 0xbf && buf[i+2] == 0xbd) {
23118
- // if (!isCopy) {
23119
- // buf = utils.createBuffer(buf);
23120
- // isCopy = true;
23121
- // }
23122
- // buf[i] = buf[i+1] = buf[i+2] = 63; // ascii question mark
23123
- // }
23124
- // }
23125
- // return buf;
23126
- // }
23103
+ // Reject string if it contains the "replacement character" after decoding
23104
+ // as utf-8
23105
+ var str = decodeSamples('utf8', samples).join('');
23106
+ var invalidPct = getInvalidPct(str);
23107
+ var high = invalidPct == 0;
23108
+ var low = invalidPct < 0.03;
23109
+ return getScore(high, low);
23110
+ }
23111
+
23112
+ function looksLikeGB18030(samples) {
23113
+ // from Jun Da's frequency table
23114
+ var commonHanZi = '的一了是不我他在人有这来个说上你们到地大着子那就也时道中出得为里下她要么去可以过和看之然后会自没小好生天而起对能还事想都心只家面样把国多又于头年手发如什开前当所无知老但见长已军从方声儿回意作话两点现很成身情十用些走经同进动己三行种向日明女正问此学太打间分因给本眼定二气力被门真法外听实其高先几笑再主将山战才口文最部第它西与全白者便相住公使东等边信像斯机光次感神却死理名重四做别叫王并水月果何位怎马常觉海张少处亲安特美呢色原直望命由候吧让应尔难关许车平师民夫书新接吗路利世比放活快总立队更花爱清五内金带工风克任至指往入空德吃表连解教思飞物电受今完林干代告兵加认通找远非性脸体轻记目令变似反南场跟必石拉士报李火且满该孩字红象即结言员房件万条提写或坐北早失离步陈乎请转近切黑深城办倒各父传音站官半男击合阿英决怕杀未形及算青黄落刚百论谁突交团度义罗始强紧敌八母钱极片化流管惊每题晚虽政兴答司妈夜越啊奇达谈武友数领朝保服曾拿则哪格尽根急语容喜求衣留双影刻制随冷九苦量备布照周故准客船江系姐争功怪星断句龙竟视界讲取古六静底精七河久绝阳识哈台确息期整伤忙娘终剑送计愿欢微您沉装敢云脚消若复收千木乐毛华集树弟皇响希诉号巴穿线汉攻呀警派刘酒雷停史阵错建足显丽另包势破亮首志观病热跑业治田冲运约暗待共院仍区害元哥围屋胡产室调类细议爷注易务众帝市摇乱密姑斗除式示睛楼造朋社持慢般皮京况块忽脑校甚查土怀福单联赶背统喝疑支血饭灵够章群威举兰游器察嘴痛铁掉宝历改推枪念参术帮党据品须居称旁退梦科岁低严引吉睡爸呼追局露维苏证村挥独节谢香亚波角案读图左掌假跳究楚余鬼钟座礼展玉肯既止守广考恩异料段尼画续米草胜存唐医程弹烟商顾招宗堂野初府激雨尚渐诗顿伯孙际沙雪板闻导致护春态基设耳简婚幸味右买演权卡继依恶庄炮亦虎州刀球需兄闪笔否烈玩啦逃排仅弄具散默景顶郑洋丝卫速侠差贵君习妇助恐救湖莫窗险顺封佛委旧印伙妹副宫洞永罪松责组防艺营班试鲁宋靠索灯介翻喊纪秘妻纸银略充戏担某杨射魔遇鱼陆级坏忘乡鲜哭费抓叶醒族纳床咱桌境列午振抱专毫店街怒托剧置秋藏赵划普岛较承脱革忍伸份免齐抗猛园临犯食架选歌按败良隐养属洛朱狂修坚压寻旅谋温探资端投泪阴换药麻施丈冰雄著绿职负短模荣遗农叹川毒吴蒋卖范禁杂富秀县祖梅谷凡刺登蓝奶缓姓牛价规篇劳质婆仙馆摆舞层狗占墙善熟验肉臣状呆圣懂袋唱值迷替归巨讨毕批镇吸森拍灭握伊杰勒卷偷奔省谓危付伦休厅预迎罢恨博亡欲悲宣标闹岸';
23115
+ var str = decodeSamples('gb18030', samples).join('');
23116
+ // Almost all the common Unicode Hanzi are in this range (along with many more uncommon ones)
23117
+ var chineseStr = str.replace(/[^\u4e00-\u9fa5]/g, '');
23118
+ var chinesePct = chineseStr.length / str.length;
23119
+ var commonAsciiStr = extractCommonAsciiChars(str);
23120
+ var commonAsciiPct = commonAsciiStr.length / str.length;
23121
+ // Some encodings get converted almost completely into valid (but mostly
23122
+ // uncommon) Chinese characters by the gb18030 converter.
23123
+ // To guard against this, we're requiring that a certain percentage of
23124
+ // characters be on a list of the most common characters.
23125
+ var commonHanZiPct = calcCharPct(chineseStr, commonHanZi);
23126
+ // check for non-convertible characters
23127
+ var invalidPct = getInvalidPct(str);
23128
+ var high = chinesePct > 0.5 && (chinesePct + commonAsciiPct) > 0.9 &&
23129
+ invalidPct === 0 && commonHanZiPct > 0.25;
23130
+ var low = chinesePct > 0.3 && (chinesePct + commonAsciiPct) > 0.8 &&
23131
+ commonHanZiPct > 0.15;
23132
+ return getScore(high, low);
23133
+ }
23134
+
23135
+ function getScore(high, low) {
23136
+ return high && 2 || low && 1 || 0;
23137
+ }
23138
+
23139
+ function getInvalidPct(str) {
23140
+ // count occurences of the "replacement" character
23141
+ var invalidCount = (str.match(/\ufffd/g) || []).length;
23142
+ return invalidCount / str.length;
23143
+ }
23144
+
23145
+ function extractCommonAsciiChars(str) {
23146
+ return str.replace(/[^a-zA-Z0-9.()'"?+\n,:;/|_$% -]/g, '');
23147
+ }
23127
23148
 
23128
23149
  // Calc percentage of chars in a string that are present in a second string
23129
23150
  // @chars String of chars to look for in @str
23130
- function getCharScore(str, chars) {
23151
+ function calcCharPct(str, chars) {
23131
23152
  var index = {},
23132
23153
  count = 0;
23133
23154
  str = str.toLowerCase();
@@ -23137,9 +23158,16 @@ ${svg}
23137
23158
  for (i=0, n=str.length; i<n; i++) {
23138
23159
  count += index[str[i]] || 0;
23139
23160
  }
23140
- return count / str.length;
23161
+ return count / str.length || 0;
23141
23162
  }
23142
23163
 
23164
+ var EncodingDetection = /*#__PURE__*/Object.freeze({
23165
+ __proto__: null,
23166
+ detectEncodingFromBOM: detectEncodingFromBOM,
23167
+ detectEncoding: detectEncoding,
23168
+ decodeSamples: decodeSamples
23169
+ });
23170
+
23143
23171
  // Convert a string containing delimited text data into a dataset object
23144
23172
  function importDelim(str, opts) {
23145
23173
  return importDelim2({content: str}, opts);
@@ -26651,25 +26679,19 @@ ${svg}
26651
26679
  var info = detectEncoding(samples);
26652
26680
  encoding = info.encoding;
26653
26681
  if (info.confidence < 2) {
26654
- msg = 'Warning: Unable to auto-detect the text encoding of a DBF file with high confidence.';
26682
+ msg = 'Warning: Unable to auto-detect the DBF file text encoding with high confidence.';
26655
26683
  msg += '\n\nDefaulting to: ' + encoding + (encoding in encodingNames ? ' (' + encodingNames[encoding] + ')' : '');
26656
- msg += '\n\nSample of how non-ascii text was imported:';
26657
- msg += '\n' + formatStringsAsGrid(decodeSamples(encoding, samples).split('\n'));
26658
- msg += decodeSamples(encoding, samples);
26684
+ msg += '\n\nSample of how non-ascii text was imported:\n';
26685
+ if (runningInBrowser()) {
26686
+ msg += '<pre>' + formatStringsAsGrid(decodeSamples(encoding, samples), 50) + '</pre>';
26687
+ } else {
26688
+ msg += formatStringsAsGrid(decodeSamples(encoding, samples));
26689
+ }
26659
26690
  msg += '\n\n' + ENCODING_PROMPT + '\n';
26660
26691
  message(msg);
26661
26692
  }
26662
26693
  }
26663
26694
 
26664
- // Show a sample of decoded text if non-ascii-range text has been found
26665
- // if (encoding && samples.length > 0) {
26666
- // msg = "Detected DBF text encoding: " + encoding + (encoding in encodingNames ? " (" + encodingNames[encoding] + ")" : "");
26667
- // message(msg);
26668
- // msg = decodeSamples(encoding, samples);
26669
- // msg = formatStringsAsGrid(msg.split('\n'));
26670
- // msg = "\nSample text containing non-ascii characters:" + (msg.length > 60 ? '\n' : '') + msg;
26671
- // verbose(msg);
26672
- // }
26673
26695
  return encoding;
26674
26696
  }
26675
26697
 
@@ -37790,7 +37812,7 @@ ${svg}
37790
37812
  filteredLyr = copyLayer(filteredLyr);
37791
37813
  }
37792
37814
 
37793
- if (opts.verbose !== false) {
37815
+ if (opts.verbose !== false && !opts.quiet) {
37794
37816
  message(utils.format('Retained %,d of %,d features', getFeatureCount(filteredLyr), n));
37795
37817
  }
37796
37818
 
@@ -37840,14 +37862,15 @@ ${svg}
37840
37862
  }
37841
37863
 
37842
37864
  function combineFilters(a, b) {
37843
- return (a && b && function(id) {
37865
+ return a && b ? function(id) {
37844
37866
  return a(id) && b(id);
37845
- }) || a || b;
37867
+ } : (a || b);
37846
37868
  }
37847
37869
 
37848
- cmd.evaluateEachFeature = function(lyr, dataset, exp, opts) {
37870
+ cmd.evaluateEachFeature = function(lyr, dataset, expArg, opts) {
37849
37871
  var n = getFeatureCount(lyr),
37850
37872
  arcs = dataset.arcs,
37873
+ exp = expArg || '',
37851
37874
  compiled, filter;
37852
37875
 
37853
37876
  var exprOpts = {
@@ -42384,6 +42407,9 @@ ${svg}
42384
42407
  candidates.forEach(function(candId) {
42385
42408
  var hit;
42386
42409
  if (candId == absId) return; // ignore self-intersections
42410
+ if (absArcId(candId) >= arcs.size()) {
42411
+ return;
42412
+ }
42387
42413
  hit = geom.getPointToPathInfo(endpoint.point[0], endpoint.point[1], [candId], arcs);
42388
42414
  if (hit && hit.distance <= maxGapLen && (!target || hit.distance < target.distance)) {
42389
42415
  target = hit;
@@ -42469,7 +42495,9 @@ ${svg}
42469
42495
  // if (opts.gap_tolerance) {
42470
42496
  //opts = utils.defaults({snap_interval: opts.gap_tolerance * 0.1}, opts);
42471
42497
  // }
42472
- addIntersectionCuts(dataset, opts);
42498
+ if (!opts.no_cuts) {
42499
+ addIntersectionCuts(dataset, opts);
42500
+ }
42473
42501
  return layers.map(function(lyr) {
42474
42502
  if (lyr.geometry_type != 'polyline') stop("Expected a polyline layer");
42475
42503
  if (opts.from_rings) {
@@ -42499,7 +42527,12 @@ ${svg}
42499
42527
  }
42500
42528
 
42501
42529
  function createPolygonLayer(lyr, dataset, opts) {
42502
- var nodes = closeUndershoots(lyr, dataset, opts);
42530
+ var nodes;
42531
+ if (opts.no_cuts) {
42532
+ nodes = new NodeCollection(dataset.arcs);
42533
+ } else {
42534
+ nodes = closeUndershoots(lyr, dataset, opts);
42535
+ }
42503
42536
  // ignore arcs that don't belong to this layer
42504
42537
  nodes.setArcFilter(getArcPresenceTest(lyr.shapes, nodes.arcs));
42505
42538
  var data = buildPolygonMosaic(nodes);
@@ -45492,7 +45525,7 @@ ${svg}
45492
45525
  });
45493
45526
  }
45494
45527
 
45495
- var version = "0.6.73";
45528
+ var version = "0.6.75";
45496
45529
 
45497
45530
  // Parse command line args into commands and run them
45498
45531
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.
@@ -46169,6 +46202,7 @@ ${svg}
46169
46202
  DelimExport,
46170
46203
  DelimImport,
46171
46204
  DelimReader,
46205
+ EncodingDetection,
46172
46206
  Encodings,
46173
46207
  Explode,
46174
46208
  Export,
package/www/page.css CHANGED
@@ -40,6 +40,20 @@ body {
40
40
  cursor: default;
41
41
  }
42
42
 
43
+ .fade-out {
44
+ animation: fadeOut ease forwards 0.6s;
45
+ }
46
+
47
+ @keyframes fadeOut {
48
+ 0% {
49
+ opacity: 1;
50
+ }
51
+ 100% {
52
+ opacity: 0;
53
+ }
54
+ }
55
+
56
+
43
57
  .selectable,.selectable * {
44
58
  user-select: default;
45
59
  -webkit-user-select: text;