mapshaper 0.5.71 → 0.5.72

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/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ v0.5.72
2
+ * Improved performance of non-adjacent polygon coloring using DSATUR algorithm.
3
+
4
+ v0.5.71
5
+ * Added -classify non-adjacent option, for assigning non-adjacent colors to a polygon layer in a randomish pattern.
6
+
1
7
  v0.5.70
2
8
  * Added -join duplication option, which duplicates features in the target layer when many-to-one joins occur.
3
9
 
@@ -23,7 +29,7 @@ v0.5.64
23
29
  * Bug fixes
24
30
 
25
31
  v0.5.63
26
- * Added -o decimal-comma function, for exporting CSV numbers with decimal commas.
32
+ * Added -o decimal-comma option, for exporting CSV numbers with decimal commas.
27
33
  * Fix for issue #497 (error erasing with overlapping polygons).
28
34
 
29
35
  v0.5.62
package/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.5.69";
3
+ var VERSION = "0.5.72";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -28208,6 +28208,8 @@ ${svg}
28208
28208
  findPairsOfNeighbors: findPairsOfNeighbors
28209
28209
  });
28210
28210
 
28211
+ var BALANCE_COLORS = true;
28212
+
28211
28213
  function getNonAdjacentClassifier(lyr, dataset, colors) {
28212
28214
  requirePolygonLayer(lyr);
28213
28215
  var getNeighbors = getNeighborLookupFunction(lyr, dataset.arcs);
@@ -28215,25 +28217,30 @@ ${svg}
28215
28217
  var data = utils.range(getFeatureCount(lyr)).map(function(shpId) {
28216
28218
  var nabes = getNeighbors(shpId) || [];
28217
28219
  return {
28220
+ // id: shpId,
28218
28221
  nabes: nabes,
28219
- n: nabes.length,
28220
- colorId: -1
28222
+ colorId: -1,
28223
+ nabeColors: [],
28224
+ uncolored: nabes.length,
28225
+ saturation: 0,
28226
+ saturation2: 0
28221
28227
  };
28222
28228
  });
28223
28229
  var getSortedColorIds = getUpdateFunction(colors.length);
28224
28230
  var colorIds = getSortedColorIds();
28225
28231
  // Sort adjacency data by number of neighbors in descending order
28226
- var sorted = data.concat();
28227
- utils.sortOn(sorted, 'n', false);
28232
+ var iter = getNodeIterator(data);
28228
28233
  // Assign colors, starting with polygons with the largest number of neighbors
28229
- sorted.forEach(function(d) {
28234
+ iter.forEach(function(d) {
28230
28235
  var colorId = pickColor(d, data, colorIds);
28231
28236
  if (colorId == -1) {
28232
28237
  errorCount++;
28233
28238
  colorId = colorIds[0];
28234
28239
  }
28235
28240
  d.colorId = colorId;
28236
- colorIds = getSortedColorIds(colorId);
28241
+ if (BALANCE_COLORS) {
28242
+ colorIds = getSortedColorIds(colorId);
28243
+ }
28237
28244
  });
28238
28245
 
28239
28246
  if (errorCount > 0) {
@@ -28244,6 +28251,59 @@ ${svg}
28244
28251
  };
28245
28252
  }
28246
28253
 
28254
+ function getNodeIterator(data) {
28255
+ var sorted = data.concat();
28256
+ utils.sortOn(sorted, 'uncolored', true);
28257
+ function forEach(cb) {
28258
+ var item;
28259
+ while(sorted.length > 0) {
28260
+ item = sorted.pop();
28261
+ cb(item);
28262
+ updateNeighbors(item, sorted, data);
28263
+ }
28264
+ }
28265
+
28266
+ return {
28267
+ forEach: forEach
28268
+ };
28269
+ }
28270
+
28271
+ function updateNeighbors(item, sorted, data) {
28272
+ var nabe;
28273
+ var ids = item.nabes;
28274
+ for (var i=0; i<ids.length; i++) {
28275
+ nabe = data[ids[i]];
28276
+ if (nabe.colorId > -1) continue;
28277
+ updateNeighbor(nabe, item.colorId, sorted);
28278
+ }
28279
+ }
28280
+
28281
+ function updateNeighbor(a, colorId, sorted) {
28282
+ var i = sorted.indexOf(a); // could optimize with a binary search
28283
+ var n = sorted.length;
28284
+ var b;
28285
+ if (i == -1) {
28286
+ error('Indexing error');
28287
+ }
28288
+ a.uncolored--;
28289
+ a.saturation2++;
28290
+ if (!a.nabeColors.includes(colorId)) {
28291
+ a.saturation++;
28292
+ a.nabeColors.push(colorId);
28293
+ }
28294
+ // insertion sort with a stopping condition
28295
+ while (++i < n) {
28296
+ b = sorted[i];
28297
+ // standard dsatur
28298
+ if (a.saturation < b.saturation || a.saturation == b.saturation && a.uncolored > b.uncolored) break;
28299
+ // based on 4-color tests with counties and zipcodes, this condition adds a bit of strength
28300
+ if (a.saturation == b.saturation && a.uncolored == b.uncolored && a.saturation2 < b.saturation2) break; // 332
28301
+ sorted[i-1] = b;
28302
+ sorted[i] = a;
28303
+ }
28304
+ }
28305
+
28306
+
28247
28307
  // Pick the id of a color that is not shared with a neighboring polygon
28248
28308
  function pickColor(d, data, colorIds) {
28249
28309
  var candidateId;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.5.71",
3
+ "version": "0.5.72",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -24,8 +24,8 @@
24
24
  "scripts": {
25
25
  "test": "mocha -r esm --parallel --jobs 4 --check-leaks -R dot",
26
26
  "build": "rollup --config",
27
- "prepublishOnly": "npm test",
28
- "postpublish": "./release",
27
+ "prepublishOnly": "npm test; ./pre-publish",
28
+ "postpublish": "./release_web_ui; ./release_github_version",
29
29
  "browserify_old": "browserify -r sync-request -r mproj -r buffer -r iconv-lite -r fs -r flatbush -r rw -r path -r d3-scale-chromatic -r d3-color -r d3-interpolate -o www/modules.js",
30
30
  "browserify": "browserify -r sync-request -r mproj -r buffer -r iconv-lite -r fs -r flatbush -r rw -r path -r d3-scale-chromatic -r d3-color -r d3-interpolate -r kdbush -o www/modules.js",
31
31
  "watch": "rollup --config --watch",
package/www/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.5.69";
3
+ var VERSION = "0.5.72";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -28208,6 +28208,8 @@ ${svg}
28208
28208
  findPairsOfNeighbors: findPairsOfNeighbors
28209
28209
  });
28210
28210
 
28211
+ var BALANCE_COLORS = true;
28212
+
28211
28213
  function getNonAdjacentClassifier(lyr, dataset, colors) {
28212
28214
  requirePolygonLayer(lyr);
28213
28215
  var getNeighbors = getNeighborLookupFunction(lyr, dataset.arcs);
@@ -28215,25 +28217,30 @@ ${svg}
28215
28217
  var data = utils.range(getFeatureCount(lyr)).map(function(shpId) {
28216
28218
  var nabes = getNeighbors(shpId) || [];
28217
28219
  return {
28220
+ // id: shpId,
28218
28221
  nabes: nabes,
28219
- n: nabes.length,
28220
- colorId: -1
28222
+ colorId: -1,
28223
+ nabeColors: [],
28224
+ uncolored: nabes.length,
28225
+ saturation: 0,
28226
+ saturation2: 0
28221
28227
  };
28222
28228
  });
28223
28229
  var getSortedColorIds = getUpdateFunction(colors.length);
28224
28230
  var colorIds = getSortedColorIds();
28225
28231
  // Sort adjacency data by number of neighbors in descending order
28226
- var sorted = data.concat();
28227
- utils.sortOn(sorted, 'n', false);
28232
+ var iter = getNodeIterator(data);
28228
28233
  // Assign colors, starting with polygons with the largest number of neighbors
28229
- sorted.forEach(function(d) {
28234
+ iter.forEach(function(d) {
28230
28235
  var colorId = pickColor(d, data, colorIds);
28231
28236
  if (colorId == -1) {
28232
28237
  errorCount++;
28233
28238
  colorId = colorIds[0];
28234
28239
  }
28235
28240
  d.colorId = colorId;
28236
- colorIds = getSortedColorIds(colorId);
28241
+ if (BALANCE_COLORS) {
28242
+ colorIds = getSortedColorIds(colorId);
28243
+ }
28237
28244
  });
28238
28245
 
28239
28246
  if (errorCount > 0) {
@@ -28244,6 +28251,59 @@ ${svg}
28244
28251
  };
28245
28252
  }
28246
28253
 
28254
+ function getNodeIterator(data) {
28255
+ var sorted = data.concat();
28256
+ utils.sortOn(sorted, 'uncolored', true);
28257
+ function forEach(cb) {
28258
+ var item;
28259
+ while(sorted.length > 0) {
28260
+ item = sorted.pop();
28261
+ cb(item);
28262
+ updateNeighbors(item, sorted, data);
28263
+ }
28264
+ }
28265
+
28266
+ return {
28267
+ forEach: forEach
28268
+ };
28269
+ }
28270
+
28271
+ function updateNeighbors(item, sorted, data) {
28272
+ var nabe;
28273
+ var ids = item.nabes;
28274
+ for (var i=0; i<ids.length; i++) {
28275
+ nabe = data[ids[i]];
28276
+ if (nabe.colorId > -1) continue;
28277
+ updateNeighbor(nabe, item.colorId, sorted);
28278
+ }
28279
+ }
28280
+
28281
+ function updateNeighbor(a, colorId, sorted) {
28282
+ var i = sorted.indexOf(a); // could optimize with a binary search
28283
+ var n = sorted.length;
28284
+ var b;
28285
+ if (i == -1) {
28286
+ error('Indexing error');
28287
+ }
28288
+ a.uncolored--;
28289
+ a.saturation2++;
28290
+ if (!a.nabeColors.includes(colorId)) {
28291
+ a.saturation++;
28292
+ a.nabeColors.push(colorId);
28293
+ }
28294
+ // insertion sort with a stopping condition
28295
+ while (++i < n) {
28296
+ b = sorted[i];
28297
+ // standard dsatur
28298
+ if (a.saturation < b.saturation || a.saturation == b.saturation && a.uncolored > b.uncolored) break;
28299
+ // based on 4-color tests with counties and zipcodes, this condition adds a bit of strength
28300
+ if (a.saturation == b.saturation && a.uncolored == b.uncolored && a.saturation2 < b.saturation2) break; // 332
28301
+ sorted[i-1] = b;
28302
+ sorted[i] = a;
28303
+ }
28304
+ }
28305
+
28306
+
28247
28307
  // Pick the id of a color that is not shared with a neighboring polygon
28248
28308
  function pickColor(d, data, colorIds) {
28249
28309
  var candidateId;