mapshaper 0.7.12 → 0.7.13

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
@@ -17490,7 +17490,7 @@
17490
17490
  // higher-level mapshaper-svg.mjs (which would otherwise form a cycle).
17491
17491
 
17492
17492
  function featureHasSvgSymbol(d) {
17493
- return !!(d && (d['svg-symbol'] || d.r));
17493
+ return !!(d && (d['svg-symbol'] || d.r || d.icon || d['icon-size']));
17494
17494
  }
17495
17495
 
17496
17496
  function featureHasLabel(d) {
@@ -17763,6 +17763,9 @@
17763
17763
  'font-style': null,
17764
17764
  'font-stretch': null,
17765
17765
  'font-weight': null,
17766
+ icon: null,
17767
+ 'icon-color': 'color',
17768
+ 'icon-size': 'number',
17766
17769
  'label-text': null, // leaving this null
17767
17770
  'letter-spacing': 'measure',
17768
17771
  'line-height': 'measure',
@@ -18110,12 +18113,44 @@
18110
18113
  if (d['svg-symbol']) {
18111
18114
  return renderComplexSymbol(d['svg-symbol']);
18112
18115
  }
18116
+ if (featureHasIcon(d)) {
18117
+ return renderIcon(d);
18118
+ }
18113
18119
  if (d.r > 0) {
18114
18120
  return circle(d);
18115
18121
  }
18116
18122
  return empty();
18117
18123
  }
18118
18124
 
18125
+ function featureHasIcon(d) {
18126
+ return !!(d && (d.icon || d['icon-size'] || (d['icon-color'] && d.r > 0)));
18127
+ }
18128
+
18129
+ function renderIcon(d) {
18130
+ var type = d.icon || 'circle';
18131
+ var r = getIconRadius(d);
18132
+ if (r > 0 === false) return empty();
18133
+ if (type == 'circle') return circle(getIconStyleData(d, r));
18134
+ if (type == 'square') return square(getIconStyleData(d, r), 0, 0);
18135
+ if (type == 'ring') return ring(getIconStyleData(d, r), 0, 0);
18136
+ if (type == 'star') return star(getIconStyleData(d, r));
18137
+ message('Unknown icon type: ' + type);
18138
+ return empty();
18139
+ }
18140
+
18141
+ function getIconRadius(d) {
18142
+ if (d['icon-size'] > 0) return d['icon-size'] / 2;
18143
+ if (d.r > 0) return d.r;
18144
+ return 5;
18145
+ }
18146
+
18147
+ function getIconStyleData(d, r) {
18148
+ var o = utils.extend({}, d);
18149
+ o.r = r;
18150
+ o.fill = d['icon-color'] || d.fill || 'black';
18151
+ return o;
18152
+ }
18153
+
18119
18154
  function renderComplexSymbol(sym, x, y) {
18120
18155
  if (utils.isString(sym)) {
18121
18156
  sym = JSON.parse(sym);
@@ -18190,10 +18225,44 @@
18190
18225
  height: r * 2
18191
18226
  }
18192
18227
  };
18193
- applyStyleAttributes(o, 'point', d);
18228
+ applyStyleAttributes(o, 'point', d, nonCirclePointFilter);
18229
+ return o;
18230
+ }
18231
+
18232
+ function ring(d, x, y) {
18233
+ var o = circle(d, x, y);
18234
+ o.properties.fill = 'none';
18235
+ o.properties.stroke = d.fill;
18236
+ if (!o.properties['stroke-width']) {
18237
+ o.properties['stroke-width'] = 1;
18238
+ }
18194
18239
  return o;
18195
18240
  }
18196
18241
 
18242
+ function star(d) {
18243
+ var coords = getStarCoords$1(d.r);
18244
+ var o = importPolygon([coords]);
18245
+ applyStyleAttributes(o, 'point', d, nonCirclePointFilter);
18246
+ return o;
18247
+ }
18248
+
18249
+ function nonCirclePointFilter(k) {
18250
+ return k != 'r';
18251
+ }
18252
+
18253
+ function getStarCoords$1(r) {
18254
+ var coords = [];
18255
+ var innerR = r * 0.42;
18256
+ var angle, len;
18257
+ for (var i=0; i<10; i++) {
18258
+ len = i % 2 === 0 ? r : innerR;
18259
+ angle = -Math.PI / 2 + i * Math.PI / 5;
18260
+ coords.push([roundToTenths(Math.cos(angle) * len), roundToTenths(Math.sin(angle) * len)]);
18261
+ }
18262
+ coords.push(coords[0].concat());
18263
+ return coords;
18264
+ }
18265
+
18197
18266
  function line(d, x, y) {
18198
18267
  var coords, o;
18199
18268
  coords = [[x, y], [x + (d.dx || 0), y + (d.dy || 0)]];
@@ -18899,7 +18968,7 @@
18899
18968
 
18900
18969
  // just a dot, no label or icon
18901
18970
  function isSimpleCircle(rec) {
18902
- return rec && (rec.r > 0 && !rec['svg-symbol'] && !rec['label-text']);
18971
+ return rec && (rec.r > 0 && !rec['svg-symbol'] && !rec['label-text'] && !rec.icon && !rec['icon-size'] && !rec['icon-color']);
18903
18972
  }
18904
18973
 
18905
18974
  function importMultiPoint(coords, rec) {
@@ -18927,6 +18996,8 @@
18927
18996
  importPolygon: importPolygon
18928
18997
  });
18929
18998
 
18999
+ var ILLUSTRATOR_PATH_VERTEX_LIMIT = 32000;
19000
+
18930
19001
  //
18931
19002
  function exportSVG(dataset, opts) {
18932
19003
  var namespace = 'xmlns="http://www.w3.org/2000/svg"';
@@ -19091,6 +19162,7 @@ ${svg}
19091
19162
  var d = utils.defaults({layers: [lyr]}, dataset);
19092
19163
  var geojson = exportDatasetAsGeoJSON(d, opts);
19093
19164
  var features = geojson.features || geojson.geometries || (geojson.type ? [geojson] : []);
19165
+ warnIfIllustratorPathLimitExceeded(lyr, features);
19094
19166
  var children = importGeoJSONFeatures(features, opts);
19095
19167
  // Drop empty placeholder <g/> elements (features whose geometry was null in the
19096
19168
  // source data, collapsed during simplification, or otherwise produced no
@@ -19109,6 +19181,53 @@ ${svg}
19109
19181
  return children;
19110
19182
  }
19111
19183
 
19184
+ function warnIfIllustratorPathLimitExceeded(lyr, features) {
19185
+ var count = 0;
19186
+ var max = 0;
19187
+ if (lyr.geometry_type != 'polygon' && lyr.geometry_type != 'polyline') return;
19188
+ features.forEach(function(feature) {
19189
+ var geom = feature.geometry || feature;
19190
+ var n = countSvgPathVertices(geom);
19191
+ if (n > ILLUSTRATOR_PATH_VERTEX_LIMIT) {
19192
+ count++;
19193
+ max = Math.max(max, n);
19194
+ }
19195
+ });
19196
+ if (count > 0) {
19197
+ warn(utils.format(
19198
+ '%,d SVG path%s in layer "%s" contain%s more than %,d vertices; Adobe Illustrator may not import %s. The largest path has %,d vertices.',
19199
+ count,
19200
+ utils.pluralSuffix(count),
19201
+ lyr.name || '[unnamed]',
19202
+ count == 1 ? 's' : '',
19203
+ ILLUSTRATOR_PATH_VERTEX_LIMIT,
19204
+ count == 1 ? 'it' : 'them',
19205
+ max
19206
+ ));
19207
+ }
19208
+ }
19209
+
19210
+ function countSvgPathVertices(geom) {
19211
+ var coords = geom && geom.coordinates;
19212
+ if (!coords) return 0;
19213
+ if (geom.type == 'LineString') return coords.length;
19214
+ if (geom.type == 'MultiLineString' || geom.type == 'Polygon') {
19215
+ return sumPathLengths(coords);
19216
+ }
19217
+ if (geom.type == 'MultiPolygon') {
19218
+ return coords.reduce(function(sum, polygon) {
19219
+ return sum + sumPathLengths(polygon);
19220
+ }, 0);
19221
+ }
19222
+ return 0;
19223
+ }
19224
+
19225
+ function sumPathLengths(paths) {
19226
+ return paths.reduce(function(sum, path) {
19227
+ return sum + path.length;
19228
+ }, 0);
19229
+ }
19230
+
19112
19231
  function isEmptyPlaceholder(o) {
19113
19232
  return o.tag == 'g' && (!o.children || o.children.length === 0);
19114
19233
  }
@@ -19206,7 +19325,7 @@ ${svg}
19206
19325
  // TODO: set fill="none" in SVG symbols, not on the container
19207
19326
  // (setting fill=none on the container overrides the default black fill
19208
19327
  // on paths, which may alter the appearance of SVG icons loaded from external URLs).
19209
- if (lyr.geometry_type == 'polyline' || layerHasSvgSymbols(lyr)) {
19328
+ if (lyr.geometry_type == 'polyline' || layerHasSvgSymbolField(lyr)) {
19210
19329
  layerObj.properties.fill = 'none';
19211
19330
  }
19212
19331
 
@@ -19229,6 +19348,15 @@ ${svg}
19229
19348
  }
19230
19349
 
19231
19350
  function layerHasSvgSymbols(lyr) {
19351
+ return lyr.geometry_type == 'point' && lyr.data && (
19352
+ lyr.data.fieldExists('svg-symbol') ||
19353
+ lyr.data.fieldExists('icon') ||
19354
+ lyr.data.fieldExists('icon-size') ||
19355
+ (lyr.data.fieldExists('icon-color') && lyr.data.fieldExists('r'))
19356
+ );
19357
+ }
19358
+
19359
+ function layerHasSvgSymbolField(lyr) {
19232
19360
  return lyr.geometry_type == 'point' && lyr.data && lyr.data.fieldExists('svg-symbol');
19233
19361
  }
19234
19362
 
@@ -28250,7 +28378,7 @@ ${svg}
28250
28378
 
28251
28379
  };
28252
28380
 
28253
- this.getHelpMessage = function(cmdName) {
28381
+ this.getHelpLines = function(cmdName) {
28254
28382
  var helpCommands, singleCommand, lines;
28255
28383
  if (cmdName) {
28256
28384
  singleCommand = findCommandDefn(cmdName, getCommands());
@@ -28262,113 +28390,115 @@ ${svg}
28262
28390
  helpCommands = getCommands().filter(function(cmd) {return cmd.name && cmd.describe || cmd.title;});
28263
28391
  lines = getMultiCommandLines(helpCommands);
28264
28392
  }
28393
+ return lines;
28394
+ };
28265
28395
 
28266
- return formatLines(lines);
28267
-
28268
- function formatLines(lines) {
28269
- var colWidth = calcColWidth(lines);
28270
- var gutter = ' ';
28271
- var indent = runningInBrowser() ? '' : ' ';
28272
- var helpStr = lines.map(function(line) {
28273
- if (Array.isArray(line)) {
28274
- line = indent + utils.rpad(line[0], colWidth, ' ') + gutter + line[1];
28275
- }
28276
- return line;
28277
- }).join('\n');
28278
- return helpStr;
28279
- }
28280
-
28281
- function getSingleCommandLines(cmd) {
28282
- var lines = [];
28283
- var options = [];
28284
- cmd.options.forEach(function(opt) {
28285
- options = options.concat(getOptionLines(opt));
28286
- });
28396
+ this.getHelpMessage = function(cmdName) {
28397
+ return formatLines(this.getHelpLines(cmdName));
28398
+ };
28287
28399
 
28288
- lines.push('COMMAND', getCommandLine(cmd));
28289
- if (options.length > 0) {
28290
- lines.push('', 'OPTIONS');
28291
- lines = lines.concat(options);
28400
+ function formatLines(lines) {
28401
+ var colWidth = calcColWidth(lines);
28402
+ var gutter = ' ';
28403
+ var indent = runningInBrowser() ? '' : ' ';
28404
+ var helpStr = lines.map(function(line) {
28405
+ if (Array.isArray(line)) {
28406
+ line = indent + utils.rpad(line[0], colWidth, ' ') + gutter + line[1];
28292
28407
  }
28408
+ return line;
28409
+ }).join('\n');
28410
+ return helpStr;
28411
+ }
28293
28412
 
28294
- // examples
28295
- if (cmd.examples) {
28296
- lines.push('', 'EXAMPLE' + (cmd.examples.length > 1 ? 'S' : ''));
28297
- cmd.examples.forEach(function(ex, i) {
28298
- if (i > 0) lines.push('');
28299
- ex.split('\n').forEach(function(line, i) {
28300
- lines.push(' ' + line);
28301
- });
28302
- });
28303
- }
28304
- return lines;
28413
+ function getSingleCommandLines(cmd) {
28414
+ var lines = [];
28415
+ var options = [];
28416
+ cmd.options.forEach(function(opt) {
28417
+ options = options.concat(getOptionLines(opt));
28418
+ });
28419
+
28420
+ lines.push('COMMAND', getCommandLine(cmd));
28421
+ if (options.length > 0) {
28422
+ lines.push('', 'OPTIONS');
28423
+ lines = lines.concat(options);
28305
28424
  }
28306
28425
 
28307
- function getOptionLines(opt, cmd) {
28308
- var lines = [];
28309
- var description = opt.describe;
28310
- var label;
28311
- if (!description) ; else if (opt.label) {
28312
- lines.push([opt.label, description]);
28313
- } else if (opt.DEFAULT) {
28314
- label = opt.name + '=';
28315
- lines.push(['<' + opt.name + '>', 'shortcut for ' + label]);
28316
- lines.push([label, description]);
28317
- } else {
28318
- label = opt.name;
28319
- if (opt.alias) label += ', ' + opt.alias;
28320
- if (opt.type != 'flag' && !opt.assign_to) label += '=';
28321
- lines.push([label, description]);
28322
- }
28323
- return lines;
28426
+ // examples
28427
+ if (cmd.examples) {
28428
+ lines.push('', 'EXAMPLE' + (cmd.examples.length > 1 ? 'S' : ''));
28429
+ cmd.examples.forEach(function(ex, i) {
28430
+ if (i > 0) lines.push('');
28431
+ ex.split('\n').forEach(function(line, i) {
28432
+ lines.push(' ' + line);
28433
+ });
28434
+ });
28324
28435
  }
28436
+ return lines;
28437
+ }
28325
28438
 
28326
- function getCommandLine(cmd) {
28327
- var name = cmd.name ? "-" + cmd.name : '';
28328
- if (cmd.alias) name += ', -' + cmd.alias;
28329
- return [name, cmd.describe || '(undocumented command)'];
28439
+ function getOptionLines(opt, cmd) {
28440
+ var lines = [];
28441
+ var description = opt.describe;
28442
+ var label;
28443
+ if (!description) ; else if (opt.label) {
28444
+ lines.push([opt.label, description]);
28445
+ } else if (opt.DEFAULT) {
28446
+ label = opt.name + '=';
28447
+ lines.push(['<' + opt.name + '>', 'shortcut for ' + label]);
28448
+ lines.push([label, description]);
28449
+ } else {
28450
+ label = opt.name;
28451
+ if (opt.alias) label += ', ' + opt.alias;
28452
+ if (opt.type != 'flag' && !opt.assign_to) label += '=';
28453
+ lines.push([label, description]);
28330
28454
  }
28455
+ return lines;
28456
+ }
28331
28457
 
28332
- function getMultiCommandLines(commands) {
28333
- var lines = [];
28334
- // usage
28335
- if (_usage) lines.push(_usage);
28458
+ function getCommandLine(cmd) {
28459
+ var name = cmd.name ? "-" + cmd.name : '';
28460
+ if (cmd.alias) name += ', -' + cmd.alias;
28461
+ return [name, cmd.describe || '(undocumented command)'];
28462
+ }
28336
28463
 
28337
- // list of commands
28338
- commands.forEach(function(cmd) {
28339
- if (cmd.title) {
28340
- lines.push('', cmd.title);
28341
- } else {
28342
- lines.push(getCommandLine(cmd));
28343
- }
28344
- });
28464
+ function getMultiCommandLines(commands) {
28465
+ var lines = [];
28466
+ // usage
28467
+ if (_usage) lines.push(_usage);
28345
28468
 
28346
- // examples
28347
- if (_examples.length > 0) {
28348
- lines.push('', 'Examples');
28349
- _examples.forEach(function(str) {
28350
- lines.push('', str);
28351
- });
28469
+ // list of commands
28470
+ commands.forEach(function(cmd) {
28471
+ if (cmd.title) {
28472
+ lines.push('', cmd.title);
28473
+ } else {
28474
+ lines.push(getCommandLine(cmd));
28352
28475
  }
28476
+ });
28353
28477
 
28354
- // note
28355
- if (_note) {
28356
- lines.push('', _note);
28357
- }
28358
- return lines;
28478
+ // examples
28479
+ if (_examples.length > 0) {
28480
+ lines.push('', 'Examples');
28481
+ _examples.forEach(function(str) {
28482
+ lines.push('', str);
28483
+ });
28359
28484
  }
28360
28485
 
28361
-
28362
- function calcColWidth(lines) {
28363
- var w = 0;
28364
- lines.forEach(function(line) {
28365
- if (Array.isArray(line)) {
28366
- w = Math.max(w, line[0].length);
28367
- }
28368
- });
28369
- return w;
28486
+ // note
28487
+ if (_note) {
28488
+ lines.push('', _note);
28370
28489
  }
28371
- };
28490
+ return lines;
28491
+ }
28492
+
28493
+ function calcColWidth(lines) {
28494
+ var w = 0;
28495
+ lines.forEach(function(line) {
28496
+ if (Array.isArray(line)) {
28497
+ w = Math.max(w, line[0].length);
28498
+ }
28499
+ });
28500
+ return w;
28501
+ }
28372
28502
 
28373
28503
  function getCommands() {
28374
28504
  return _commands.map(function(cmd) {
@@ -30488,6 +30618,15 @@ ${svg}
30488
30618
  .option('r', {
30489
30619
  describe: 'symbol radius (set this to export points as circles)',
30490
30620
  })
30621
+ .option('icon', {
30622
+ describe: 'point icon shape; one of: circle, square, ring, star'
30623
+ })
30624
+ .option('icon-size', {
30625
+ describe: 'point icon size in pixels'
30626
+ })
30627
+ .option('icon-color', {
30628
+ describe: 'point icon color (defaults to fill color, then black)'
30629
+ })
30491
30630
  .option('label-text', {
30492
30631
  describe: 'label text (set this to export points as labels)'
30493
30632
  })
@@ -44055,7 +44194,14 @@ ${svg}
44055
44194
  }]
44056
44195
  };
44057
44196
  }
44058
- message(formatInfo(arr));
44197
+ if (runningInBrowser()) {
44198
+ message({
44199
+ type: 'mapshaper-console-info',
44200
+ layers: arr
44201
+ });
44202
+ } else {
44203
+ message(formatInfo(arr));
44204
+ }
44059
44205
  };
44060
44206
 
44061
44207
  cmd.printInfo = cmd.info; // old name
@@ -49377,8 +49523,15 @@ ${svg}
49377
49523
  }
49378
49524
 
49379
49525
  cmd.printHelp = function(opts) {
49380
- var str = getOptionParser().getHelpMessage(opts.command);
49381
- print(str);
49526
+ var parser = getOptionParser();
49527
+ if (runningInBrowser()) {
49528
+ message({
49529
+ type: 'mapshaper-console-help',
49530
+ lines: parser.getHelpLines(opts.command)
49531
+ });
49532
+ } else {
49533
+ print(parser.getHelpMessage(opts.command));
49534
+ }
49382
49535
  };
49383
49536
 
49384
49537
  function stopJob(job) {
@@ -55528,7 +55681,7 @@ ${svg}
55528
55681
  });
55529
55682
  }
55530
55683
 
55531
- var version = "0.7.12";
55684
+ var version = "0.7.13";
55532
55685
 
55533
55686
  // Parse command line args into commands and run them
55534
55687
  // 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.7.12",
3
+ "version": "0.7.13",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
package/www/index.html CHANGED
@@ -68,7 +68,7 @@
68
68
  <div class="page-header">
69
69
  <div class="mapshaper-logo">map<span class="logo-highlight">shaper</span></div>
70
70
 
71
- <div class="layer-control-btn icon-duo"><span class="btn header-btn layer-name"></span></div>
71
+ <div class="layer-control-btn"><span class="active-layer-label btn" role="button" tabindex="0" aria-label="Open layers panel"></span></div>
72
72
 
73
73
  <div class="simplify-control-wrapper"><div class="simplify-control"><div class="header-btn btn simplify-settings-btn">Settings</div>
74
74
  <div class="slider">
@@ -116,32 +116,6 @@
116
116
  </div>
117
117
  </div>
118
118
 
119
- <div class="layer-control main-area popup-dialog">
120
- <div class="info-box">
121
- <div class="info-box-scrolled">
122
- <div class="layer-menu">
123
- <h3>Layers</h3>
124
- <div class="pin-all pinnable">
125
- <img class="eye-btn black-eye" src="images/eye.png" alt="">
126
- <img class="eye-btn green-eye" src="images/eye2.png" alt="">
127
- </div>
128
- <div class="layer-list"></div>
129
- <!-- <h4>Sources</h4> -->
130
- <div class="no-layer-note">No data has been added</div>
131
- <div class="source-file-section">
132
- <h4>Source files</h4>
133
- <div class="file-list"></div>
134
- </div>
135
- <div>
136
- <div id="add-file-btn" class="dialog-btn btn">Add files</div>
137
- <div id="add-empty-btn" class="dialog-btn btn">Add empty layer</div>
138
- </div>
139
- </div>
140
- </div>
141
- </div>
142
- </div>
143
-
144
-
145
119
  <div class="box-tool-options sidebar-buttons">
146
120
  <div>
147
121
  <div class="select-btn btn sidebar-btn">Select</div>
@@ -367,11 +341,35 @@ encoding=big5</span>. Click to see all options.</div></div></div>
367
341
  <!-- TODO: remove #mshp-main-page without causing the map to jitter when resized -->
368
342
  <div id="mshp-main-page">
369
343
 
370
- <div class="console main-area console-area">
344
+ <div class="layer-control main-area layer-area sidebar-panel">
345
+ <div class="info-box">
346
+ <div class="info-box-scrolled">
347
+ <div class="layer-menu">
348
+ <div class="layer-add-links">
349
+ <span id="add-file-btn" class="layer-menu-link">Add files</span><span class="layer-menu-link-separator">&nbsp;&nbsp;·&nbsp;&nbsp;</span><span id="add-empty-btn" class="layer-menu-link">Add empty layer</span>
350
+ </div>
351
+ <div class="layer-item">
352
+ <h3>Layers</h3>
353
+ <div class="pin-all pinnable">
354
+ <img class="eye-btn black-eye" src="images/eye.png" alt="">
355
+ <img class="eye-btn green-eye" src="images/eye2.png" alt="">
356
+ </div>
357
+ </div>
358
+ <div class="layer-list"></div>
359
+ <div class="no-layer-note">No data has been added</div>
360
+ </div>
361
+ </div>
362
+ </div>
363
+ </div>
364
+ <div class="console main-area console-area sidebar-panel">
371
365
  <div class="console-window"><div class="console-buffer selectable"></div></div>
372
366
  </div>
367
+ <div class="sidebar-resize-handle" role="separator" aria-orientation="vertical" aria-label="Resize sidebar"></div>
368
+ <div class="sidebar-tabs">
369
+ <div class="sidebar-tab layer-tab" role="button" tabindex="0" aria-label="Toggle layers panel" aria-expanded="false">Layers</div>
370
+ <div class="sidebar-tab console-tab console-btn" role="button" tabindex="0" aria-label="Toggle console" aria-expanded="false">Console</div>
371
+ </div>
373
372
  <div class="mshp-main-map main-area map-area">
374
- <div class="console-tab console-btn" role="button" tabindex="0" aria-label="Toggle console">Console</div>
375
373
  <div class="intersection-display">
376
374
  <span class="intersection-count">0 line intersections</span>
377
375
  <div class="repair-btn text-btn colored-text">Repair</div>