mapshaper 0.5.97 → 0.5.98
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 +3 -0
- package/mapshaper.js +50 -25
- package/package.json +1 -1
- package/www/mapshaper.js +50 -25
package/CHANGELOG.md
CHANGED
package/mapshaper.js
CHANGED
|
@@ -29059,6 +29059,31 @@ ${svg}
|
|
|
29059
29059
|
return ramp;
|
|
29060
29060
|
}
|
|
29061
29061
|
|
|
29062
|
+
function getNullValue(opts) {
|
|
29063
|
+
var nullValue;
|
|
29064
|
+
if ('null_value' in opts) {
|
|
29065
|
+
nullValue = parseNullValue(opts.null_value);
|
|
29066
|
+
} else if (opts.colors) {
|
|
29067
|
+
nullValue = '#eee';
|
|
29068
|
+
} else if (opts.values) {
|
|
29069
|
+
nullValue = null;
|
|
29070
|
+
} else {
|
|
29071
|
+
nullValue = -1; // kludge, to match behavior of getClassValues()
|
|
29072
|
+
}
|
|
29073
|
+
return nullValue;
|
|
29074
|
+
}
|
|
29075
|
+
|
|
29076
|
+
// Parse command line string arguments to the correct data type
|
|
29077
|
+
function parseNullValue(val) {
|
|
29078
|
+
if (utils.isString(val) && !isNaN(+val)) {
|
|
29079
|
+
val = +val;
|
|
29080
|
+
}
|
|
29081
|
+
if (val === 'null') {
|
|
29082
|
+
val = null;
|
|
29083
|
+
}
|
|
29084
|
+
return val;
|
|
29085
|
+
}
|
|
29086
|
+
|
|
29062
29087
|
function getClassValues(method, n, opts) {
|
|
29063
29088
|
var categorical = method == 'categorical' || method == 'non-adjacent';
|
|
29064
29089
|
var colorArg = opts.colors && opts.colors.length == 1 ? opts.colors[0] : null;
|
|
@@ -29132,27 +29157,33 @@ ${svg}
|
|
|
29132
29157
|
return values;
|
|
29133
29158
|
}
|
|
29134
29159
|
|
|
29135
|
-
var sequential = ['quantile', 'nice', 'equal-interval', 'hybrid'];
|
|
29160
|
+
var sequential = ['quantile', 'nice', 'equal-interval', 'hybrid', 'breaks'];
|
|
29136
29161
|
var all = ['non-adjacent', 'indexed', 'categorical'].concat(sequential);
|
|
29137
29162
|
|
|
29138
|
-
function getClassifyMethod(opts,
|
|
29163
|
+
function getClassifyMethod(opts, dataType) {
|
|
29139
29164
|
var method;
|
|
29140
29165
|
if (opts.method) {
|
|
29141
29166
|
method = opts.method;
|
|
29167
|
+
} else if (opts.breaks) {
|
|
29168
|
+
method = 'breaks';
|
|
29142
29169
|
} else if (opts.index_field) {
|
|
29143
29170
|
method = 'indexed';
|
|
29144
|
-
} else if (opts.categories ||
|
|
29171
|
+
} else if (opts.categories || dataType == 'string') {
|
|
29145
29172
|
method = 'categorical';
|
|
29146
|
-
} else if (
|
|
29173
|
+
} else if (dataType == 'number') {
|
|
29147
29174
|
method = 'quantile'; // TODO: validate data field
|
|
29175
|
+
} else if (dataType == 'date' || dataType == 'object') {
|
|
29176
|
+
stop('Data type does not support classification:', dataType);
|
|
29177
|
+
} else if (dataType === null) {
|
|
29178
|
+
// data field is empty
|
|
29179
|
+
return null; // kludge
|
|
29148
29180
|
} else {
|
|
29149
|
-
|
|
29150
|
-
stop('Missing a data field and/or classification method');
|
|
29181
|
+
stop('Unable to determine which classification method to use.');
|
|
29151
29182
|
}
|
|
29152
29183
|
if (!all.includes(method)) {
|
|
29153
29184
|
stop('Not a recognized classification method:', method);
|
|
29154
29185
|
}
|
|
29155
|
-
if (sequential.includes(method) &&
|
|
29186
|
+
if (sequential.includes(method) && dataType != 'number' && dataType !== null) {
|
|
29156
29187
|
stop('The', method, 'method requires a numerical data field');
|
|
29157
29188
|
}
|
|
29158
29189
|
return method;
|
|
@@ -29165,7 +29196,7 @@ ${svg}
|
|
|
29165
29196
|
var opts = optsArg || {};
|
|
29166
29197
|
var records = lyr.data && lyr.data.getRecords();
|
|
29167
29198
|
var valuesAreColors = !!opts.colors;
|
|
29168
|
-
var dataField,
|
|
29199
|
+
var dataField, fieldType, outputField;
|
|
29169
29200
|
var values, nullValue;
|
|
29170
29201
|
var classifyByValue, classifyByRecordId;
|
|
29171
29202
|
var numClasses, numValues;
|
|
@@ -29179,9 +29210,10 @@ ${svg}
|
|
|
29179
29210
|
//
|
|
29180
29211
|
if (opts.index_field) {
|
|
29181
29212
|
dataField = opts.index_field;
|
|
29182
|
-
|
|
29213
|
+
fieldType = getColumnType(opts.field, records);
|
|
29214
|
+
} else if (opts.field) {
|
|
29183
29215
|
dataField = opts.field;
|
|
29184
|
-
|
|
29216
|
+
fieldType = getColumnType(opts.field, records);
|
|
29185
29217
|
}
|
|
29186
29218
|
if (dataField) {
|
|
29187
29219
|
requireDataField(lyr.data, dataField);
|
|
@@ -29189,7 +29221,7 @@ ${svg}
|
|
|
29189
29221
|
|
|
29190
29222
|
// get classification method
|
|
29191
29223
|
//
|
|
29192
|
-
method = getClassifyMethod(opts,
|
|
29224
|
+
method = getClassifyMethod(opts, fieldType);
|
|
29193
29225
|
|
|
29194
29226
|
// validate classification method
|
|
29195
29227
|
if (method == 'non-adjacent') {
|
|
@@ -29207,6 +29239,7 @@ ${svg}
|
|
|
29207
29239
|
// get the number of classes and the number of values
|
|
29208
29240
|
//
|
|
29209
29241
|
// expand categories if value is '*'
|
|
29242
|
+
// use all unique values if categories option is missing
|
|
29210
29243
|
if (method == 'categorical') {
|
|
29211
29244
|
if ((!opts.categories || opts.categories.includes('*')) && dataField) {
|
|
29212
29245
|
opts.categories = getUniqFieldValues(records, dataField);
|
|
@@ -29248,24 +29281,16 @@ ${svg}
|
|
|
29248
29281
|
message('Colors:', formatValuesForLogging(values));
|
|
29249
29282
|
}
|
|
29250
29283
|
|
|
29251
|
-
|
|
29252
|
-
//
|
|
29253
|
-
if ('null_value' in opts) {
|
|
29254
|
-
nullValue = opts.null_value;
|
|
29255
|
-
} else if (valuesAreColors) {
|
|
29256
|
-
nullValue = '#eee';
|
|
29257
|
-
} else if (opts.values) {
|
|
29258
|
-
nullValue = null;
|
|
29259
|
-
} else {
|
|
29260
|
-
nullValue = -1; // kludge, to match behavior of getClassValues()
|
|
29261
|
-
}
|
|
29262
|
-
|
|
29284
|
+
nullValue = getNullValue(opts);
|
|
29263
29285
|
|
|
29264
29286
|
// get a function to convert input data to class indexes
|
|
29265
29287
|
//
|
|
29266
|
-
if (
|
|
29288
|
+
if (fieldType === null) {
|
|
29289
|
+
// no valid data -- always return null value
|
|
29290
|
+
classifyByRecordId = function() {return nullValue;};
|
|
29291
|
+
} else if (method == 'non-adjacent') {
|
|
29267
29292
|
classifyByRecordId = getNonAdjacentClassifier(lyr, dataset, values);
|
|
29268
|
-
} else if (
|
|
29293
|
+
} else if (method == 'indexed') {
|
|
29269
29294
|
// data is pre-classified... just read the index from a field
|
|
29270
29295
|
classifyByValue = getIndexedClassifier(values, nullValue, opts);
|
|
29271
29296
|
} else if (method == 'categorical') {
|
package/package.json
CHANGED
package/www/mapshaper.js
CHANGED
|
@@ -29059,6 +29059,31 @@ ${svg}
|
|
|
29059
29059
|
return ramp;
|
|
29060
29060
|
}
|
|
29061
29061
|
|
|
29062
|
+
function getNullValue(opts) {
|
|
29063
|
+
var nullValue;
|
|
29064
|
+
if ('null_value' in opts) {
|
|
29065
|
+
nullValue = parseNullValue(opts.null_value);
|
|
29066
|
+
} else if (opts.colors) {
|
|
29067
|
+
nullValue = '#eee';
|
|
29068
|
+
} else if (opts.values) {
|
|
29069
|
+
nullValue = null;
|
|
29070
|
+
} else {
|
|
29071
|
+
nullValue = -1; // kludge, to match behavior of getClassValues()
|
|
29072
|
+
}
|
|
29073
|
+
return nullValue;
|
|
29074
|
+
}
|
|
29075
|
+
|
|
29076
|
+
// Parse command line string arguments to the correct data type
|
|
29077
|
+
function parseNullValue(val) {
|
|
29078
|
+
if (utils.isString(val) && !isNaN(+val)) {
|
|
29079
|
+
val = +val;
|
|
29080
|
+
}
|
|
29081
|
+
if (val === 'null') {
|
|
29082
|
+
val = null;
|
|
29083
|
+
}
|
|
29084
|
+
return val;
|
|
29085
|
+
}
|
|
29086
|
+
|
|
29062
29087
|
function getClassValues(method, n, opts) {
|
|
29063
29088
|
var categorical = method == 'categorical' || method == 'non-adjacent';
|
|
29064
29089
|
var colorArg = opts.colors && opts.colors.length == 1 ? opts.colors[0] : null;
|
|
@@ -29132,27 +29157,33 @@ ${svg}
|
|
|
29132
29157
|
return values;
|
|
29133
29158
|
}
|
|
29134
29159
|
|
|
29135
|
-
var sequential = ['quantile', 'nice', 'equal-interval', 'hybrid'];
|
|
29160
|
+
var sequential = ['quantile', 'nice', 'equal-interval', 'hybrid', 'breaks'];
|
|
29136
29161
|
var all = ['non-adjacent', 'indexed', 'categorical'].concat(sequential);
|
|
29137
29162
|
|
|
29138
|
-
function getClassifyMethod(opts,
|
|
29163
|
+
function getClassifyMethod(opts, dataType) {
|
|
29139
29164
|
var method;
|
|
29140
29165
|
if (opts.method) {
|
|
29141
29166
|
method = opts.method;
|
|
29167
|
+
} else if (opts.breaks) {
|
|
29168
|
+
method = 'breaks';
|
|
29142
29169
|
} else if (opts.index_field) {
|
|
29143
29170
|
method = 'indexed';
|
|
29144
|
-
} else if (opts.categories ||
|
|
29171
|
+
} else if (opts.categories || dataType == 'string') {
|
|
29145
29172
|
method = 'categorical';
|
|
29146
|
-
} else if (
|
|
29173
|
+
} else if (dataType == 'number') {
|
|
29147
29174
|
method = 'quantile'; // TODO: validate data field
|
|
29175
|
+
} else if (dataType == 'date' || dataType == 'object') {
|
|
29176
|
+
stop('Data type does not support classification:', dataType);
|
|
29177
|
+
} else if (dataType === null) {
|
|
29178
|
+
// data field is empty
|
|
29179
|
+
return null; // kludge
|
|
29148
29180
|
} else {
|
|
29149
|
-
|
|
29150
|
-
stop('Missing a data field and/or classification method');
|
|
29181
|
+
stop('Unable to determine which classification method to use.');
|
|
29151
29182
|
}
|
|
29152
29183
|
if (!all.includes(method)) {
|
|
29153
29184
|
stop('Not a recognized classification method:', method);
|
|
29154
29185
|
}
|
|
29155
|
-
if (sequential.includes(method) &&
|
|
29186
|
+
if (sequential.includes(method) && dataType != 'number' && dataType !== null) {
|
|
29156
29187
|
stop('The', method, 'method requires a numerical data field');
|
|
29157
29188
|
}
|
|
29158
29189
|
return method;
|
|
@@ -29165,7 +29196,7 @@ ${svg}
|
|
|
29165
29196
|
var opts = optsArg || {};
|
|
29166
29197
|
var records = lyr.data && lyr.data.getRecords();
|
|
29167
29198
|
var valuesAreColors = !!opts.colors;
|
|
29168
|
-
var dataField,
|
|
29199
|
+
var dataField, fieldType, outputField;
|
|
29169
29200
|
var values, nullValue;
|
|
29170
29201
|
var classifyByValue, classifyByRecordId;
|
|
29171
29202
|
var numClasses, numValues;
|
|
@@ -29179,9 +29210,10 @@ ${svg}
|
|
|
29179
29210
|
//
|
|
29180
29211
|
if (opts.index_field) {
|
|
29181
29212
|
dataField = opts.index_field;
|
|
29182
|
-
|
|
29213
|
+
fieldType = getColumnType(opts.field, records);
|
|
29214
|
+
} else if (opts.field) {
|
|
29183
29215
|
dataField = opts.field;
|
|
29184
|
-
|
|
29216
|
+
fieldType = getColumnType(opts.field, records);
|
|
29185
29217
|
}
|
|
29186
29218
|
if (dataField) {
|
|
29187
29219
|
requireDataField(lyr.data, dataField);
|
|
@@ -29189,7 +29221,7 @@ ${svg}
|
|
|
29189
29221
|
|
|
29190
29222
|
// get classification method
|
|
29191
29223
|
//
|
|
29192
|
-
method = getClassifyMethod(opts,
|
|
29224
|
+
method = getClassifyMethod(opts, fieldType);
|
|
29193
29225
|
|
|
29194
29226
|
// validate classification method
|
|
29195
29227
|
if (method == 'non-adjacent') {
|
|
@@ -29207,6 +29239,7 @@ ${svg}
|
|
|
29207
29239
|
// get the number of classes and the number of values
|
|
29208
29240
|
//
|
|
29209
29241
|
// expand categories if value is '*'
|
|
29242
|
+
// use all unique values if categories option is missing
|
|
29210
29243
|
if (method == 'categorical') {
|
|
29211
29244
|
if ((!opts.categories || opts.categories.includes('*')) && dataField) {
|
|
29212
29245
|
opts.categories = getUniqFieldValues(records, dataField);
|
|
@@ -29248,24 +29281,16 @@ ${svg}
|
|
|
29248
29281
|
message('Colors:', formatValuesForLogging(values));
|
|
29249
29282
|
}
|
|
29250
29283
|
|
|
29251
|
-
|
|
29252
|
-
//
|
|
29253
|
-
if ('null_value' in opts) {
|
|
29254
|
-
nullValue = opts.null_value;
|
|
29255
|
-
} else if (valuesAreColors) {
|
|
29256
|
-
nullValue = '#eee';
|
|
29257
|
-
} else if (opts.values) {
|
|
29258
|
-
nullValue = null;
|
|
29259
|
-
} else {
|
|
29260
|
-
nullValue = -1; // kludge, to match behavior of getClassValues()
|
|
29261
|
-
}
|
|
29262
|
-
|
|
29284
|
+
nullValue = getNullValue(opts);
|
|
29263
29285
|
|
|
29264
29286
|
// get a function to convert input data to class indexes
|
|
29265
29287
|
//
|
|
29266
|
-
if (
|
|
29288
|
+
if (fieldType === null) {
|
|
29289
|
+
// no valid data -- always return null value
|
|
29290
|
+
classifyByRecordId = function() {return nullValue;};
|
|
29291
|
+
} else if (method == 'non-adjacent') {
|
|
29267
29292
|
classifyByRecordId = getNonAdjacentClassifier(lyr, dataset, values);
|
|
29268
|
-
} else if (
|
|
29293
|
+
} else if (method == 'indexed') {
|
|
29269
29294
|
// data is pre-classified... just read the index from a field
|
|
29270
29295
|
classifyByValue = getIndexedClassifier(values, nullValue, opts);
|
|
29271
29296
|
} else if (method == 'categorical') {
|