mapshaper 0.5.68 → 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 +17 -1
- package/mapshaper.js +450 -199
- package/package.json +3 -3
- package/www/mapshaper-gui.js +18 -2
- package/www/mapshaper.js +450 -199
package/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.5.
|
|
3
|
+
var VERSION = "0.5.72";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -1167,6 +1167,10 @@
|
|
|
1167
1167
|
throw new UserError(formatLogArgs(arguments));
|
|
1168
1168
|
};
|
|
1169
1169
|
|
|
1170
|
+
var _interrupt = function() {
|
|
1171
|
+
throw new NonFatalError(formatLogArgs(arguments));
|
|
1172
|
+
};
|
|
1173
|
+
|
|
1170
1174
|
var _message = function() {
|
|
1171
1175
|
logArgs(arguments);
|
|
1172
1176
|
};
|
|
@@ -1185,10 +1189,14 @@
|
|
|
1185
1189
|
}
|
|
1186
1190
|
|
|
1187
1191
|
// Handle an error caused by invalid input or misuse of API
|
|
1188
|
-
function stop
|
|
1192
|
+
function stop() {
|
|
1189
1193
|
_stop.apply(null, utils.toArray(arguments));
|
|
1190
1194
|
}
|
|
1191
1195
|
|
|
1196
|
+
function interrupt() {
|
|
1197
|
+
_interrupt.apply(null, utils.toArray(arguments));
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1192
1200
|
// Print a status message
|
|
1193
1201
|
function message() {
|
|
1194
1202
|
_message.apply(null, messageArgs(arguments));
|
|
@@ -1228,7 +1236,9 @@
|
|
|
1228
1236
|
if (utils.isString(err)) {
|
|
1229
1237
|
err = new UserError(err);
|
|
1230
1238
|
}
|
|
1231
|
-
if (err.name == '
|
|
1239
|
+
if (err.name == 'NonFatalError') {
|
|
1240
|
+
console.error(messageArgs([err.message]).join(' '));
|
|
1241
|
+
} else if (err.name == 'UserError') {
|
|
1232
1242
|
msg = err.message;
|
|
1233
1243
|
if (!/Error/.test(msg)) {
|
|
1234
1244
|
msg = "Error: " + msg;
|
|
@@ -1248,6 +1258,12 @@
|
|
|
1248
1258
|
return err;
|
|
1249
1259
|
}
|
|
1250
1260
|
|
|
1261
|
+
function NonFatalError(msg) {
|
|
1262
|
+
var err = new Error(msg);
|
|
1263
|
+
err.name = 'NonFatalError';
|
|
1264
|
+
return err;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1251
1267
|
function formatColumns(arr, alignments) {
|
|
1252
1268
|
var widths = arr.reduce(function(memo, line) {
|
|
1253
1269
|
return line.map(function(str, i) {
|
|
@@ -1308,6 +1324,7 @@
|
|
|
1308
1324
|
loggingEnabled: loggingEnabled,
|
|
1309
1325
|
error: error,
|
|
1310
1326
|
stop: stop,
|
|
1327
|
+
interrupt: interrupt,
|
|
1311
1328
|
message: message,
|
|
1312
1329
|
setLoggingFunctions: setLoggingFunctions,
|
|
1313
1330
|
print: print,
|
|
@@ -1315,6 +1332,7 @@
|
|
|
1315
1332
|
debug: debug,
|
|
1316
1333
|
printError: printError,
|
|
1317
1334
|
UserError: UserError,
|
|
1335
|
+
NonFatalError: NonFatalError,
|
|
1318
1336
|
formatColumns: formatColumns,
|
|
1319
1337
|
formatStringsAsGrid: formatStringsAsGrid,
|
|
1320
1338
|
formatLogArgs: formatLogArgs,
|
|
@@ -14306,7 +14324,7 @@
|
|
|
14306
14324
|
joinStr = obj.tag == 'text' || obj.tag == 'tspan' ? '' : '\n';
|
|
14307
14325
|
svg += '>' + joinStr;
|
|
14308
14326
|
if (obj.value) {
|
|
14309
|
-
svg += obj.value;
|
|
14327
|
+
svg += stringEscape(obj.value);
|
|
14310
14328
|
}
|
|
14311
14329
|
if (obj.children) {
|
|
14312
14330
|
svg += obj.children.map(stringify).join(joinStr);
|
|
@@ -14329,8 +14347,13 @@
|
|
|
14329
14347
|
"'": '''
|
|
14330
14348
|
};
|
|
14331
14349
|
function stringEscape(s) {
|
|
14332
|
-
return String(s).replace(rxp, function(
|
|
14333
|
-
|
|
14350
|
+
return String(s).replace(rxp, function(match, i) {
|
|
14351
|
+
var entity = map[match];
|
|
14352
|
+
// don't replace & with &
|
|
14353
|
+
if (match == '&' && s.substr(i, entity.length) == entity) {
|
|
14354
|
+
return '&';
|
|
14355
|
+
}
|
|
14356
|
+
return entity;
|
|
14334
14357
|
});
|
|
14335
14358
|
}
|
|
14336
14359
|
|
|
@@ -18655,7 +18678,8 @@ ${svg}
|
|
|
18655
18678
|
.option('no-replace', noReplaceOpt);
|
|
18656
18679
|
|
|
18657
18680
|
parser.command('classify')
|
|
18658
|
-
.describe('apply sequential or categorical classification')
|
|
18681
|
+
// .describe('apply sequential or categorical classification')
|
|
18682
|
+
.describe('assign colors or values using one of several methods')
|
|
18659
18683
|
.option('field', {
|
|
18660
18684
|
describe: 'name of field to classify',
|
|
18661
18685
|
DEFAULT: true
|
|
@@ -18675,6 +18699,10 @@ ${svg}
|
|
|
18675
18699
|
// deprecated in favor of colors=
|
|
18676
18700
|
// describe: 'name of a predefined color scheme (see -colors command)'
|
|
18677
18701
|
})
|
|
18702
|
+
.option('non-adjacent', {
|
|
18703
|
+
describe: 'assign non-adjacent colors to a polygon layer',
|
|
18704
|
+
assign_to: 'method'
|
|
18705
|
+
})
|
|
18678
18706
|
.option('stops', {
|
|
18679
18707
|
describe: 'a pair of values (0-100) for limiting a color ramp',
|
|
18680
18708
|
type: 'numbers'
|
|
@@ -18759,7 +18787,6 @@ ${svg}
|
|
|
18759
18787
|
.option('key-last-suffix', {
|
|
18760
18788
|
describe: 'string to append to last label'
|
|
18761
18789
|
})
|
|
18762
|
-
|
|
18763
18790
|
.option('target', targetOpt);
|
|
18764
18791
|
|
|
18765
18792
|
parser.command('clean')
|
|
@@ -19168,6 +19195,14 @@ ${svg}
|
|
|
19168
19195
|
.option('target', targetOpt)
|
|
19169
19196
|
.option('no-replace', noReplaceOpt);
|
|
19170
19197
|
|
|
19198
|
+
parser.command('ignore')
|
|
19199
|
+
// .describe('stop processing if a condition is met')
|
|
19200
|
+
.option('empty', {
|
|
19201
|
+
describe: 'ignore empty files',
|
|
19202
|
+
type: 'flag'
|
|
19203
|
+
})
|
|
19204
|
+
.option('target', targetOpt);
|
|
19205
|
+
|
|
19171
19206
|
parser.command('inlay')
|
|
19172
19207
|
.describe('inscribe a polygon layer inside another polygon layer')
|
|
19173
19208
|
.option('source', {
|
|
@@ -19239,6 +19274,10 @@ ${svg}
|
|
|
19239
19274
|
// describe: 'use planar geometry when interpolating by area' // useful for testing
|
|
19240
19275
|
type: 'flag'
|
|
19241
19276
|
})
|
|
19277
|
+
.option('duplication', {
|
|
19278
|
+
describe: 'duplicate target features on many-to-one joins',
|
|
19279
|
+
type: 'flag'
|
|
19280
|
+
})
|
|
19242
19281
|
.option('string-fields', stringFieldsOpt)
|
|
19243
19282
|
.option('field-types', fieldTypesOpt)
|
|
19244
19283
|
.option('sum-fields', {
|
|
@@ -28028,25 +28067,301 @@ ${svg}
|
|
|
28028
28067
|
return maxId + 1;
|
|
28029
28068
|
}
|
|
28030
28069
|
|
|
28031
|
-
|
|
28070
|
+
// Returns a function for constructing a query function that accepts an arc id and
|
|
28071
|
+
// returns information about the polygon or polygons that use the given arc.
|
|
28072
|
+
// TODO: explain this better.
|
|
28073
|
+
//
|
|
28074
|
+
// options:
|
|
28075
|
+
// filter: optional filter function; signature: function(idA, idB or -1) : boolean
|
|
28076
|
+
// reusable: flag that lets an arc be queried multiple times.
|
|
28077
|
+
function getArcClassifier(shapes, arcs) {
|
|
28078
|
+
var opts = arguments[2] || {},
|
|
28079
|
+
useOnce = !opts.reusable,
|
|
28080
|
+
n = arcs.size(),
|
|
28081
|
+
a = new Int32Array(n),
|
|
28082
|
+
b = new Int32Array(n);
|
|
28083
|
+
|
|
28084
|
+
utils.initializeArray(a, -1);
|
|
28085
|
+
utils.initializeArray(b, -1);
|
|
28086
|
+
|
|
28087
|
+
traversePaths(shapes, function(o) {
|
|
28088
|
+
var i = absArcId(o.arcId);
|
|
28089
|
+
var shpId = o.shapeId;
|
|
28090
|
+
var aval = a[i];
|
|
28091
|
+
if (aval == -1) {
|
|
28092
|
+
a[i] = shpId;
|
|
28093
|
+
} else if (shpId < aval) {
|
|
28094
|
+
b[i] = aval;
|
|
28095
|
+
a[i] = shpId;
|
|
28096
|
+
} else {
|
|
28097
|
+
b[i] = shpId;
|
|
28098
|
+
}
|
|
28099
|
+
});
|
|
28100
|
+
|
|
28101
|
+
function classify(arcId, getKey) {
|
|
28102
|
+
var i = absArcId(arcId);
|
|
28103
|
+
var shpA = a[i];
|
|
28104
|
+
var shpB = b[i];
|
|
28105
|
+
var key;
|
|
28106
|
+
if (shpA == -1) return null;
|
|
28107
|
+
key = getKey(shpA, shpB);
|
|
28108
|
+
if (key === null || key === false) return null;
|
|
28109
|
+
if (useOnce) {
|
|
28110
|
+
// arc can only be queried once
|
|
28111
|
+
a[i] = -1;
|
|
28112
|
+
b[i] = -1;
|
|
28113
|
+
}
|
|
28114
|
+
// use optional filter to exclude some arcs
|
|
28115
|
+
if (opts.filter && !opts.filter(shpA, shpB)) return null;
|
|
28116
|
+
return key;
|
|
28117
|
+
}
|
|
28118
|
+
|
|
28119
|
+
return function(getKey) {
|
|
28120
|
+
return function(arcId) {
|
|
28121
|
+
return classify(arcId, getKey);
|
|
28122
|
+
};
|
|
28123
|
+
};
|
|
28124
|
+
}
|
|
28125
|
+
|
|
28126
|
+
var ArcClassifier = /*#__PURE__*/Object.freeze({
|
|
28127
|
+
__proto__: null,
|
|
28128
|
+
getArcClassifier: getArcClassifier
|
|
28129
|
+
});
|
|
28130
|
+
|
|
28131
|
+
// Returns a function for querying the neighbors of a given shape. The function
|
|
28132
|
+
// can be called in either of two ways:
|
|
28133
|
+
//
|
|
28134
|
+
// 1. function(shapeId, callback)
|
|
28135
|
+
// Callback signature: function(adjacentShapeId, arcId)
|
|
28136
|
+
// The callback function is called once for each arc that the given feature
|
|
28137
|
+
// shares with another feature.
|
|
28138
|
+
//
|
|
28139
|
+
// 2. function(shapeId)
|
|
28140
|
+
// The function returns an array of unique ids of neighboring shapes, or
|
|
28141
|
+
// an empty array if a shape has no neighbors.
|
|
28142
|
+
//
|
|
28143
|
+
function getNeighborLookupFunction(lyr, arcs) {
|
|
28144
|
+
var classifier = getArcClassifier(lyr.shapes, arcs, {reusable: true});
|
|
28145
|
+
var classify = classifier(onShapes);
|
|
28146
|
+
var currShapeId;
|
|
28147
|
+
var neighbors;
|
|
28148
|
+
var callback;
|
|
28149
|
+
|
|
28150
|
+
function onShapes(a, b) {
|
|
28151
|
+
if (b == -1) return -1; // outer edges are b == -1
|
|
28152
|
+
return a == currShapeId ? b : a;
|
|
28153
|
+
}
|
|
28154
|
+
|
|
28155
|
+
function onArc(arcId) {
|
|
28156
|
+
var nabeId = classify(arcId);
|
|
28157
|
+
if (nabeId == -1) return;
|
|
28158
|
+
if (callback) {
|
|
28159
|
+
callback(nabeId, arcId);
|
|
28160
|
+
} else if (neighbors.indexOf(nabeId) == -1) {
|
|
28161
|
+
neighbors.push(nabeId);
|
|
28162
|
+
}
|
|
28163
|
+
}
|
|
28164
|
+
|
|
28165
|
+
return function(shpId, cb) {
|
|
28166
|
+
currShapeId = shpId;
|
|
28167
|
+
if (cb) {
|
|
28168
|
+
callback = cb;
|
|
28169
|
+
forEachArcId(lyr.shapes[shpId], onArc);
|
|
28170
|
+
callback = null;
|
|
28171
|
+
} else {
|
|
28172
|
+
neighbors = [];
|
|
28173
|
+
forEachArcId(lyr.shapes[shpId], onArc);
|
|
28174
|
+
return neighbors;
|
|
28175
|
+
}
|
|
28176
|
+
};
|
|
28177
|
+
}
|
|
28178
|
+
|
|
28179
|
+
|
|
28180
|
+
// Returns an array containing all pairs of adjacent shapes
|
|
28181
|
+
// in a collection of polygon shapes. A pair of shapes is represented as
|
|
28182
|
+
// an array of two shape indexes [a, b].
|
|
28183
|
+
function findPairsOfNeighbors(shapes, arcs) {
|
|
28184
|
+
var getKey = function(a, b) {
|
|
28185
|
+
return b > -1 && a > -1 ? [a, b] : null;
|
|
28186
|
+
};
|
|
28187
|
+
var classify = getArcClassifier(shapes, arcs)(getKey);
|
|
28188
|
+
var arr = [];
|
|
28189
|
+
var index = {};
|
|
28190
|
+
var onArc = function(arcId) {
|
|
28191
|
+
var obj = classify(arcId);
|
|
28192
|
+
var key;
|
|
28193
|
+
if (obj) {
|
|
28194
|
+
key = obj.join('~');
|
|
28195
|
+
if (key in index === false) {
|
|
28196
|
+
arr.push(obj);
|
|
28197
|
+
index[key] = true;
|
|
28198
|
+
}
|
|
28199
|
+
}
|
|
28200
|
+
};
|
|
28201
|
+
forEachArcId(shapes, onArc);
|
|
28202
|
+
return arr;
|
|
28203
|
+
}
|
|
28204
|
+
|
|
28205
|
+
var PolygonNeighbors = /*#__PURE__*/Object.freeze({
|
|
28206
|
+
__proto__: null,
|
|
28207
|
+
getNeighborLookupFunction: getNeighborLookupFunction,
|
|
28208
|
+
findPairsOfNeighbors: findPairsOfNeighbors
|
|
28209
|
+
});
|
|
28210
|
+
|
|
28211
|
+
var BALANCE_COLORS = true;
|
|
28212
|
+
|
|
28213
|
+
function getNonAdjacentClassifier(lyr, dataset, colors) {
|
|
28214
|
+
requirePolygonLayer(lyr);
|
|
28215
|
+
var getNeighbors = getNeighborLookupFunction(lyr, dataset.arcs);
|
|
28216
|
+
var errorCount = 0;
|
|
28217
|
+
var data = utils.range(getFeatureCount(lyr)).map(function(shpId) {
|
|
28218
|
+
var nabes = getNeighbors(shpId) || [];
|
|
28219
|
+
return {
|
|
28220
|
+
// id: shpId,
|
|
28221
|
+
nabes: nabes,
|
|
28222
|
+
colorId: -1,
|
|
28223
|
+
nabeColors: [],
|
|
28224
|
+
uncolored: nabes.length,
|
|
28225
|
+
saturation: 0,
|
|
28226
|
+
saturation2: 0
|
|
28227
|
+
};
|
|
28228
|
+
});
|
|
28229
|
+
var getSortedColorIds = getUpdateFunction(colors.length);
|
|
28230
|
+
var colorIds = getSortedColorIds();
|
|
28231
|
+
// Sort adjacency data by number of neighbors in descending order
|
|
28232
|
+
var iter = getNodeIterator(data);
|
|
28233
|
+
// Assign colors, starting with polygons with the largest number of neighbors
|
|
28234
|
+
iter.forEach(function(d) {
|
|
28235
|
+
var colorId = pickColor(d, data, colorIds);
|
|
28236
|
+
if (colorId == -1) {
|
|
28237
|
+
errorCount++;
|
|
28238
|
+
colorId = colorIds[0];
|
|
28239
|
+
}
|
|
28240
|
+
d.colorId = colorId;
|
|
28241
|
+
if (BALANCE_COLORS) {
|
|
28242
|
+
colorIds = getSortedColorIds(colorId);
|
|
28243
|
+
}
|
|
28244
|
+
});
|
|
28245
|
+
|
|
28246
|
+
if (errorCount > 0) {
|
|
28247
|
+
message(`Unable to find non-adjacent colors for ${errorCount} ${errorCount == 1 ? 'polygon' : 'polygons'}`);
|
|
28248
|
+
}
|
|
28249
|
+
return function(shpId) {
|
|
28250
|
+
return colors[data[shpId].colorId];
|
|
28251
|
+
};
|
|
28252
|
+
}
|
|
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
|
+
|
|
28307
|
+
// Pick the id of a color that is not shared with a neighboring polygon
|
|
28308
|
+
function pickColor(d, data, colorIds) {
|
|
28309
|
+
var candidateId;
|
|
28310
|
+
for (var i=0; i<colorIds.length; i++) {
|
|
28311
|
+
candidateId = colorIds[i];
|
|
28312
|
+
if (isAvailableColor(d, data, candidateId)) {
|
|
28313
|
+
return candidateId;
|
|
28314
|
+
}
|
|
28315
|
+
}
|
|
28316
|
+
return -1; // no colors are available
|
|
28317
|
+
}
|
|
28318
|
+
|
|
28319
|
+
function isAvailableColor(d, data, colorId) {
|
|
28320
|
+
var nabes = d.nabes;
|
|
28321
|
+
for (var i=0; i<nabes.length; i++) {
|
|
28322
|
+
if (data[nabes[i]].colorId === colorId) return false;
|
|
28323
|
+
}
|
|
28324
|
+
return true;
|
|
28325
|
+
}
|
|
28326
|
+
|
|
28327
|
+
// Update function returns an array of ids, sorted in descending order of preference
|
|
28328
|
+
// (less-used ids are preferred).
|
|
28329
|
+
// Function recieves an (optional) id that was just used.
|
|
28330
|
+
function getUpdateFunction(n) {
|
|
28331
|
+
var ids = utils.range(n);
|
|
28332
|
+
var counts = new Uint32Array(n);
|
|
28333
|
+
return function(i) {
|
|
28334
|
+
if (i >= 0 && i < n) {
|
|
28335
|
+
counts[i]++;
|
|
28336
|
+
utils.sortArrayIndex(ids, counts, true);
|
|
28337
|
+
} else if (i !== undefined) {
|
|
28338
|
+
error('Unexpected color index:', i);
|
|
28339
|
+
}
|
|
28340
|
+
return ids;
|
|
28341
|
+
};
|
|
28342
|
+
}
|
|
28343
|
+
|
|
28344
|
+
cmd.classify = function(lyr, dataset, optsArg) {
|
|
28345
|
+
if (!lyr.data) {
|
|
28346
|
+
initDataTable(lyr);
|
|
28347
|
+
}
|
|
28032
28348
|
var opts = optsArg || {};
|
|
28033
28349
|
var records = lyr.data && lyr.data.getRecords();
|
|
28034
28350
|
var nullValue = opts.null_value || null;
|
|
28035
28351
|
var looksLikeColors = !!opts.colors || !!opts.color_scheme;
|
|
28036
28352
|
var colorScheme;
|
|
28037
|
-
var classValues,
|
|
28353
|
+
var classValues, classifyByValue, classifyById;
|
|
28038
28354
|
var numBuckets, numValues;
|
|
28039
28355
|
var dataField, outputField;
|
|
28040
28356
|
|
|
28041
28357
|
// validate explicitly set classes
|
|
28042
28358
|
if (opts.classes) {
|
|
28043
28359
|
if (!utils.isInteger(opts.classes) || opts.classes > 1 === false) {
|
|
28044
|
-
stop('Invalid classes
|
|
28360
|
+
stop('Invalid number of classes:', opts.classes, '(expected a value greater than 1)');
|
|
28045
28361
|
}
|
|
28046
28362
|
numBuckets = opts.classes;
|
|
28047
28363
|
}
|
|
28048
28364
|
|
|
28049
|
-
|
|
28050
28365
|
// TODO: better validation of breaks values
|
|
28051
28366
|
if (opts.breaks) {
|
|
28052
28367
|
numBuckets = opts.breaks.length + 1;
|
|
@@ -28064,9 +28379,6 @@ ${svg}
|
|
|
28064
28379
|
|
|
28065
28380
|
} else if (opts.field) {
|
|
28066
28381
|
dataField = opts.field;
|
|
28067
|
-
|
|
28068
|
-
} else {
|
|
28069
|
-
stop('Missing a data field to classify');
|
|
28070
28382
|
}
|
|
28071
28383
|
|
|
28072
28384
|
// expand categories if value is '*'
|
|
@@ -28074,7 +28386,18 @@ ${svg}
|
|
|
28074
28386
|
opts.categories = getUniqFieldValues(records, dataField);
|
|
28075
28387
|
}
|
|
28076
28388
|
|
|
28077
|
-
|
|
28389
|
+
if (opts.method == 'non-adjacent') {
|
|
28390
|
+
if (lyr.geometry_type != 'polygon') {
|
|
28391
|
+
stop('The non-adjacent option requires a polygon layer');
|
|
28392
|
+
}
|
|
28393
|
+
if (dataField) {
|
|
28394
|
+
stop('The non-adjacent option does not accept a data field argument');
|
|
28395
|
+
}
|
|
28396
|
+
} else if (!dataField) {
|
|
28397
|
+
stop('Missing a data field to classify');
|
|
28398
|
+
} else {
|
|
28399
|
+
requireDataField(lyr.data, dataField);
|
|
28400
|
+
}
|
|
28078
28401
|
|
|
28079
28402
|
if (numBuckets) {
|
|
28080
28403
|
numValues = opts.continuous ? numBuckets + 1 : numBuckets;
|
|
@@ -28142,15 +28465,25 @@ ${svg}
|
|
|
28142
28465
|
|
|
28143
28466
|
// get a function to convert input data to class indexes
|
|
28144
28467
|
//
|
|
28145
|
-
if (opts.
|
|
28468
|
+
if (opts.method == 'non-adjacent') {
|
|
28469
|
+
classifyById = getNonAdjacentClassifier(lyr, dataset, classValues);
|
|
28470
|
+
} else if (opts.index_field) {
|
|
28146
28471
|
// data is pre-classified... just read the index from a field
|
|
28147
|
-
|
|
28472
|
+
classifyByValue = getIndexedClassifier(classValues, nullValue, opts);
|
|
28148
28473
|
} else if (opts.categories) {
|
|
28149
|
-
|
|
28474
|
+
classifyByValue = getCategoricalClassifier(classValues, nullValue, opts);
|
|
28150
28475
|
} else {
|
|
28151
|
-
|
|
28476
|
+
classifyByValue = getSequentialClassifier(classValues, nullValue, getFieldValues(records, dataField), opts);
|
|
28152
28477
|
}
|
|
28153
28478
|
|
|
28479
|
+
if (classifyByValue) {
|
|
28480
|
+
classifyById = function(id) {
|
|
28481
|
+
var d = records[id] || {};
|
|
28482
|
+
return classifyByValue(d[dataField]);
|
|
28483
|
+
};
|
|
28484
|
+
}
|
|
28485
|
+
|
|
28486
|
+
|
|
28154
28487
|
// get the name of the output field
|
|
28155
28488
|
//
|
|
28156
28489
|
if (looksLikeColors) {
|
|
@@ -28166,8 +28499,7 @@ ${svg}
|
|
|
28166
28499
|
}
|
|
28167
28500
|
|
|
28168
28501
|
records.forEach(function(d, i) {
|
|
28169
|
-
d =
|
|
28170
|
-
d[outputField] = classify(d[dataField]);
|
|
28502
|
+
d[outputField] = classifyById(i);
|
|
28171
28503
|
});
|
|
28172
28504
|
};
|
|
28173
28505
|
|
|
@@ -28979,147 +29311,6 @@ ${svg}
|
|
|
28979
29311
|
getClipMessage: getClipMessage
|
|
28980
29312
|
});
|
|
28981
29313
|
|
|
28982
|
-
// Returns a function for constructing a query function that accepts an arc id and
|
|
28983
|
-
// returns information about the polygon or polygons that use the given arc.
|
|
28984
|
-
// TODO: explain this better.
|
|
28985
|
-
//
|
|
28986
|
-
// options:
|
|
28987
|
-
// filter: optional filter function; signature: function(idA, idB or -1) : boolean
|
|
28988
|
-
// reusable: flag that lets an arc be queried multiple times.
|
|
28989
|
-
function getArcClassifier(shapes, arcs) {
|
|
28990
|
-
var opts = arguments[2] || {},
|
|
28991
|
-
useOnce = !opts.reusable,
|
|
28992
|
-
n = arcs.size(),
|
|
28993
|
-
a = new Int32Array(n),
|
|
28994
|
-
b = new Int32Array(n);
|
|
28995
|
-
|
|
28996
|
-
utils.initializeArray(a, -1);
|
|
28997
|
-
utils.initializeArray(b, -1);
|
|
28998
|
-
|
|
28999
|
-
traversePaths(shapes, function(o) {
|
|
29000
|
-
var i = absArcId(o.arcId);
|
|
29001
|
-
var shpId = o.shapeId;
|
|
29002
|
-
var aval = a[i];
|
|
29003
|
-
if (aval == -1) {
|
|
29004
|
-
a[i] = shpId;
|
|
29005
|
-
} else if (shpId < aval) {
|
|
29006
|
-
b[i] = aval;
|
|
29007
|
-
a[i] = shpId;
|
|
29008
|
-
} else {
|
|
29009
|
-
b[i] = shpId;
|
|
29010
|
-
}
|
|
29011
|
-
});
|
|
29012
|
-
|
|
29013
|
-
function classify(arcId, getKey) {
|
|
29014
|
-
var i = absArcId(arcId);
|
|
29015
|
-
var shpA = a[i];
|
|
29016
|
-
var shpB = b[i];
|
|
29017
|
-
var key;
|
|
29018
|
-
if (shpA == -1) return null;
|
|
29019
|
-
key = getKey(shpA, shpB);
|
|
29020
|
-
if (key === null || key === false) return null;
|
|
29021
|
-
if (useOnce) {
|
|
29022
|
-
// arc can only be queried once
|
|
29023
|
-
a[i] = -1;
|
|
29024
|
-
b[i] = -1;
|
|
29025
|
-
}
|
|
29026
|
-
// use optional filter to exclude some arcs
|
|
29027
|
-
if (opts.filter && !opts.filter(shpA, shpB)) return null;
|
|
29028
|
-
return key;
|
|
29029
|
-
}
|
|
29030
|
-
|
|
29031
|
-
return function(getKey) {
|
|
29032
|
-
return function(arcId) {
|
|
29033
|
-
return classify(arcId, getKey);
|
|
29034
|
-
};
|
|
29035
|
-
};
|
|
29036
|
-
}
|
|
29037
|
-
|
|
29038
|
-
var ArcClassifier = /*#__PURE__*/Object.freeze({
|
|
29039
|
-
__proto__: null,
|
|
29040
|
-
getArcClassifier: getArcClassifier
|
|
29041
|
-
});
|
|
29042
|
-
|
|
29043
|
-
// Returns a function for querying the neighbors of a given shape. The function
|
|
29044
|
-
// can be called in either of two ways:
|
|
29045
|
-
//
|
|
29046
|
-
// 1. function(shapeId, callback)
|
|
29047
|
-
// Callback signature: function(adjacentShapeId, arcId)
|
|
29048
|
-
// The callback function is called once for each arc that the given feature
|
|
29049
|
-
// shares with another feature.
|
|
29050
|
-
//
|
|
29051
|
-
// 2. function(shapeId)
|
|
29052
|
-
// The function returns an array of unique ids of neighboring shapes, or
|
|
29053
|
-
// an empty array if a shape has no neighbors.
|
|
29054
|
-
//
|
|
29055
|
-
function getNeighborLookupFunction(lyr, arcs) {
|
|
29056
|
-
var classifier = getArcClassifier(lyr.shapes, arcs, {reusable: true});
|
|
29057
|
-
var classify = classifier(onShapes);
|
|
29058
|
-
var currShapeId;
|
|
29059
|
-
var neighbors;
|
|
29060
|
-
var callback;
|
|
29061
|
-
|
|
29062
|
-
function onShapes(a, b) {
|
|
29063
|
-
if (b == -1) return -1; // outer edges are b == -1
|
|
29064
|
-
return a == currShapeId ? b : a;
|
|
29065
|
-
}
|
|
29066
|
-
|
|
29067
|
-
function onArc(arcId) {
|
|
29068
|
-
var nabeId = classify(arcId);
|
|
29069
|
-
if (nabeId == -1) return;
|
|
29070
|
-
if (callback) {
|
|
29071
|
-
callback(nabeId, arcId);
|
|
29072
|
-
} else if (neighbors.indexOf(nabeId) == -1) {
|
|
29073
|
-
neighbors.push(nabeId);
|
|
29074
|
-
}
|
|
29075
|
-
}
|
|
29076
|
-
|
|
29077
|
-
return function(shpId, cb) {
|
|
29078
|
-
currShapeId = shpId;
|
|
29079
|
-
if (cb) {
|
|
29080
|
-
callback = cb;
|
|
29081
|
-
forEachArcId(lyr.shapes[shpId], onArc);
|
|
29082
|
-
callback = null;
|
|
29083
|
-
} else {
|
|
29084
|
-
neighbors = [];
|
|
29085
|
-
forEachArcId(lyr.shapes[shpId], onArc);
|
|
29086
|
-
return neighbors;
|
|
29087
|
-
}
|
|
29088
|
-
};
|
|
29089
|
-
}
|
|
29090
|
-
|
|
29091
|
-
|
|
29092
|
-
// Returns an array containing all pairs of adjacent shapes
|
|
29093
|
-
// in a collection of polygon shapes. A pair of shapes is represented as
|
|
29094
|
-
// an array of two shape indexes [a, b].
|
|
29095
|
-
function findPairsOfNeighbors(shapes, arcs) {
|
|
29096
|
-
var getKey = function(a, b) {
|
|
29097
|
-
return b > -1 && a > -1 ? [a, b] : null;
|
|
29098
|
-
};
|
|
29099
|
-
var classify = getArcClassifier(shapes, arcs)(getKey);
|
|
29100
|
-
var arr = [];
|
|
29101
|
-
var index = {};
|
|
29102
|
-
var onArc = function(arcId) {
|
|
29103
|
-
var obj = classify(arcId);
|
|
29104
|
-
var key;
|
|
29105
|
-
if (obj) {
|
|
29106
|
-
key = obj.join('~');
|
|
29107
|
-
if (key in index === false) {
|
|
29108
|
-
arr.push(obj);
|
|
29109
|
-
index[key] = true;
|
|
29110
|
-
}
|
|
29111
|
-
}
|
|
29112
|
-
};
|
|
29113
|
-
forEachArcId(shapes, onArc);
|
|
29114
|
-
return arr;
|
|
29115
|
-
}
|
|
29116
|
-
|
|
29117
|
-
var PolygonNeighbors = /*#__PURE__*/Object.freeze({
|
|
29118
|
-
__proto__: null,
|
|
29119
|
-
getNeighborLookupFunction: getNeighborLookupFunction,
|
|
29120
|
-
findPairsOfNeighbors: findPairsOfNeighbors
|
|
29121
|
-
});
|
|
29122
|
-
|
|
29123
29314
|
// Assign a cluster id to each polygon in a dataset, which can be used with
|
|
29124
29315
|
// one of the dissolve commands to dissolve the clusters
|
|
29125
29316
|
// Works by iteratively grouping pairs of polygons with the smallest distance
|
|
@@ -29806,12 +29997,19 @@ ${svg}
|
|
|
29806
29997
|
});
|
|
29807
29998
|
|
|
29808
29999
|
// Join data from @src table to records in @dest table
|
|
30000
|
+
function joinTables(dest, src, join, opts) {
|
|
30001
|
+
return joinTableToLayer({data: dest}, src, join, opts);
|
|
30002
|
+
}
|
|
30003
|
+
|
|
30004
|
+
// Join data from @src table to records in @destLyr layer.
|
|
29809
30005
|
// @join function
|
|
29810
30006
|
// Receives index of record in the dest table
|
|
29811
30007
|
// Returns array of matching records in src table, or null if no matches
|
|
29812
30008
|
//
|
|
29813
|
-
function
|
|
29814
|
-
var
|
|
30009
|
+
function joinTableToLayer(destLyr, src, join, opts) {
|
|
30010
|
+
var dest = destLyr.data,
|
|
30011
|
+
useDuplication = !!opts.duplication,
|
|
30012
|
+
srcRecords = src.getRecords(),
|
|
29815
30013
|
destRecords = dest.getRecords(),
|
|
29816
30014
|
prefix = opts.prefix || '',
|
|
29817
30015
|
unmatchedRecords = [],
|
|
@@ -29826,6 +30024,14 @@ ${svg}
|
|
|
29826
30024
|
retn = {},
|
|
29827
30025
|
srcRec, srcId, destRec, joins, count, filter, calc, i, j, n, m;
|
|
29828
30026
|
|
|
30027
|
+
// support for duplication of destination records
|
|
30028
|
+
var duplicateRecords, destShapes;
|
|
30029
|
+
if (useDuplication) {
|
|
30030
|
+
if (opts.calc) stop('duplication and calc options cannot be used together');
|
|
30031
|
+
duplicateRecords = dest.clone().getRecords();
|
|
30032
|
+
destShapes = destLyr.shapes || [];
|
|
30033
|
+
}
|
|
30034
|
+
|
|
29829
30035
|
if (opts.where) {
|
|
29830
30036
|
filter = getJoinFilter(src, opts.where);
|
|
29831
30037
|
}
|
|
@@ -29835,7 +30041,8 @@ ${svg}
|
|
|
29835
30041
|
}
|
|
29836
30042
|
|
|
29837
30043
|
// join source records to target records
|
|
29838
|
-
|
|
30044
|
+
n = destRecords.length;
|
|
30045
|
+
for (i=0; i<n; i++) {
|
|
29839
30046
|
destRec = destRecords[i];
|
|
29840
30047
|
joins = join(i);
|
|
29841
30048
|
if (joins && filter) {
|
|
@@ -29846,7 +30053,13 @@ ${svg}
|
|
|
29846
30053
|
for (j=0, count=0, m=joins ? joins.length : 0; j<m; j++) {
|
|
29847
30054
|
srcId = joins[j];
|
|
29848
30055
|
srcRec = srcRecords[srcId];
|
|
29849
|
-
|
|
30056
|
+
// duplication mode: many-to-one joins add new features to the target layer.
|
|
30057
|
+
if (count > 0 && useDuplication) {
|
|
30058
|
+
destRec = copyRecord(duplicateRecords[i]);
|
|
30059
|
+
destRecords.push(destRec);
|
|
30060
|
+
destShapes.push(cloneShape(destShapes[i]));
|
|
30061
|
+
}
|
|
30062
|
+
if (count === 0 || useDuplication) {
|
|
29850
30063
|
if (copyFields.length > 0) {
|
|
29851
30064
|
// only copying the first match
|
|
29852
30065
|
joinByCopy(destRec, srcRec, copyFields, prefix);
|
|
@@ -29878,7 +30091,7 @@ ${svg}
|
|
|
29878
30091
|
}
|
|
29879
30092
|
}
|
|
29880
30093
|
|
|
29881
|
-
printJoinMessage(matchCount,
|
|
30094
|
+
printJoinMessage(matchCount, n,
|
|
29882
30095
|
countJoins(joinCounts), srcRecords.length, skipCount, collisionCount, collisionFields);
|
|
29883
30096
|
|
|
29884
30097
|
if (opts.unjoined) {
|
|
@@ -29906,6 +30119,7 @@ ${svg}
|
|
|
29906
30119
|
});
|
|
29907
30120
|
}
|
|
29908
30121
|
|
|
30122
|
+
|
|
29909
30123
|
function countJoins(counts) {
|
|
29910
30124
|
var joinCount = 0;
|
|
29911
30125
|
for (var i=0, n=counts.length; i<n; i++) {
|
|
@@ -29968,14 +30182,16 @@ ${svg}
|
|
|
29968
30182
|
|
|
29969
30183
|
function printJoinMessage(matches, n, joins, m, skipped, collisions, collisionFields) {
|
|
29970
30184
|
// TODO: add tip for troubleshooting join problems, if join is less than perfect.
|
|
30185
|
+
var unmatched = n - matches;
|
|
29971
30186
|
if (matches > 0 === false) {
|
|
29972
30187
|
message("No records could be joined");
|
|
29973
30188
|
return;
|
|
29974
30189
|
}
|
|
29975
30190
|
message(utils.format("Joined data from %'d source record%s to %'d target record%s",
|
|
29976
30191
|
joins, utils.pluralSuffix(joins), matches, utils.pluralSuffix(matches)));
|
|
29977
|
-
if (
|
|
29978
|
-
message(utils.format('%d
|
|
30192
|
+
if (unmatched > 0) {
|
|
30193
|
+
message(utils.format('%d target record%s received no data', unmatched, utils.pluralSuffix(unmatched)));
|
|
30194
|
+
// message(utils.format('%d target records received no data', n-matches));
|
|
29979
30195
|
}
|
|
29980
30196
|
if (joins < m) {
|
|
29981
30197
|
message(utils.format("%d/%d source records could not be joined", m-joins, m));
|
|
@@ -30024,6 +30240,7 @@ ${svg}
|
|
|
30024
30240
|
var JoinTables = /*#__PURE__*/Object.freeze({
|
|
30025
30241
|
__proto__: null,
|
|
30026
30242
|
joinTables: joinTables,
|
|
30243
|
+
joinTableToLayer: joinTableToLayer,
|
|
30027
30244
|
validateFieldNames: validateFieldNames,
|
|
30028
30245
|
updateUnmatchedRecord: updateUnmatchedRecord,
|
|
30029
30246
|
findCollisionFields: findCollisionFields,
|
|
@@ -31490,13 +31707,13 @@ ${svg}
|
|
|
31490
31707
|
// TODO: option to copy points that can't be joined to a new layer
|
|
31491
31708
|
var joinFunction = getPolygonToPointsFunction(targetLyr, arcs, pointLyr, opts);
|
|
31492
31709
|
prepJoinLayers(targetLyr, pointLyr);
|
|
31493
|
-
return
|
|
31710
|
+
return joinTableToLayer(targetLyr, pointLyr.data, joinFunction, opts);
|
|
31494
31711
|
}
|
|
31495
31712
|
|
|
31496
31713
|
function joinPolygonsToPoints(targetLyr, polygonLyr, arcs, opts) {
|
|
31497
31714
|
var joinFunction = getPointToPolygonsFunction(targetLyr, polygonLyr, arcs, opts);
|
|
31498
31715
|
prepJoinLayers(targetLyr, polygonLyr);
|
|
31499
|
-
return
|
|
31716
|
+
return joinTableToLayer(targetLyr, polygonLyr.data, joinFunction, opts);
|
|
31500
31717
|
}
|
|
31501
31718
|
|
|
31502
31719
|
|
|
@@ -33282,6 +33499,12 @@ ${svg}
|
|
|
33282
33499
|
};
|
|
33283
33500
|
}
|
|
33284
33501
|
|
|
33502
|
+
cmd.ignore = function(targetLayer, dataset, opts) {
|
|
33503
|
+
if (opts.empty && layerIsEmpty(targetLayer)) {
|
|
33504
|
+
interrupt('Layer is empty, stopping processing');
|
|
33505
|
+
}
|
|
33506
|
+
};
|
|
33507
|
+
|
|
33285
33508
|
cmd.include = function(opts) {
|
|
33286
33509
|
var content, obj, context;
|
|
33287
33510
|
// TODO: handle web context
|
|
@@ -33657,9 +33880,10 @@ ${svg}
|
|
|
33657
33880
|
|
|
33658
33881
|
var joinOpts = utils.extend({}, opts);
|
|
33659
33882
|
var joinFunction = getPolygonToPolygonFunction(targetLyr, sourceLyr, mosaicIndex, opts);
|
|
33660
|
-
var retn =
|
|
33883
|
+
var retn = joinTableToLayer(targetLyr, sourceLyr.data, joinFunction, joinOpts);
|
|
33661
33884
|
|
|
33662
33885
|
if (opts.interpolate) {
|
|
33886
|
+
if (opts.duplication) stop('duplication and interpolate options cannot be used together');
|
|
33663
33887
|
interpolateFieldsByArea(targetLyr, sourceLyr, mosaicIndex, opts);
|
|
33664
33888
|
}
|
|
33665
33889
|
return retn;
|
|
@@ -34574,7 +34798,7 @@ ${svg}
|
|
|
34574
34798
|
function joinPointsToPoints(targetLyr, srcLyr, crs, opts) {
|
|
34575
34799
|
var joinFunction = getPointToPointFunction(targetLyr, srcLyr, crs, opts);
|
|
34576
34800
|
prepJoinLayers(targetLyr, srcLyr);
|
|
34577
|
-
return
|
|
34801
|
+
return joinTableToLayer(targetLyr, srcLyr.data, joinFunction, opts);
|
|
34578
34802
|
}
|
|
34579
34803
|
|
|
34580
34804
|
function getPointToPointFunction(targetLyr, srcLyr, crs, opts) {
|
|
@@ -34624,14 +34848,14 @@ ${svg}
|
|
|
34624
34848
|
}
|
|
34625
34849
|
};
|
|
34626
34850
|
|
|
34627
|
-
function joinAttributesToFeatures(
|
|
34851
|
+
function joinAttributesToFeatures(destLyr, srcTable, opts) {
|
|
34628
34852
|
var keys = opts.keys,
|
|
34629
34853
|
destKey = keys[0],
|
|
34630
34854
|
srcKey = keys[1],
|
|
34631
|
-
destTable =
|
|
34855
|
+
destTable = destLyr.data,
|
|
34632
34856
|
joinFunction = getJoinByKey(destTable, destKey, srcTable, srcKey);
|
|
34633
34857
|
validateFieldNames(keys);
|
|
34634
|
-
return
|
|
34858
|
+
return joinTableToLayer(destLyr, srcTable, joinFunction, opts);
|
|
34635
34859
|
}
|
|
34636
34860
|
|
|
34637
34861
|
// Return a function for translating a target id to an array of source ids based on values
|
|
@@ -37623,7 +37847,7 @@ ${svg}
|
|
|
37623
37847
|
applyCommandToEachLayer(cmd.calc, targetLayers, arcs, opts);
|
|
37624
37848
|
|
|
37625
37849
|
} else if (name == 'classify') {
|
|
37626
|
-
applyCommandToEachLayer(cmd.classify, targetLayers, opts);
|
|
37850
|
+
applyCommandToEachLayer(cmd.classify, targetLayers, targetDataset, opts);
|
|
37627
37851
|
|
|
37628
37852
|
} else if (name == 'clean') {
|
|
37629
37853
|
cmd.cleanLayers(targetLayers, targetDataset, opts);
|
|
@@ -37707,6 +37931,9 @@ ${svg}
|
|
|
37707
37931
|
outputLayers = targetDataset.layers; // kludge to allow layer naming below
|
|
37708
37932
|
}
|
|
37709
37933
|
|
|
37934
|
+
} else if (name == 'ignore') {
|
|
37935
|
+
applyCommandToEachLayer(cmd.ignore, targetLayers, targetDataset, opts);
|
|
37936
|
+
|
|
37710
37937
|
} else if (name == 'include') {
|
|
37711
37938
|
cmd.include(opts);
|
|
37712
37939
|
|
|
@@ -38077,6 +38304,7 @@ ${svg}
|
|
|
38077
38304
|
cmd.options.output = outputArr;
|
|
38078
38305
|
}
|
|
38079
38306
|
});
|
|
38307
|
+
|
|
38080
38308
|
runParsedCommands(commands, null, callback);
|
|
38081
38309
|
}
|
|
38082
38310
|
|
|
@@ -38137,10 +38365,6 @@ ${svg}
|
|
|
38137
38365
|
error("Changed in v0.4: runParsedCommands() takes a Catalog object");
|
|
38138
38366
|
}
|
|
38139
38367
|
|
|
38140
|
-
if (!utils.isFunction(done)) {
|
|
38141
|
-
error("Missing a callback function");
|
|
38142
|
-
}
|
|
38143
|
-
|
|
38144
38368
|
if (!utils.isArray(commands)) {
|
|
38145
38369
|
error("Expected an array of parsed commands");
|
|
38146
38370
|
}
|
|
@@ -38161,18 +38385,25 @@ ${svg}
|
|
|
38161
38385
|
// that it can modify the output dataset in-place instead of making a copy.
|
|
38162
38386
|
commands[commands.length-1].options.final = true;
|
|
38163
38387
|
}
|
|
38164
|
-
commands = divideImportCommand(commands);
|
|
38165
|
-
utils.reduceAsync(commands, catalog, nextCommand, done);
|
|
38166
38388
|
|
|
38167
|
-
|
|
38168
|
-
|
|
38169
|
-
|
|
38170
|
-
|
|
38171
|
-
|
|
38389
|
+
var groups = divideImportCommand(commands);
|
|
38390
|
+
if (groups.length == 1) {
|
|
38391
|
+
// run a simple sequence of commands (input files are not batched)
|
|
38392
|
+
return runParsedCommands2(commands, catalog, done);
|
|
38393
|
+
}
|
|
38394
|
+
|
|
38395
|
+
// run duplicated commands (i.e. batch mode)
|
|
38396
|
+
utils.reduceAsync(groups, catalog, nextGroup, done);
|
|
38397
|
+
|
|
38398
|
+
function nextGroup(catalog, commands, next) {
|
|
38399
|
+
runParsedCommands2(commands, catalog, function(err, catalog) {
|
|
38400
|
+
err = filterError(err);
|
|
38401
|
+
next(err, catalog);
|
|
38402
|
+
});
|
|
38172
38403
|
}
|
|
38173
38404
|
|
|
38174
38405
|
function done(err, catalog) {
|
|
38175
|
-
|
|
38406
|
+
err = filterError(err);
|
|
38176
38407
|
cb(err, catalog);
|
|
38177
38408
|
setStateVar('current_command', null);
|
|
38178
38409
|
setStateVar('verbose', false);
|
|
@@ -38180,11 +38411,31 @@ ${svg}
|
|
|
38180
38411
|
}
|
|
38181
38412
|
}
|
|
38182
38413
|
|
|
38414
|
+
function filterError(err) {
|
|
38415
|
+
if (err) printError(err);
|
|
38416
|
+
if (err && err.name == 'NonFatalError') {
|
|
38417
|
+
return null;
|
|
38418
|
+
}
|
|
38419
|
+
return err;
|
|
38420
|
+
}
|
|
38421
|
+
|
|
38422
|
+
function runParsedCommands2(commands, catalog, cb) {
|
|
38423
|
+
utils.reduceAsync(commands, catalog, nextCommand, cb);
|
|
38424
|
+
|
|
38425
|
+
function nextCommand(catalog, cmd, next) {
|
|
38426
|
+
setStateVar('current_command', cmd.name); // for log msgs
|
|
38427
|
+
setStateVar('verbose', !!cmd.options.verbose);
|
|
38428
|
+
setStateVar('debug', !!cmd.options.debug);
|
|
38429
|
+
runCommand(cmd, catalog, next);
|
|
38430
|
+
}
|
|
38431
|
+
}
|
|
38432
|
+
|
|
38433
|
+
|
|
38183
38434
|
// If an initial import command indicates that several input files should be
|
|
38184
38435
|
// processed separately, then duplicate the sequence of commands to run
|
|
38185
38436
|
// once for each input file
|
|
38186
38437
|
// @commands Array of parsed commands
|
|
38187
|
-
// Returns:
|
|
38438
|
+
// Returns: Array of one or more sequences of parsed commands
|
|
38188
38439
|
//
|
|
38189
38440
|
function divideImportCommand(commands) {
|
|
38190
38441
|
var firstCmd = commands[0],
|
|
@@ -38192,23 +38443,23 @@ ${svg}
|
|
|
38192
38443
|
|
|
38193
38444
|
if (firstCmd.name != 'i' || opts.stdin || opts.merge_files ||
|
|
38194
38445
|
opts.combine_files || !opts.files || opts.files.length < 2) {
|
|
38195
|
-
return commands;
|
|
38446
|
+
return [commands];
|
|
38196
38447
|
}
|
|
38197
38448
|
|
|
38198
|
-
return
|
|
38199
|
-
var
|
|
38449
|
+
return opts.files.map(function(file) {
|
|
38450
|
+
var group = [{
|
|
38200
38451
|
name: 'i',
|
|
38201
38452
|
options: utils.defaults({
|
|
38202
38453
|
files:[file],
|
|
38203
38454
|
replace: true // kludge to replace data catalog
|
|
38204
38455
|
}, opts)
|
|
38205
|
-
};
|
|
38206
|
-
|
|
38207
|
-
|
|
38208
|
-
|
|
38209
|
-
}, []);
|
|
38456
|
+
}];
|
|
38457
|
+
group.push.apply(group, commands.slice(1));
|
|
38458
|
+
return group;
|
|
38459
|
+
});
|
|
38210
38460
|
}
|
|
38211
38461
|
|
|
38462
|
+
|
|
38212
38463
|
function printStartupMessages() {
|
|
38213
38464
|
// print heap memory message if running with a custom amount
|
|
38214
38465
|
var rxp = /^--max-old-space-size=([0-9]+)$/;
|