mapshaper 0.6.115 → 0.6.117

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.
Files changed (3) hide show
  1. package/mapshaper.js +884 -35
  2. package/package.json +1 -1
  3. package/www/mapshaper.js +884 -35
package/www/mapshaper.js CHANGED
@@ -53,7 +53,7 @@
53
53
  get isBoolean () { return isBoolean; },
54
54
  get isDate () { return isDate; },
55
55
  get isEven () { return isEven; },
56
- get isFiniteNumber () { return isFiniteNumber; },
56
+ get isFiniteNumber () { return isFiniteNumber$1; },
57
57
  get isFunction () { return isFunction; },
58
58
  get isInteger () { return isInteger; },
59
59
  get isNonNegNumber () { return isNonNegNumber; },
@@ -70,7 +70,7 @@
70
70
  get mergeNames () { return mergeNames; },
71
71
  get numToStr () { return numToStr; },
72
72
  get parseIntlNumber () { return parseIntlNumber; },
73
- get parseNumber () { return parseNumber; },
73
+ get parseNumber () { return parseNumber$1; },
74
74
  get parsePercent () { return parsePercent; },
75
75
  get parseString () { return parseString; },
76
76
  get pickOne () { return pickOne; },
@@ -188,7 +188,7 @@
188
188
  }
189
189
 
190
190
  // Similar to isFinite() but does not coerce strings or other types
191
- function isFiniteNumber(val) {
191
+ function isFiniteNumber$1(val) {
192
192
  return isValidNumber(val) && val !== Infinity && val !== -Infinity;
193
193
  }
194
194
 
@@ -1182,7 +1182,7 @@
1182
1182
  // Use null instead of NaN for unparsable values
1183
1183
  // (in part because if NaN is used, empty strings get converted to "NaN"
1184
1184
  // when re-exported).
1185
- function parseNumber(raw) {
1185
+ function parseNumber$1(raw) {
1186
1186
  return parseToNum(raw, cleanNumericString);
1187
1187
  }
1188
1188
 
@@ -5248,7 +5248,7 @@
5248
5248
  }
5249
5249
 
5250
5250
  function toLngLat(xy, P) {
5251
- return projectPoint(xy, P, parseCrsString('wgs84'));
5251
+ return projectPoint(xy, P, parseCrsString$1('wgs84'));
5252
5252
  }
5253
5253
 
5254
5254
  function projectPoint(xy, crsFrom, crsTo) {
@@ -5335,11 +5335,11 @@
5335
5335
  function getCrsInfo(str) {
5336
5336
  return {
5337
5337
  crs_string: str,
5338
- crs: parseCrsString(str)
5338
+ crs: parseCrsString$1(str)
5339
5339
  };
5340
5340
  }
5341
5341
 
5342
- function parseCrsString(str) {
5342
+ function parseCrsString$1(str) {
5343
5343
  var defn = getProjDefn(str); // defn is a string or a Proj object
5344
5344
  var P;
5345
5345
  if (!utils.isString(defn)) {
@@ -5374,15 +5374,15 @@
5374
5374
  function getDatasetCrsInfo(dataset) {
5375
5375
  var info = copyCrsProperties(dataset.info || {});
5376
5376
  if (!info.crs && info.wkt1) {
5377
- info.crs = parseCrsString(wkt1ToProj(info.wkt1));
5377
+ info.crs = parseCrsString$1(wkt1ToProj(info.wkt1));
5378
5378
  } else if (!info.crs && info.crs_string) {
5379
- info.crs = parseCrsString(info.crs_string);
5379
+ info.crs = parseCrsString$1(info.crs_string);
5380
5380
  }
5381
5381
  if (!info.crs) {
5382
5382
  if (probablyDecimalDegreeBounds(getDatasetBounds(dataset))) {
5383
5383
  // use wgs84 for probable latlong datasets with unknown datums
5384
5384
  info.crs_string = 'wgs84';
5385
- info.crs = parseCrsString(info.crs_string);
5385
+ info.crs = parseCrsString$1(info.crs_string);
5386
5386
  }
5387
5387
  }
5388
5388
  return info;
@@ -5473,7 +5473,7 @@
5473
5473
 
5474
5474
  // Convert contents of a .prj file to a projection object
5475
5475
  function parsePrj(str) {
5476
- return parseCrsString(wkt1ToProj(str));
5476
+ return parseCrsString$1(wkt1ToProj(str));
5477
5477
  }
5478
5478
 
5479
5479
  var Projections = /*#__PURE__*/Object.freeze({
@@ -5499,7 +5499,7 @@
5499
5499
  isWGS84: isWGS84,
5500
5500
  isWebMercator: isWebMercator,
5501
5501
  looksLikeProj4String: looksLikeProj4String,
5502
- parseCrsString: parseCrsString,
5502
+ parseCrsString: parseCrsString$1,
5503
5503
  parsePrj: parsePrj,
5504
5504
  printProjections: printProjections,
5505
5505
  projectPoint: projectPoint,
@@ -11611,7 +11611,7 @@
11611
11611
  function guessInputFileType(file) {
11612
11612
  var ext = getFileExtension(file || '').toLowerCase(),
11613
11613
  type = null;
11614
- if (ext == 'dbf' || ext == 'shp' || ext == 'kml' || ext == 'fgb' || ext == 'gpkg') {
11614
+ if (ext == 'dbf' || ext == 'shp' || ext == 'kml' || ext == 'svg' || ext == 'fgb' || ext == 'gpkg') {
11615
11615
  type = ext;
11616
11616
  } else if (isAuxiliaryInputFileType(ext)) {
11617
11617
  type = ext;
@@ -11634,7 +11634,8 @@
11634
11634
  var type = null;
11635
11635
  if (utils.isString(content)) {
11636
11636
  type = stringLooksLikeJSON(content) && 'json' ||
11637
- stringLooksLikeKML(content) && 'kml' || 'text';
11637
+ stringLooksLikeKML(content) && 'kml' ||
11638
+ stringLooksLikeSVG(content) && 'svg' || 'text';
11638
11639
  } else if (utils.isObject(content) && content.type || utils.isArray(content)) {
11639
11640
  type = 'json';
11640
11641
  }
@@ -11654,6 +11655,11 @@
11654
11655
  return str.includes('<kml ') && str.includes('xmlns="http://www.opengis.net/kml/');
11655
11656
  }
11656
11657
 
11658
+ function stringLooksLikeSVG(str) {
11659
+ str = String(str);
11660
+ return str.includes('<svg ') && str.includes('xmlns="http://www.w3.org/2000/svg"');
11661
+ }
11662
+
11657
11663
  function couldBeDsvFile(name) {
11658
11664
  var ext = getFileExtension(name).toLowerCase();
11659
11665
  return /csv|tsv|txt$/.test(ext);
@@ -11725,7 +11731,8 @@
11725
11731
  looksLikeContentFile: looksLikeContentFile,
11726
11732
  looksLikeImportableFile: looksLikeImportableFile,
11727
11733
  stringLooksLikeJSON: stringLooksLikeJSON,
11728
- stringLooksLikeKML: stringLooksLikeKML
11734
+ stringLooksLikeKML: stringLooksLikeKML,
11735
+ stringLooksLikeSVG: stringLooksLikeSVG
11729
11736
  });
11730
11737
 
11731
11738
  // input: A file path or a buffer
@@ -24493,22 +24500,28 @@ ${svg}
24493
24500
  }
24494
24501
 
24495
24502
  async function exportLayerToGeoPackage(lyr, dataset, gpkg, opts) {
24496
- var features, fields, columns;
24503
+ var features, fields, columns, tableName, targetSrs;
24497
24504
  if (!lyr.geometry_type) return;
24498
24505
  features = exportLayerAsGeoJSON(lyr, dataset, opts, true, null)
24499
24506
  .filter(feat => !!(feat && feat.geometry));
24500
24507
  if (features.length === 0) return;
24501
24508
  fields = inferFieldTypes(features);
24502
- var tableName = getTableName(lyr.name);
24509
+ tableName = getTableName(lyr.name);
24503
24510
  columns = fields.map(function(field) {
24504
24511
  return {
24505
24512
  name: field.name,
24506
24513
  dataType: field.type
24507
24514
  };
24508
24515
  });
24509
- await gpkg.createFeatureTableFromProperties(tableName, columns);
24516
+ targetSrs = getExportSrs(dataset);
24517
+ await ensureSrsExists(gpkg, targetSrs);
24518
+ // createFeatureTableFromProperties() hardcodes EPSG:4326
24519
+ await gpkg.createFeatureTable(tableName, null, columns, undefined, targetSrs.srs_id);
24510
24520
  var featureDao = gpkg.getFeatureDao(tableName);
24511
- var srs = normalizeSrsForInsert(featureDao && featureDao.srs);
24521
+ // addGeoJSONFeatureToGeoPackageWithFeatureDaoAndSrs() assumes source
24522
+ // GeoJSON is EPSG:4326 and reprojects unless given EPSG:4326 metadata.
24523
+ // Mapshaper output coords are already in target CRS, so suppress reprojection.
24524
+ var srs = getSourceSrsWithoutReprojection(featureDao && featureDao.srs, targetSrs);
24512
24525
  for (var i = 0; i < features.length; i++) {
24513
24526
  var feat = features[i];
24514
24527
  var normalized = normalizeFeature(feat, fields);
@@ -24607,6 +24620,143 @@ ${svg}
24607
24620
  return removeUndefinedValues(output);
24608
24621
  }
24609
24622
 
24623
+ function getExportSrs(dataset) {
24624
+ var info = dataset.info || {};
24625
+ var gpkgCrs = normalizeSrsForInsert(info.geopackage_crs);
24626
+ if (gpkgCrs) {
24627
+ if (!gpkgCrs.definition && info.wkt1) {
24628
+ gpkgCrs.definition = info.wkt1;
24629
+ }
24630
+ return gpkgCrs;
24631
+ }
24632
+ var parsed = parseCrsString(info.crs_string);
24633
+ if (parsed) {
24634
+ if (info.wkt1) parsed.definition = info.wkt1;
24635
+ return parsed;
24636
+ }
24637
+ var fromWkt = parseWktAuthority(info.wkt1);
24638
+ if (fromWkt) {
24639
+ fromWkt.definition = info.wkt1;
24640
+ return fromWkt;
24641
+ }
24642
+ if (info.wkt1) {
24643
+ return buildCustomSrsFromWkt(info.wkt1);
24644
+ }
24645
+ return {
24646
+ srs_id: 4326,
24647
+ organization: 'EPSG',
24648
+ organization_coordsys_id: 4326
24649
+ };
24650
+ }
24651
+
24652
+ function parseCrsString(str) {
24653
+ if (!str || typeof str != 'string') return null;
24654
+ var match = str.match(/^([a-z]+):(\d+)$/i);
24655
+ if (!match) return null;
24656
+ var org = match[1].toUpperCase();
24657
+ var code = +match[2];
24658
+ if (!code) return null;
24659
+ return {
24660
+ srs_id: code,
24661
+ organization: org,
24662
+ organization_coordsys_id: code
24663
+ };
24664
+ }
24665
+
24666
+ function parseWktAuthority(wkt) {
24667
+ if (!wkt || typeof wkt != 'string') return null;
24668
+ var rootAuthority = findTopLevelWktAuthority(wkt);
24669
+ if (!rootAuthority) return null;
24670
+ var org = String(rootAuthority[1]).toUpperCase();
24671
+ var code = +rootAuthority[2];
24672
+ if (!code) return null;
24673
+ return {
24674
+ srs_id: code,
24675
+ organization: org,
24676
+ organization_coordsys_id: code
24677
+ };
24678
+ }
24679
+
24680
+ function findTopLevelWktAuthority(wkt) {
24681
+ var depth = 0;
24682
+ var inQuote = false;
24683
+ for (var i = 0; i < wkt.length; i++) {
24684
+ var c = wkt.charAt(i);
24685
+ if (c == '"') {
24686
+ inQuote = !inQuote;
24687
+ continue;
24688
+ }
24689
+ if (inQuote) continue;
24690
+ if (c == '[') {
24691
+ depth++;
24692
+ continue;
24693
+ }
24694
+ if (c == ']') {
24695
+ depth--;
24696
+ continue;
24697
+ }
24698
+ if (depth != 1) continue;
24699
+ if (wkt.slice(i, i + 10).toUpperCase() == 'AUTHORITY[') {
24700
+ return wkt.slice(i).match(/^AUTHORITY\["([^"]+)","(\d+)"\]/i);
24701
+ }
24702
+ }
24703
+ return null;
24704
+ }
24705
+
24706
+ function buildCustomSrsFromWkt(wkt) {
24707
+ var srsId = getCustomSrsId(wkt);
24708
+ return {
24709
+ srs_id: srsId,
24710
+ srs_name: getWktName(wkt) || 'CUSTOM_CRS',
24711
+ organization: 'NONE',
24712
+ organization_coordsys_id: srsId,
24713
+ definition: wkt,
24714
+ description: 'Custom projection'
24715
+ };
24716
+ }
24717
+
24718
+ function getWktName(wkt) {
24719
+ var match = wkt && String(wkt).match(/^(?:PROJCS|GEOGCS)\["([^"]+)"/i);
24720
+ return match ? match[1] : null;
24721
+ }
24722
+
24723
+ function getCustomSrsId(wkt) {
24724
+ var str = String(wkt || '');
24725
+ var hash = 2166136261; // FNV-1a
24726
+ for (var i = 0; i < str.length; i++) {
24727
+ hash ^= str.charCodeAt(i);
24728
+ hash = (hash * 16777619) >>> 0;
24729
+ }
24730
+ return 100000 + (hash % 900000);
24731
+ }
24732
+
24733
+ async function ensureSrsExists(gpkg, srs) {
24734
+ if (!srs || !srs.srs_id) return;
24735
+ var existing = gpkg.getSrs(srs.srs_id);
24736
+ if (existing) return;
24737
+ if (!srs.definition) {
24738
+ stop$1('Unable to export GeoPackage with missing CRS definition for SRS ' + srs.srs_id);
24739
+ }
24740
+ var geopackage = require$1('@ngageoint/geopackage');
24741
+ var spatialReferenceSystem = new geopackage.SpatialReferenceSystem();
24742
+ spatialReferenceSystem.srs_id = srs.srs_id;
24743
+ spatialReferenceSystem.srs_name = srs.srs_name || (srs.organization + ':' + srs.organization_coordsys_id);
24744
+ spatialReferenceSystem.organization = srs.organization;
24745
+ spatialReferenceSystem.organization_coordsys_id = srs.organization_coordsys_id;
24746
+ spatialReferenceSystem.definition = srs.definition;
24747
+ spatialReferenceSystem.description = srs.description || null;
24748
+ gpkg.createSpatialReferenceSystem(spatialReferenceSystem);
24749
+ }
24750
+
24751
+ function getSourceSrsWithoutReprojection(tableSrs, fallbackSrs) {
24752
+ var target = normalizeSrsForInsert(tableSrs) || normalizeSrsForInsert(fallbackSrs);
24753
+ return {
24754
+ srs_id: target.srs_id,
24755
+ organization: 'EPSG',
24756
+ organization_coordsys_id: 4326
24757
+ };
24758
+ }
24759
+
24610
24760
  function normalizeValue(value, type) {
24611
24761
  if (value === null || value === undefined) return null;
24612
24762
  if (type == 'TEXT' && typeof value != 'string') {
@@ -24664,14 +24814,14 @@ ${svg}
24664
24814
  }
24665
24815
 
24666
24816
  function normalizeSrsForInsert(srs) {
24667
- if (!srs) {
24668
- return {
24669
- srs_id: 4326,
24670
- organization: 'EPSG',
24671
- organization_coordsys_id: 4326
24672
- };
24673
- }
24817
+ if (!srs) return null;
24674
24818
  var normalized = Object.assign({}, srs);
24819
+ if (normalized.srs_id == null && normalized.id != null) {
24820
+ normalized.srs_id = normalized.id;
24821
+ }
24822
+ if (normalized.organization_coordsys_id == null && normalized.code != null) {
24823
+ normalized.organization_coordsys_id = normalized.code;
24824
+ }
24675
24825
  if (normalized.srs_id == null && normalized.srsId != null) {
24676
24826
  normalized.srs_id = normalized.srsId;
24677
24827
  }
@@ -24685,6 +24835,7 @@ ${svg}
24685
24835
  if (!normalized.organization) {
24686
24836
  normalized.organization = 'EPSG';
24687
24837
  }
24838
+ normalized.organization = String(normalized.organization).toUpperCase();
24688
24839
  if (normalized.organization_coordsys_id == null) {
24689
24840
  normalized.organization_coordsys_id = normalized.srs_id || 4326;
24690
24841
  }
@@ -31313,17 +31464,26 @@ ${svg}
31313
31464
  var gpkg;
31314
31465
  var datasets;
31315
31466
  var source;
31467
+ var tmpPath = null;
31316
31468
 
31317
31469
  if (!geopackage || !geopackage.GeoPackageAPI) {
31318
31470
  stop$1('GeoPackage library is not loaded');
31319
31471
  }
31320
31472
 
31321
- source = utils.isString(content) ? content : new Uint8Array(content);
31473
+ if (utils.isString(content)) {
31474
+ source = content;
31475
+ } else if (!runningInBrowser()) {
31476
+ tmpPath = writeGeoPackageTempFile(content);
31477
+ source = tmpPath;
31478
+ } else {
31479
+ source = new Uint8Array(content);
31480
+ }
31322
31481
  gpkg = await geopackage.GeoPackageAPI.open(source);
31323
31482
  try {
31324
31483
  datasets = readFeatureTableDatasets(gpkg, opts);
31325
31484
  } finally {
31326
31485
  gpkg.close();
31486
+ removeTempGeoPackageFile(tmpPath);
31327
31487
  }
31328
31488
 
31329
31489
  if (datasets.length === 0) {
@@ -31338,6 +31498,24 @@ ${svg}
31338
31498
  return mergeDatasets(datasets);
31339
31499
  }
31340
31500
 
31501
+ function writeGeoPackageTempFile(content) {
31502
+ var fs = require$1('fs');
31503
+ var os = require$1('os');
31504
+ var path = require$1('path');
31505
+ var unique = Date.now() + '-' + process.pid + '-' + Math.random().toString(36).slice(2);
31506
+ var tmpPath = path.join(os.tmpdir(), 'mapshaper-gpkg-import-' + unique + '.gpkg');
31507
+ fs.writeFileSync(tmpPath, Buffer.from(new Uint8Array(content)));
31508
+ return tmpPath;
31509
+ }
31510
+
31511
+ function removeTempGeoPackageFile(filepath) {
31512
+ if (!filepath) return;
31513
+ var fs = require$1('fs');
31514
+ if (fs.existsSync(filepath)) {
31515
+ fs.unlinkSync(filepath);
31516
+ }
31517
+ }
31518
+
31341
31519
  // load lookup tables for epsg codes if needed (for browser)
31342
31520
  async function initProjLib(datasets) {
31343
31521
  for (const dataset of datasets) {
@@ -31449,6 +31627,672 @@ ${svg}
31449
31627
  return obj;
31450
31628
  }
31451
31629
 
31630
+ var INHERITED_STYLE_KEYS = [
31631
+ 'fill', 'fill-opacity',
31632
+ 'stroke', 'stroke-width', 'stroke-opacity', 'stroke-dasharray',
31633
+ 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit',
31634
+ 'opacity', 'vector-effect',
31635
+ 'font-family', 'font-size', 'font-style', 'font-stretch', 'font-weight',
31636
+ 'text-anchor', 'dominant-baseline', 'letter-spacing', 'line-height'
31637
+ ];
31638
+
31639
+ var INHERITED_STYLE_INDEX = INHERITED_STYLE_KEYS.reduce(function(memo, key) {
31640
+ memo[key] = true;
31641
+ return memo;
31642
+ }, {});
31643
+
31644
+ var LAYER_SUFFIX = {
31645
+ polygon: 'polygons',
31646
+ polyline: 'lines',
31647
+ point: 'points'
31648
+ };
31649
+
31650
+ function importSVG(str, optsArg) {
31651
+ var opts = optsArg || {};
31652
+ var Parser = typeof DOMParser == 'undefined' ? require$1('@xmldom/xmldom').DOMParser : DOMParser;
31653
+ var doc = new Parser().parseFromString(str, 'text/xml');
31654
+ var root = doc && doc.documentElement;
31655
+ var groups = getTopLevelLayerGroups(root);
31656
+ var layerData = [];
31657
+ var datasets = [];
31658
+
31659
+ groups.forEach(function(group) {
31660
+ var features = [];
31661
+ collectFeatures(group.node, {}, features, {
31662
+ forcePolylinePaths: layerHasOpenPaths(group.node)
31663
+ });
31664
+ if (features.length === 0) return;
31665
+ layerData.push({
31666
+ name: group.name,
31667
+ features: features
31668
+ });
31669
+ });
31670
+
31671
+ flipYCoordinates(layerData);
31672
+
31673
+ layerData.forEach(function(layer) {
31674
+ datasets.push(importLayerFeatures(layer.name, layer.features, opts));
31675
+ });
31676
+
31677
+ if (datasets.length === 0) {
31678
+ return {layers: [], info: {}};
31679
+ }
31680
+ if (datasets.length === 1) {
31681
+ return datasets[0];
31682
+ }
31683
+ return mergeDatasets(datasets);
31684
+ }
31685
+
31686
+ function importLayerFeatures(layerName, features, opts) {
31687
+ var dataset = importGeoJSON({
31688
+ type: 'FeatureCollection',
31689
+ features: features
31690
+ }, opts);
31691
+ if (dataset.layers.length === 1) {
31692
+ dataset.layers[0].name = layerName;
31693
+ } else {
31694
+ dataset.layers.forEach(function(lyr) {
31695
+ var suffix = LAYER_SUFFIX[lyr.geometry_type] || 'features';
31696
+ lyr.name = layerName + '_' + suffix;
31697
+ });
31698
+ }
31699
+ return dataset;
31700
+ }
31701
+
31702
+ function getTopLevelLayerGroups(root) {
31703
+ var groups = [];
31704
+ var childNodes = getElementChildren(root);
31705
+ var defaultNode = null;
31706
+ var layerCount = 0;
31707
+
31708
+ childNodes.forEach(function(node) {
31709
+ var tag = getTagName(node);
31710
+ if (tag == 'defs') return;
31711
+ if (tag == 'g') {
31712
+ groups.push({
31713
+ node: node,
31714
+ name: node.getAttribute('id') || getDefaultLayerName(++layerCount)
31715
+ });
31716
+ } else if (tag == 'path' || tag == 'circle' || tag == 'text') {
31717
+ if (!defaultNode) {
31718
+ defaultNode = {
31719
+ tagName: 'g',
31720
+ childNodes: [],
31721
+ attributes: []
31722
+ };
31723
+ groups.push({
31724
+ node: defaultNode,
31725
+ name: getDefaultLayerName(++layerCount)
31726
+ });
31727
+ }
31728
+ defaultNode.childNodes.push(node);
31729
+ }
31730
+ });
31731
+
31732
+ if (groups.length === 0 && root) {
31733
+ groups.push({
31734
+ node: root,
31735
+ name: getDefaultLayerName(1)
31736
+ });
31737
+ }
31738
+ return groups;
31739
+ }
31740
+
31741
+ function getDefaultLayerName(i) {
31742
+ return 'layer' + i;
31743
+ }
31744
+
31745
+ function collectFeatures(node, inheritedStyles, features, layerOpts) {
31746
+ var tag = getTagName(node);
31747
+ var nodeStyles = getNodeStyles(node);
31748
+ var inherited = extendProps(inheritedStyles, nodeStyles);
31749
+
31750
+ if (tag == 'defs') return;
31751
+ if (tag == 'g' || tag == 'svg') {
31752
+ getElementChildren(node).forEach(function(child) {
31753
+ collectFeatures(child, inherited, features, layerOpts);
31754
+ });
31755
+ return;
31756
+ }
31757
+ if (tag == 'path') {
31758
+ collectPathFeature(node, inherited, features, layerOpts);
31759
+ } else if (tag == 'circle') {
31760
+ collectCircleFeature(node, inherited, features);
31761
+ } else if (tag == 'text') {
31762
+ collectTextFeature(node, inherited, features);
31763
+ }
31764
+ }
31765
+
31766
+ function collectPathFeature(node, inherited, features, layerOpts) {
31767
+ var d = node.getAttribute('d');
31768
+ var geom = parsePathGeometry(d, layerOpts && layerOpts.forcePolylinePaths);
31769
+ var props;
31770
+ if (!geom) return;
31771
+ props = getFeatureProperties(node, inherited, {d: true});
31772
+ features.push({
31773
+ type: 'Feature',
31774
+ geometry: geom,
31775
+ properties: props
31776
+ });
31777
+ }
31778
+
31779
+ function collectCircleFeature(node, inherited, features) {
31780
+ var x = parseNumber(node.getAttribute('cx'));
31781
+ var y = parseNumber(node.getAttribute('cy'));
31782
+ var props;
31783
+ if (!isFiniteNumber(x) || !isFiniteNumber(y)) return;
31784
+ props = getFeatureProperties(node, inherited, {cx: true, cy: true});
31785
+ addNumericProperty(props, 'r', node.getAttribute('r'));
31786
+ features.push({
31787
+ type: 'Feature',
31788
+ geometry: {
31789
+ type: 'Point',
31790
+ coordinates: [x, y]
31791
+ },
31792
+ properties: props
31793
+ });
31794
+ }
31795
+
31796
+ function collectTextFeature(node, inherited, features) {
31797
+ var baseX = parseNumber(node.getAttribute('x')) || 0;
31798
+ var baseY = parseNumber(node.getAttribute('y')) || 0;
31799
+ var translate = parseTranslate(node.getAttribute('transform'));
31800
+ var hasTranslate = nodeHasTranslate(node.getAttribute('transform'));
31801
+ var x = hasTranslate ? translate[0] : baseX;
31802
+ var y = hasTranslate ? translate[1] : baseY;
31803
+ var text = (node.textContent || '').trim();
31804
+ var props = getFeatureProperties(node, inherited, {x: true, y: true, transform: true});
31805
+
31806
+ props['label-text'] = text;
31807
+ if (hasTranslate && node.getAttribute('x') !== null) {
31808
+ props.dx = baseX;
31809
+ }
31810
+ if (hasTranslate && node.getAttribute('y') !== null) {
31811
+ props.dy = baseY;
31812
+ }
31813
+ features.push({
31814
+ type: 'Feature',
31815
+ geometry: {
31816
+ type: 'Point',
31817
+ coordinates: [x, y]
31818
+ },
31819
+ properties: props
31820
+ });
31821
+ }
31822
+
31823
+ function getFeatureProperties(node, inherited, excluded) {
31824
+ var props = extendProps({}, inherited);
31825
+ var attrs = node.attributes || [];
31826
+ var styleMap = parseStyleString(node.getAttribute && node.getAttribute('style'));
31827
+
31828
+ Object.keys(styleMap).forEach(function(name) {
31829
+ if (name == 'fill-rule') return;
31830
+ props[name] = styleMap[name];
31831
+ });
31832
+ for (var i = 0; i < attrs.length; i++) {
31833
+ var attr = attrs[i];
31834
+ var key = attr && attr.name;
31835
+ var val = attr && attr.value;
31836
+ if (!key || key == 'style' || (excluded && excluded[key])) continue;
31837
+ if (key == 'id' || key == 'class' || key.indexOf('data-') === 0 || INHERITED_STYLE_INDEX[key]) {
31838
+ props[key] = val;
31839
+ }
31840
+ }
31841
+ return props;
31842
+ }
31843
+
31844
+ function getNodeStyles(node) {
31845
+ var styles = {};
31846
+ var attrs = node.attributes || [];
31847
+ var styleMap = parseStyleString(node.getAttribute && node.getAttribute('style'));
31848
+ var i, attr, key;
31849
+
31850
+ Object.keys(styleMap).forEach(function(name) {
31851
+ if (INHERITED_STYLE_INDEX[name]) {
31852
+ styles[name] = styleMap[name];
31853
+ }
31854
+ });
31855
+
31856
+ for (i = 0; i < attrs.length; i++) {
31857
+ attr = attrs[i];
31858
+ key = attr && attr.name;
31859
+ if (key && INHERITED_STYLE_INDEX[key]) {
31860
+ styles[key] = attr.value;
31861
+ }
31862
+ }
31863
+ return styles;
31864
+ }
31865
+
31866
+ function parseStyleString(style) {
31867
+ var out = {};
31868
+ var parts, i, part, idx, key, val;
31869
+ if (!style) return out;
31870
+ parts = String(style).split(';');
31871
+ for (i = 0; i < parts.length; i++) {
31872
+ part = parts[i].trim();
31873
+ if (!part) continue;
31874
+ idx = part.indexOf(':');
31875
+ if (idx == -1) continue;
31876
+ key = part.substr(0, idx).trim();
31877
+ val = part.substr(idx + 1).trim();
31878
+ if (!key) continue;
31879
+ out[key] = val;
31880
+ }
31881
+ return out;
31882
+ }
31883
+
31884
+ function parsePathGeometry(d, forcePolylinePaths) {
31885
+ var subpaths = parsePathData(d);
31886
+ var lines = [];
31887
+ var rings = [];
31888
+ var parts = [];
31889
+ var polygonGeom, polylineGeom;
31890
+
31891
+ subpaths.forEach(function(path) {
31892
+ var coords = path.coords;
31893
+ if (coords.length < 2) return;
31894
+ if (forcePolylinePaths) {
31895
+ lines.push(path.closed || pointsEqual(coords[0], coords[coords.length - 1]) ? closeRing(coords) : coords);
31896
+ return;
31897
+ }
31898
+ if (path.closed || pointsEqual(coords[0], coords[coords.length - 1])) {
31899
+ if (coords.length >= 3) {
31900
+ rings.push(closeRing(coords));
31901
+ }
31902
+ } else {
31903
+ lines.push(coords);
31904
+ }
31905
+ });
31906
+
31907
+ if (rings.length > 0) {
31908
+ polygonGeom = buildPolygonGeometry(rings);
31909
+ if (polygonGeom) parts.push(polygonGeom);
31910
+ }
31911
+ if (lines.length > 0) {
31912
+ polylineGeom = lines.length == 1 ? {
31913
+ type: 'LineString',
31914
+ coordinates: lines[0]
31915
+ } : {
31916
+ type: 'MultiLineString',
31917
+ coordinates: lines
31918
+ };
31919
+ parts.push(polylineGeom);
31920
+ }
31921
+ if (parts.length === 0) return null;
31922
+ if (parts.length === 1) return parts[0];
31923
+ return {
31924
+ type: 'GeometryCollection',
31925
+ geometries: parts
31926
+ };
31927
+ }
31928
+
31929
+ function buildPolygonGeometry(rings) {
31930
+ var ringData = rings.map(function(coords, i) {
31931
+ return {
31932
+ id: i,
31933
+ coords: coords,
31934
+ area: Math.abs(getRingArea(coords)),
31935
+ containers: [],
31936
+ depth: 0,
31937
+ parent: null
31938
+ };
31939
+ });
31940
+
31941
+ ringData.forEach(function(ring, i) {
31942
+ var point = getRingSamplePoint(ring.coords);
31943
+ ringData.forEach(function(other, j) {
31944
+ if (i == j) return;
31945
+ if (pointInRing(point, other.coords)) {
31946
+ ring.containers.push(other.id);
31947
+ }
31948
+ });
31949
+ ring.depth = ring.containers.length;
31950
+ });
31951
+
31952
+ ringData.forEach(function(ring) {
31953
+ var parentDepth = ring.depth - 1;
31954
+ if (parentDepth < 0) return;
31955
+ ring.containers.forEach(function(parentId) {
31956
+ var candidate = ringData[parentId];
31957
+ if (candidate.depth != parentDepth) return;
31958
+ if (!ring.parent || candidate.area < ring.parent.area) {
31959
+ ring.parent = candidate;
31960
+ }
31961
+ });
31962
+ });
31963
+
31964
+ var polygons = [];
31965
+ ringData.forEach(function(ring) {
31966
+ if (ring.depth % 2 !== 0) return;
31967
+ polygons.push([ring.coords]);
31968
+ });
31969
+
31970
+ ringData.forEach(function(ring) {
31971
+ var polygon;
31972
+ if (ring.depth % 2 !== 1 || !ring.parent) return;
31973
+ polygon = polygons.find(function(coords) {
31974
+ return coords[0] === ring.parent.coords;
31975
+ });
31976
+ if (polygon) {
31977
+ polygon.push(ring.coords);
31978
+ }
31979
+ });
31980
+
31981
+ if (polygons.length === 0) return null;
31982
+ if (polygons.length == 1) {
31983
+ return {
31984
+ type: 'Polygon',
31985
+ coordinates: polygons[0]
31986
+ };
31987
+ }
31988
+ return {
31989
+ type: 'MultiPolygon',
31990
+ coordinates: polygons.map(function(coords) {
31991
+ return [coords[0]].concat(coords.slice(1));
31992
+ })
31993
+ };
31994
+ }
31995
+
31996
+ function parsePathData(d) {
31997
+ var tokens = tokenizePath(d || '');
31998
+ var paths = [];
31999
+ var cmd = null;
32000
+ var i = 0;
32001
+ var currX = 0;
32002
+ var currY = 0;
32003
+ var startX = 0;
32004
+ var startY = 0;
32005
+ var path = null;
32006
+
32007
+ function startPath(x, y) {
32008
+ if (path && path.coords.length > 0) {
32009
+ paths.push(path);
32010
+ }
32011
+ path = {
32012
+ coords: [[x, y]],
32013
+ closed: false
32014
+ };
32015
+ currX = x;
32016
+ currY = y;
32017
+ startX = x;
32018
+ startY = y;
32019
+ }
32020
+
32021
+ function addPoint(x, y) {
32022
+ if (!path) {
32023
+ startPath(x, y);
32024
+ return;
32025
+ }
32026
+ path.coords.push([x, y]);
32027
+ currX = x;
32028
+ currY = y;
32029
+ }
32030
+
32031
+ while (i < tokens.length) {
32032
+ if (isPathCommand(tokens[i])) {
32033
+ cmd = tokens[i++];
32034
+ if (cmd == 'Z' || cmd == 'z') {
32035
+ if (path) {
32036
+ path.closed = true;
32037
+ currX = startX;
32038
+ currY = startY;
32039
+ }
32040
+ }
32041
+ continue;
32042
+ }
32043
+ if (!cmd) {
32044
+ i++;
32045
+ continue;
32046
+ }
32047
+
32048
+ if (cmd == 'M' || cmd == 'm') {
32049
+ if (!hasPair(tokens, i)) break;
32050
+ var moveX = Number(tokens[i++]);
32051
+ var moveY = Number(tokens[i++]);
32052
+ if (cmd == 'm') {
32053
+ moveX += currX;
32054
+ moveY += currY;
32055
+ }
32056
+ startPath(moveX, moveY);
32057
+ cmd = cmd == 'm' ? 'l' : 'L';
32058
+ continue;
32059
+ }
32060
+
32061
+ if (cmd == 'L' || cmd == 'l') {
32062
+ if (!hasPair(tokens, i)) break;
32063
+ var lineX = Number(tokens[i++]);
32064
+ var lineY = Number(tokens[i++]);
32065
+ if (cmd == 'l') {
32066
+ lineX += currX;
32067
+ lineY += currY;
32068
+ }
32069
+ addPoint(lineX, lineY);
32070
+ continue;
32071
+ }
32072
+
32073
+ if (cmd == 'H' || cmd == 'h') {
32074
+ var x = Number(tokens[i++]);
32075
+ if (cmd == 'h') x += currX;
32076
+ addPoint(x, currY);
32077
+ continue;
32078
+ }
32079
+
32080
+ if (cmd == 'V' || cmd == 'v') {
32081
+ var y = Number(tokens[i++]);
32082
+ if (cmd == 'v') y += currY;
32083
+ addPoint(currX, y);
32084
+ continue;
32085
+ }
32086
+
32087
+ // Unsupported command -- skip following numeric tokens until next command.
32088
+ while (i < tokens.length && !isPathCommand(tokens[i])) {
32089
+ i++;
32090
+ }
32091
+ }
32092
+
32093
+ if (path && path.coords.length > 0) {
32094
+ paths.push(path);
32095
+ }
32096
+ return paths;
32097
+ }
32098
+
32099
+ function layerHasOpenPaths(node) {
32100
+ var hasOpenPath = false;
32101
+
32102
+ function scan(el) {
32103
+ var tag = getTagName(el);
32104
+ if (!tag || tag == 'defs' || hasOpenPath) return;
32105
+ if (tag == 'path') {
32106
+ hasOpenPath = pathContainsOpenSubpath(el.getAttribute('d'));
32107
+ return;
32108
+ }
32109
+ getElementChildren(el).forEach(scan);
32110
+ }
32111
+
32112
+ scan(node);
32113
+ return hasOpenPath;
32114
+ }
32115
+
32116
+ function pathContainsOpenSubpath(d) {
32117
+ var subpaths = parsePathData(d);
32118
+ for (var i = 0; i < subpaths.length; i++) {
32119
+ var coords = subpaths[i].coords;
32120
+ if (coords.length < 2) continue;
32121
+ if (!subpaths[i].closed && !pointsEqual(coords[0], coords[coords.length - 1])) {
32122
+ return true;
32123
+ }
32124
+ }
32125
+ return false;
32126
+ }
32127
+
32128
+ function flipYCoordinates(layerData) {
32129
+ var range = getYRange(layerData);
32130
+ if (!range) return;
32131
+ layerData.forEach(function(layer) {
32132
+ layer.features.forEach(function(feature) {
32133
+ if (feature && feature.geometry) {
32134
+ flipGeometryY(feature.geometry, range);
32135
+ }
32136
+ });
32137
+ });
32138
+ }
32139
+
32140
+ function getYRange(layerData) {
32141
+ var minY = Infinity;
32142
+ var maxY = -Infinity;
32143
+ layerData.forEach(function(layer) {
32144
+ layer.features.forEach(function(feature) {
32145
+ forEachGeometryCoordinate(feature && feature.geometry, function(coord) {
32146
+ if (coord[1] < minY) minY = coord[1];
32147
+ if (coord[1] > maxY) maxY = coord[1];
32148
+ });
32149
+ });
32150
+ });
32151
+ if (!isFinite(minY) || !isFinite(maxY)) return null;
32152
+ return {min: minY, max: maxY};
32153
+ }
32154
+
32155
+ function flipGeometryY(geom, range) {
32156
+ forEachGeometryCoordinate(geom, function(coord) {
32157
+ coord[1] = range.min + range.max - coord[1];
32158
+ });
32159
+ }
32160
+
32161
+ function forEachGeometryCoordinate(geom, cb) {
32162
+ if (!geom || !geom.type) return;
32163
+ if (geom.type == 'Point') {
32164
+ cb(geom.coordinates);
32165
+ } else if (geom.type == 'LineString' || geom.type == 'MultiPoint') {
32166
+ geom.coordinates.forEach(cb);
32167
+ } else if (geom.type == 'Polygon' || geom.type == 'MultiLineString') {
32168
+ geom.coordinates.forEach(function(path) {
32169
+ path.forEach(cb);
32170
+ });
32171
+ } else if (geom.type == 'MultiPolygon') {
32172
+ geom.coordinates.forEach(function(poly) {
32173
+ poly.forEach(function(ring) {
32174
+ ring.forEach(cb);
32175
+ });
32176
+ });
32177
+ } else if (geom.type == 'GeometryCollection') {
32178
+ (geom.geometries || []).forEach(function(child) {
32179
+ forEachGeometryCoordinate(child, cb);
32180
+ });
32181
+ }
32182
+ }
32183
+
32184
+ function tokenizePath(d) {
32185
+ var rxp = /[a-zA-Z]|-?(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?/ig;
32186
+ return String(d).match(rxp) || [];
32187
+ }
32188
+
32189
+ function parseTranslate(str) {
32190
+ var match = String(str || '').match(/translate\(\s*([^\s,()]+)(?:[\s,]+([^\s,()]+))?/i);
32191
+ var x = 0;
32192
+ var y = 0;
32193
+ if (match) {
32194
+ x = parseNumber(match[1]) || 0;
32195
+ y = parseNumber(match[2]) || 0;
32196
+ }
32197
+ return [x, y];
32198
+ }
32199
+
32200
+ function nodeHasTranslate(str) {
32201
+ return /translate\(/i.test(String(str || ''));
32202
+ }
32203
+
32204
+ function closeRing(coords) {
32205
+ var ring = coords.map(function(p) { return [p[0], p[1]]; });
32206
+ if (!pointsEqual(ring[0], ring[ring.length - 1])) {
32207
+ ring.push([ring[0][0], ring[0][1]]);
32208
+ }
32209
+ return ring;
32210
+ }
32211
+
32212
+ function getRingSamplePoint(ring) {
32213
+ return ring[0];
32214
+ }
32215
+
32216
+ function getRingArea(ring) {
32217
+ var area = 0;
32218
+ for (var i = 0, n = ring.length - 1; i < n; i++) {
32219
+ area += ring[i][0] * ring[i + 1][1] - ring[i + 1][0] * ring[i][1];
32220
+ }
32221
+ return area / 2;
32222
+ }
32223
+
32224
+ function pointInRing(point, ring) {
32225
+ var x = point[0];
32226
+ var y = point[1];
32227
+ var inside = false;
32228
+ var i, j, xi, yi, xj, yj, intersects;
32229
+ for (i = 0, j = ring.length - 1; i < ring.length; j = i++) {
32230
+ xi = ring[i][0];
32231
+ yi = ring[i][1];
32232
+ xj = ring[j][0];
32233
+ yj = ring[j][1];
32234
+ intersects = ((yi > y) != (yj > y)) &&
32235
+ (x < (xj - xi) * (y - yi) / ((yj - yi) || 1e-30) + xi);
32236
+ if (intersects) inside = !inside;
32237
+ }
32238
+ return inside;
32239
+ }
32240
+
32241
+ function addNumericProperty(props, key, strVal) {
32242
+ var num = parseNumber(strVal);
32243
+ if (isFiniteNumber(num)) {
32244
+ props[key] = num;
32245
+ }
32246
+ }
32247
+
32248
+ function parseNumber(str) {
32249
+ var num = Number(str);
32250
+ return isFiniteNumber(num) ? num : null;
32251
+ }
32252
+
32253
+ function hasPair(tokens, i) {
32254
+ return i + 1 < tokens.length && !isPathCommand(tokens[i]) && !isPathCommand(tokens[i + 1]);
32255
+ }
32256
+
32257
+ function isPathCommand(token) {
32258
+ return /^[a-z]$/i.test(token);
32259
+ }
32260
+
32261
+ function pointsEqual(a, b) {
32262
+ return a && b && a[0] == b[0] && a[1] == b[1];
32263
+ }
32264
+
32265
+ function isFiniteNumber(val) {
32266
+ return typeof val == 'number' && isFinite(val);
32267
+ }
32268
+
32269
+ function getTagName(node) {
32270
+ return node && node.tagName ? String(node.tagName).toLowerCase() : '';
32271
+ }
32272
+
32273
+ function getElementChildren(node) {
32274
+ var out = [];
32275
+ var childNodes = node && node.childNodes ? node.childNodes : [];
32276
+ for (var i = 0; i < childNodes.length; i++) {
32277
+ if (childNodes[i] && childNodes[i].nodeType == 1) {
32278
+ out.push(childNodes[i]);
32279
+ }
32280
+ }
32281
+ return out;
32282
+ }
32283
+
32284
+ function extendProps(dest, src) {
32285
+ var out = {};
32286
+ var key;
32287
+ if (dest) {
32288
+ for (key in dest) out[key] = dest[key];
32289
+ }
32290
+ if (src) {
32291
+ for (key in src) out[key] = src[key];
32292
+ }
32293
+ return out;
32294
+ }
32295
+
31452
32296
  // Parse content of one or more input files and return a dataset
31453
32297
  // @obj: file data, indexed by file type
31454
32298
  // File data objects have two properties:
@@ -31491,6 +32335,11 @@ ${svg}
31491
32335
  data = obj.kml;
31492
32336
  dataset = importKML(data.content, opts);
31493
32337
 
32338
+ } else if (obj.svg) {
32339
+ dataFmt = 'svg';
32340
+ data = obj.svg;
32341
+ dataset = importSVG(data.content, opts);
32342
+
31494
32343
  } else if (obj.fgb) {
31495
32344
  stop$1("FlatGeobuf import requires async import path");
31496
32345
  } else if (obj.gpkg) {
@@ -31690,7 +32539,7 @@ ${svg}
31690
32539
  if (o.crs_string) {
31691
32540
  // load external files (e.g. epsg definitions) if needed in GUI
31692
32541
  await initProjLibrary({crs: o.crs_string});
31693
- o.crs = parseCrsString(o.crs_string);
32542
+ o.crs = parseCrsString$1(o.crs_string);
31694
32543
  } else if (o.prj) {
31695
32544
  o.crs = parsePrj(o.prj);
31696
32545
  }
@@ -35072,7 +35921,7 @@ ${svg}
35072
35921
  // Make a single geodetic circle
35073
35922
  function getCircleGeoJSON(center, radius, vertices, opts) {
35074
35923
  var n = 360;
35075
- var geod = getGeodeticSegmentFunction(parseCrsString('wgs84')); // ?
35924
+ var geod = getGeodeticSegmentFunction(parseCrsString$1('wgs84')); // ?
35076
35925
  if (opts.inset) {
35077
35926
  radius -= opts.inset;
35078
35927
  }
@@ -43702,23 +44551,23 @@ ${svg}
43702
44551
  };
43703
44552
 
43704
44553
  function createUnprojectedPolygon(opts) {
43705
- var crs = parseCrsString('wgs84');
44554
+ var crs = parseCrsString$1('wgs84');
43706
44555
  return getPolygonDataset$1(crs, crs, opts);
43707
44556
  }
43708
44557
 
43709
44558
  function createProjectedPolygon(dest, opts) {
43710
- var src = parseCrsString('wgs84');
44559
+ var src = parseCrsString$1('wgs84');
43711
44560
  return getPolygonDataset$1(src, dest, opts);
43712
44561
  }
43713
44562
 
43714
44563
  function createUnprojectedGraticule(opts) {
43715
- var src = parseCrsString('wgs84');
44564
+ var src = parseCrsString$1('wgs84');
43716
44565
  var graticule = importGeoJSON(createGraticule(src, false, opts));
43717
44566
  return graticule;
43718
44567
  }
43719
44568
 
43720
44569
  function createProjectedGraticule(dest, opts) {
43721
- var src = parseCrsString('wgs84');
44570
+ var src = parseCrsString$1('wgs84');
43722
44571
  var outline = getOutlineDataset(src, dest, {});
43723
44572
  var graticule = importGeoJSON(createGraticule(dest, !!outline, opts));
43724
44573
  projectDataset(graticule, src, dest, {no_clip: false}); // TODO: densify?
@@ -46752,7 +47601,7 @@ ${svg}
46752
47601
  stop$1('Missing required radius parameter.');
46753
47602
  }
46754
47603
  var cp = opts.center || [0, 0];
46755
- var radius = opts.radius || getCircleRadiusFromAngle(parseCrsString('wgs84'), opts.radius_angle);
47604
+ var radius = opts.radius || getCircleRadiusFromAngle(parseCrsString$1('wgs84'), opts.radius_angle);
46756
47605
  return getCircleGeoJSON(cp, radius, null, {geometry_type : opts.geometry || 'polygon'});
46757
47606
  }
46758
47607
 
@@ -49343,7 +50192,7 @@ ${svg}
49343
50192
  });
49344
50193
  }
49345
50194
 
49346
- var version = "0.6.115";
50195
+ var version = "0.6.117";
49347
50196
 
49348
50197
  // Parse command line args into commands and run them
49349
50198
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.