mapshaper 0.5.91 → 0.5.92

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/bin/mapshaper-gui CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  var defaultPort = 5555,
4
- program = require('commander')
4
+ commander = require('commander'),
5
+ program = new commander.Command()
5
6
  .name('mapshaper-gui')
6
7
  .usage('[options] [file ...]')
7
8
  .option('-p, --port <port>', 'http port of server on localhost', defaultPort)
@@ -10,10 +11,13 @@ var defaultPort = 5555,
10
11
  .option('-f, --force-save', 'allow overwriting input files with output files')
11
12
  .option('-a, --display-all', 'turn on visibility of all layers')
12
13
  .option('-n, --name <name(s)>', 'rename input layer or layers')
14
+ .option('-c, --commands <string>', 'console commands to run initially')
13
15
  .option('-t, --target <name>', 'name of layer to select initially')
16
+ .addOption(new commander.Option('-b, --blurb <text>',
17
+ 'replace the default blurb on the import screen').hideHelp())
14
18
  .helpOption('-h, --help', 'show this help message')
15
19
  .version(require('../package.json').version)
16
- .parse(),
20
+ .parse(process.argv),
17
21
  opts = program.opts(),
18
22
  http = require("http"),
19
23
  path = require("path"),
@@ -26,7 +30,6 @@ var defaultPort = 5555,
26
30
  dataFiles = expandShapefiles(program.args),
27
31
  probeCount = 0,
28
32
  sessionId = null;
29
-
30
33
  validateFiles(dataFiles);
31
34
 
32
35
  process.on('uncaughtException', function(err) {
@@ -204,12 +207,16 @@ function validateOutputFile(file) {
204
207
  }
205
208
 
206
209
  function getManifestJS(files, opts) {
207
- var o = {files: files};
208
- if (opts.target) o.target = opts.target;
209
- if (opts.directSave) o.allow_saving = true;
210
- if (opts.displayAll) o.display_all = true;
211
- if (opts.quickView) o.quick_view = true;
212
- if (opts.name) o.name = opts.name;
210
+ var o = {
211
+ files: files,
212
+ target: opts.target,
213
+ allow_saving: opts.directSave,
214
+ display_all: opts.displayAll,
215
+ quick_view: opts.quickView,
216
+ name: opts.name,
217
+ commands: opts.commands,
218
+ blurb: opts.blurb
219
+ };
213
220
  return "mapshaper.manifest = " + JSON.stringify(o) + ";\n";
214
221
  }
215
222
 
package/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.5.88";
3
+ var VERSION = "0.5.91";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -2158,6 +2158,7 @@
2158
2158
  function getPointToPathInfo(px, py, ids, arcs) {
2159
2159
  var iter = arcs.getShapeIter(ids);
2160
2160
  var pPathSq = Infinity;
2161
+ var arcId;
2161
2162
  var ax, ay, bx, by, axmin, aymin, bxmin, bymin, pabSq;
2162
2163
  if (iter.hasNext()) {
2163
2164
  ax = axmin = bxmin = iter.x;
@@ -2169,6 +2170,7 @@
2169
2170
  pabSq = pointSegDistSq2(px, py, ax, ay, bx, by);
2170
2171
  if (pabSq < pPathSq) {
2171
2172
  pPathSq = pabSq;
2173
+ arcId = iter._ids[iter._i]; // kludge
2172
2174
  axmin = ax;
2173
2175
  aymin = ay;
2174
2176
  bxmin = bx;
@@ -2180,7 +2182,8 @@
2180
2182
  if (pPathSq == Infinity) return {distance: Infinity};
2181
2183
  return {
2182
2184
  segment: [[axmin, aymin], [bxmin, bymin]],
2183
- distance: Math.sqrt(pPathSq)
2185
+ distance: Math.sqrt(pPathSq),
2186
+ arcId: arcId
2184
2187
  };
2185
2188
  }
2186
2189
 
@@ -2188,11 +2191,20 @@
2188
2191
  // Return unsigned distance of a point to the nearest point on a polygon or polyline path
2189
2192
  //
2190
2193
  function getPointToShapeDistance(x, y, shp, arcs) {
2191
- var minDist = (shp || []).reduce(function(minDist, ids) {
2192
- var pathDist = getPointToPathDistance(x, y, ids, arcs);
2193
- return Math.min(minDist, pathDist);
2194
- }, Infinity);
2195
- return minDist;
2194
+ var info = getPointToShapeInfo(x, y, shp, arcs);
2195
+ return info ? info.distance : Infinity;
2196
+ }
2197
+
2198
+ function getPointToShapeInfo(x, y, shp, arcs) {
2199
+ return (shp || []).reduce(function(memo, ids) {
2200
+ var pathInfo = getPointToPathInfo(x, y, ids, arcs);
2201
+ if (!memo || pathInfo.distance < memo.distance) return pathInfo;
2202
+ return memo;
2203
+ }, null) || {
2204
+ distance: Infinity,
2205
+ arcId: -1,
2206
+ segment: null
2207
+ };
2196
2208
  }
2197
2209
 
2198
2210
  // @ids array of arc ids
@@ -2277,6 +2289,7 @@
2277
2289
  getPointToPathDistance: getPointToPathDistance,
2278
2290
  getPointToPathInfo: getPointToPathInfo,
2279
2291
  getPointToShapeDistance: getPointToShapeDistance,
2292
+ getPointToShapeInfo: getPointToShapeInfo,
2280
2293
  getAvgPathXY: getAvgPathXY,
2281
2294
  getMaxPath: getMaxPath,
2282
2295
  countVerticesInPath: countVerticesInPath,
@@ -5377,6 +5390,10 @@
5377
5390
  };
5378
5391
  };
5379
5392
 
5393
+ this.getVertex2 = function(i) {
5394
+ return [_xx[i], _yy[i]];
5395
+ };
5396
+
5380
5397
  // @nth: index of vertex. ~(idx) starts from the opposite endpoint
5381
5398
  this.indexOfVertex = function(arcId, nth) {
5382
5399
  var absId = arcId < 0 ? ~arcId : arcId,
@@ -27167,7 +27184,7 @@ ${svg}
27167
27184
  }
27168
27185
 
27169
27186
  function samePoint(a, b) {
27170
- return a[0] === b[0] && a[1] === b[1];
27187
+ return a && b && a[0] === b[0] && a[1] === b[1];
27171
27188
  }
27172
27189
 
27173
27190
  function isClosedPath(arr) {
@@ -27781,11 +27798,15 @@ ${svg}
27781
27798
  }
27782
27799
 
27783
27800
  function getCategoricalColorScheme(name, n) {
27801
+ var colors;
27784
27802
  initSchemes();
27785
- if (index.categorical.includes(name) === false) {
27786
- stop(name, 'is not a categorical color scheme');
27803
+ if (!isColorSchemeName(name)) {
27804
+ stop('Unknown color scheme name:', name);
27805
+ } else if (isCategoricalColorScheme(name)) {
27806
+ colors = ramps[name] || require('d3-scale-chromatic')['scheme' + name];
27807
+ } else {
27808
+ colors = getColorRamp(name, n);
27787
27809
  }
27788
- var colors = ramps[name] || require('d3-scale-chromatic')['scheme' + name];
27789
27810
  if (n > colors.length) {
27790
27811
  stop(name, 'does not contain', n, 'colors');
27791
27812
  }
@@ -27798,6 +27819,11 @@ ${svg}
27798
27819
  index.diverging.includes(name) || index.rainbow.includes(name);
27799
27820
  }
27800
27821
 
27822
+ function isCategoricalColorScheme(name) {
27823
+ initSchemes();
27824
+ return index.categorical.includes(name);
27825
+ }
27826
+
27801
27827
  function getColorRamp(name, n, stops) {
27802
27828
  initSchemes();
27803
27829
  var lib = require('d3-scale-chromatic');
@@ -28287,7 +28313,7 @@ ${svg}
28287
28313
  };
28288
28314
  }
28289
28315
 
28290
- function getSequentialClassifier$1(classValues, nullValue, dataValues, opts) {
28316
+ function getSequentialClassifier$1(classValues, nullValue, dataValues, method, opts) {
28291
28317
  var numValues = classValues.length;
28292
28318
  var numBuckets = opts.continuous ? numValues - 1 : numValues;
28293
28319
 
@@ -28295,7 +28321,6 @@ ${svg}
28295
28321
  // discreetly classed values
28296
28322
  var numBreaks = numBuckets - 1;
28297
28323
  var round = opts.precision ? getRoundingFunction(opts.precision) : null;
28298
- var method = opts.method || 'quantile';
28299
28324
  var breaks, classifier, dataToClass, classToValue;
28300
28325
 
28301
28326
  if (round) {
@@ -28900,34 +28925,35 @@ ${svg}
28900
28925
  var opts = optsArg || {};
28901
28926
  var records = lyr.data && lyr.data.getRecords();
28902
28927
  var nullValue = opts.null_value || null;
28903
- var looksLikeColors = !!opts.colors || !!opts.color_scheme;
28928
+ var valuesAreColors = !!opts.colors || !!opts.color_scheme;
28904
28929
  var colorScheme;
28905
- var classValues, classifyByValue, classifyById;
28906
- var numBuckets, numValues;
28930
+ var values, classifyByValue, classifyById;
28931
+ var numClasses, numValues;
28907
28932
  var dataField, outputField;
28933
+ var method;
28908
28934
 
28909
28935
  // validate explicitly set classes
28910
28936
  if (opts.classes) {
28911
28937
  if (!utils.isInteger(opts.classes) || opts.classes > 1 === false) {
28912
28938
  stop('Invalid number of classes:', opts.classes, '(expected a value greater than 1)');
28913
28939
  }
28914
- numBuckets = opts.classes;
28940
+ numClasses = opts.classes;
28915
28941
  }
28916
28942
 
28917
28943
  // TODO: better validation of breaks values
28918
28944
  if (opts.breaks) {
28919
- numBuckets = opts.breaks.length + 1;
28945
+ numClasses = opts.breaks.length + 1;
28920
28946
  }
28921
28947
 
28922
28948
  if (opts.index_field) {
28923
28949
  dataField = opts.index_field;
28924
- if (numBuckets > 0 === false) {
28950
+ if (numClasses > 0 === false) {
28925
28951
  stop('The index-field= option requires the classes= option to be set');
28926
28952
  }
28927
28953
  // You can't infer the number of classes by looking at index values;
28928
28954
  // this can cause unwanted interpolation if one or more values are
28929
28955
  // not present in the index field
28930
- // numBuckets = validateClassIndexField(records, opts.index_field);
28956
+ // numClasses = validateClassIndexField(records, opts.index_field);
28931
28957
 
28932
28958
  } else if (opts.field) {
28933
28959
  dataField = opts.field;
@@ -28938,7 +28964,19 @@ ${svg}
28938
28964
  opts.categories = getUniqFieldValues(records, dataField);
28939
28965
  }
28940
28966
 
28941
- if (opts.method == 'non-adjacent') {
28967
+ // get classification method
28968
+ //
28969
+ if (opts.method) {
28970
+ method = opts.method;
28971
+ } else if (opts.categories) {
28972
+ method = 'categorical';
28973
+ } else if (opts.index_field) {
28974
+ method = 'indexed';
28975
+ } else {
28976
+ method = 'quantile'; // TODO: validate data field
28977
+ }
28978
+
28979
+ if (method == 'non-adjacent') {
28942
28980
  if (lyr.geometry_type != 'polygon') {
28943
28981
  stop('The non-adjacent option requires a polygon layer');
28944
28982
  }
@@ -28951,8 +28989,8 @@ ${svg}
28951
28989
  requireDataField(lyr.data, dataField);
28952
28990
  }
28953
28991
 
28954
- if (numBuckets) {
28955
- numValues = opts.continuous ? numBuckets + 1 : numBuckets;
28992
+ if (numClasses) {
28993
+ numValues = opts.continuous ? numClasses + 1 : numClasses;
28956
28994
  }
28957
28995
 
28958
28996
  // support both deprecated color-scheme= option and colors=<color-scheme> syntax
@@ -28967,39 +29005,44 @@ ${svg}
28967
29005
  opts.colors.forEach(parseColor); // validate colors -- error if unparsable
28968
29006
  }
28969
29007
 
29008
+ /// get values (usually colors)
29009
+ ///
28970
29010
  if (colorScheme) {
28971
- // using a named color scheme: generate a ramp
29011
+ if (method == 'non-adjacent') {
29012
+ numClasses = numValues = numClasses || 5;
29013
+ values = getCategoricalColorScheme(colorScheme, numValues);
29014
+
29015
+ } else if (method == 'categorical') {
29016
+ values = getCategoricalColorScheme(colorScheme, opts.categories.length);
29017
+ numClasses = numValues = values.length;
28972
29018
 
28973
- if (opts.categories) {
28974
- classValues = getCategoricalColorScheme(colorScheme, opts.categories.length);
28975
- numBuckets = numValues = classValues.length;
28976
29019
  } else {
28977
- if (!numBuckets) {
29020
+ if (!numClasses) {
28978
29021
  // stop('color-scheme= option requires classes= or breaks=');
28979
- numBuckets = 4; // use a default number of classes
28980
- numValues = opts.continuous ? numBuckets + 1 : numBuckets;
29022
+ numClasses = 4; // use a default number of classes
29023
+ numValues = opts.continuous ? numClasses + 1 : numClasses;
28981
29024
  }
28982
- classValues = getColorRamp(colorScheme, numValues, opts.stops);
29025
+ values = getColorRamp(colorScheme, numValues, opts.stops);
28983
29026
  }
28984
29027
 
28985
29028
  } else if (opts.colors || opts.values) {
28986
- classValues = opts.values ? parseValues(opts.values) : opts.colors;
29029
+ values = opts.values ? parseValues(opts.values) : opts.colors;
28987
29030
  if (!numValues) {
28988
- numValues = classValues.length;
29031
+ numValues = values.length;
28989
29032
  }
28990
- if ((classValues.length != numValues || opts.stops) && numValues > 1) {
29033
+ if ((values.length != numValues || opts.stops) && numValues > 1) {
28991
29034
  // TODO: handle numValues == 1
28992
29035
  // TODO: check for non-interpolatable value types (e.g. boolean, text)
28993
- classValues = interpolateValuesToClasses(classValues, numValues, opts.stops);
29036
+ values = interpolateValuesToClasses(values, numValues, opts.stops);
28994
29037
  }
28995
29038
 
28996
29039
  } else if (numValues > 1) {
28997
29040
  // no values were given: assign indexes for each class
28998
- classValues = getIndexValues(numValues);
29041
+ values = getIndexValues(numValues);
28999
29042
  nullValue = -1;
29000
29043
  }
29001
29044
 
29002
- if (looksLikeColors) {
29045
+ if (valuesAreColors) {
29003
29046
  nullValue = nullValue || '#eee';
29004
29047
  }
29005
29048
 
@@ -29008,24 +29051,24 @@ ${svg}
29008
29051
  }
29009
29052
 
29010
29053
  if (opts.invert) {
29011
- classValues = classValues.concat().reverse();
29054
+ values = values.concat().reverse();
29012
29055
  }
29013
29056
 
29014
- if (looksLikeColors) {
29015
- message('Colors:', formatValuesForLogging(classValues));
29057
+ if (valuesAreColors) {
29058
+ message('Colors:', formatValuesForLogging(values));
29016
29059
  }
29017
29060
 
29018
29061
  // get a function to convert input data to class indexes
29019
29062
  //
29020
- if (opts.method == 'non-adjacent') {
29021
- classifyById = getNonAdjacentClassifier(lyr, dataset, classValues);
29063
+ if (method == 'non-adjacent') {
29064
+ classifyById = getNonAdjacentClassifier(lyr, dataset, values);
29022
29065
  } else if (opts.index_field) {
29023
29066
  // data is pre-classified... just read the index from a field
29024
- classifyByValue = getIndexedClassifier(classValues, nullValue, opts);
29025
- } else if (opts.categories) {
29026
- classifyByValue = getCategoricalClassifier(classValues, nullValue, opts);
29067
+ classifyByValue = getIndexedClassifier(values, nullValue, opts);
29068
+ } else if (method == 'categorical') {
29069
+ classifyByValue = getCategoricalClassifier(values, nullValue, opts);
29027
29070
  } else {
29028
- classifyByValue = getSequentialClassifier$1(classValues, nullValue, getFieldValues(records, dataField), opts);
29071
+ classifyByValue = getSequentialClassifier$1(values, nullValue, getFieldValues(records, dataField), method, opts);
29029
29072
  }
29030
29073
 
29031
29074
  if (classifyByValue) {
@@ -29038,7 +29081,7 @@ ${svg}
29038
29081
 
29039
29082
  // get the name of the output field
29040
29083
  //
29041
- if (looksLikeColors) {
29084
+ if (valuesAreColors) {
29042
29085
  outputField = lyr.geometry_type == 'polyline' ? 'stroke' : 'fill';
29043
29086
  } else {
29044
29087
  outputField = 'class';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.5.91",
3
+ "version": "0.5.92",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -40,7 +40,7 @@
40
40
  "!.DS_Store"
41
41
  ],
42
42
  "dependencies": {
43
- "commander": "^5.1.0",
43
+ "commander": "7.0.0",
44
44
  "cookies": "^0.8.0",
45
45
  "d3-color": "2.0.0",
46
46
  "d3-scale-chromatic": "2.0.0",
package/www/index.html CHANGED
@@ -201,7 +201,7 @@ a smoother appearance.</div></div></div></div>
201
201
 
202
202
  <div id="splash-screen" class="main-area">
203
203
  <div>
204
- <h3>Mapshaper is an editor for map data</h3>
204
+ <h3 id="splash-screen-blurb">Mapshaper is an editor for map data</h3>
205
205
  </div>
206
206
  <div id="drop-areas" class="drop-area-wrapper main-area">
207
207