mapshaper 0.5.93 → 0.5.96
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 +1323 -0
- package/mapshaper.js +421 -383
- package/package.json +1 -1
- package/www/mapshaper-gui.js +139 -104
- package/www/mapshaper.js +421 -383
- package/www/nacis/Makefile +0 -22
- package/www/nacis/Makefile.txt +0 -22
- package/www/nacis/images/close.png +0 -0
- package/www/nacis/images/eye.png +0 -0
- package/www/nacis/images/eye2.png +0 -0
- package/www/nacis/index.html +0 -262
- package/www/nacis/manifest.js +0 -27
- package/www/nacis/map.svg +0 -12308
package/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.5.
|
|
3
|
+
var VERSION = "0.5.95";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -4993,7 +4993,7 @@
|
|
|
4993
4993
|
this._n = 0;
|
|
4994
4994
|
this.x = 0;
|
|
4995
4995
|
this.y = 0;
|
|
4996
|
-
this.i = -1;
|
|
4996
|
+
// this.i = -1;
|
|
4997
4997
|
}
|
|
4998
4998
|
|
|
4999
4999
|
ShapeIter.prototype.hasNext = function() {
|
|
@@ -5004,7 +5004,7 @@
|
|
|
5004
5004
|
if (arc.hasNext()) {
|
|
5005
5005
|
this.x = arc.x;
|
|
5006
5006
|
this.y = arc.y;
|
|
5007
|
-
this.i = arc.i;
|
|
5007
|
+
// this.i = arc.i;
|
|
5008
5008
|
return true;
|
|
5009
5009
|
}
|
|
5010
5010
|
this.nextArc();
|
|
@@ -9461,6 +9461,9 @@
|
|
|
9461
9461
|
return rec && (rec[name] === val);
|
|
9462
9462
|
});
|
|
9463
9463
|
};
|
|
9464
|
+
obj.file_exists = function(name) {
|
|
9465
|
+
return cli.isFile(name);
|
|
9466
|
+
};
|
|
9464
9467
|
return obj;
|
|
9465
9468
|
}
|
|
9466
9469
|
|
|
@@ -19149,7 +19152,7 @@ ${svg}
|
|
|
19149
19152
|
describe: 'value (or color) to use for invalid or missing data'
|
|
19150
19153
|
})
|
|
19151
19154
|
.option('method', {
|
|
19152
|
-
describe: '
|
|
19155
|
+
describe: 'quantile, nice, equal-interval, categorical, etc.'
|
|
19153
19156
|
})
|
|
19154
19157
|
.option('quantile', {
|
|
19155
19158
|
//describe: 'shortcut for method=quantile (the default)',
|
|
@@ -27731,217 +27734,6 @@ ${svg}
|
|
|
27731
27734
|
return [lyr2];
|
|
27732
27735
|
}
|
|
27733
27736
|
|
|
27734
|
-
// TODO: support three or more stops
|
|
27735
|
-
function getGradientFunction(stops) {
|
|
27736
|
-
var min = stops[0] / 100,
|
|
27737
|
-
max = stops[1] / 100;
|
|
27738
|
-
if (stops.length != 2) {
|
|
27739
|
-
stop('Only two stops are currently supported');
|
|
27740
|
-
}
|
|
27741
|
-
if (!(min >= 0 && max <= 1 && min < max)) {
|
|
27742
|
-
stop('Invalid gradient stops:', stops);
|
|
27743
|
-
}
|
|
27744
|
-
return function(t) {
|
|
27745
|
-
return t * (max - min) + min;
|
|
27746
|
-
};
|
|
27747
|
-
}
|
|
27748
|
-
|
|
27749
|
-
function getStoppedValues(values, stops) {
|
|
27750
|
-
var interpolate = getInterpolatedValueGetter(values, null);
|
|
27751
|
-
var n = values.length;
|
|
27752
|
-
var fstop = getGradientFunction(stops);
|
|
27753
|
-
var values2 = [];
|
|
27754
|
-
var t, val;
|
|
27755
|
-
for (var i=0; i<n; i++) {
|
|
27756
|
-
t = fstop(i / (n - 1));
|
|
27757
|
-
val = interpolate(t * (n - 1));
|
|
27758
|
-
values2.push(val);
|
|
27759
|
-
}
|
|
27760
|
-
return values2;
|
|
27761
|
-
}
|
|
27762
|
-
|
|
27763
|
-
// convert a continuous index ([0, n-1], -1) to a corresponding interpolated value
|
|
27764
|
-
function getInterpolatedValueGetter(values, nullValue) {
|
|
27765
|
-
var d3 = require('d3-interpolate');
|
|
27766
|
-
var interpolators = [];
|
|
27767
|
-
var tmax = values.length - 1;
|
|
27768
|
-
for (var i=1; i<values.length; i++) {
|
|
27769
|
-
interpolators.push(d3.interpolate(values[i-1], values[i]));
|
|
27770
|
-
}
|
|
27771
|
-
return function(t) {
|
|
27772
|
-
if (t == -1) return nullValue;
|
|
27773
|
-
if ((t >= 0 && t <= tmax) === false) {
|
|
27774
|
-
error('Range error');
|
|
27775
|
-
}
|
|
27776
|
-
var i = t == tmax ? tmax - 1 : Math.floor(t);
|
|
27777
|
-
var j = t == tmax ? 1 : t % 1;
|
|
27778
|
-
return interpolators[i](j);
|
|
27779
|
-
};
|
|
27780
|
-
}
|
|
27781
|
-
|
|
27782
|
-
// return an array of n values
|
|
27783
|
-
// assumes that values can be interpolated by d3-interpolate
|
|
27784
|
-
// (colors and numbers should work)
|
|
27785
|
-
function interpolateValuesToClasses(values, n, stops) {
|
|
27786
|
-
if (values.length == n && !stops) return values;
|
|
27787
|
-
var d3 = require('d3-interpolate');
|
|
27788
|
-
var numPairs = values.length - 1;
|
|
27789
|
-
var output = [values[0]];
|
|
27790
|
-
var k, j, t, intVal;
|
|
27791
|
-
for (var i=1; i<n-1; i++) {
|
|
27792
|
-
k = i / (n-1) * numPairs;
|
|
27793
|
-
j = Math.floor(k);
|
|
27794
|
-
t = k - j;
|
|
27795
|
-
// if (convert) t = convert(t);
|
|
27796
|
-
intVal = d3.interpolate(values[j], values[j+1])(t);
|
|
27797
|
-
output.push(intVal);
|
|
27798
|
-
}
|
|
27799
|
-
output.push(values[values.length - 1]);
|
|
27800
|
-
if (stops) {
|
|
27801
|
-
output = getStoppedValues(output, stops);
|
|
27802
|
-
}
|
|
27803
|
-
return output;
|
|
27804
|
-
}
|
|
27805
|
-
|
|
27806
|
-
var index = {
|
|
27807
|
-
categorical: [],
|
|
27808
|
-
sequential: [],
|
|
27809
|
-
rainbow: [],
|
|
27810
|
-
diverging: []
|
|
27811
|
-
};
|
|
27812
|
-
var ramps;
|
|
27813
|
-
|
|
27814
|
-
function initSchemes() {
|
|
27815
|
-
if (ramps) return;
|
|
27816
|
-
ramps = {};
|
|
27817
|
-
addSchemesFromD3('categorical', 'Category10,Accent,Dark2,Paired,Pastel1,Pastel2,Set1,Set2,Set3,Tableau10');
|
|
27818
|
-
addSchemesFromD3('sequential', 'Blues,Greens,Greys,Purples,Reds,Oranges,BuGn,BuPu,GnBu,OrRd,PuBuGn,PuBu,PuRd,RdPu,YlGnBu,YlGn,YlOrBr,YlOrRd');
|
|
27819
|
-
addSchemesFromD3('rainbow', 'Cividis,CubehelixDefault,Rainbow,Warm,Cool,Sinebow,Turbo,Viridis,Magma,Inferno,Plasma');
|
|
27820
|
-
addSchemesFromD3('diverging', 'BrBG,PRGn,PRGn,PiYG,PuOr,RdBu,RdGy,RdYlBu,RdYlGn,Spectral');
|
|
27821
|
-
testLib(); // make sure these schemes are all available
|
|
27822
|
-
addCategoricalScheme('Category20',
|
|
27823
|
-
'1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5');
|
|
27824
|
-
addCategoricalScheme('Category20b',
|
|
27825
|
-
'393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6');
|
|
27826
|
-
addCategoricalScheme('Category20c',
|
|
27827
|
-
'3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9');
|
|
27828
|
-
addCategoricalScheme('Tableau20',
|
|
27829
|
-
'4c78a89ecae9f58518ffbf7954a24b88d27ab79a20f2cf5b43989483bcb6e45756ff9d9879706ebab0acd67195fcbfd2b279a2d6a5c99e765fd8b5a5');
|
|
27830
|
-
}
|
|
27831
|
-
|
|
27832
|
-
function addSchemesFromD3(type, names) {
|
|
27833
|
-
index[type] = index[type].concat(names.split(','));
|
|
27834
|
-
}
|
|
27835
|
-
|
|
27836
|
-
function addCategoricalScheme(name, str) {
|
|
27837
|
-
index.categorical.push(name);
|
|
27838
|
-
ramps[name] = unpackRamp(str);
|
|
27839
|
-
}
|
|
27840
|
-
|
|
27841
|
-
function unpackRamp(str) {
|
|
27842
|
-
var colors = [];
|
|
27843
|
-
for (var i=0, n=str.length; i<n; i+=6) {
|
|
27844
|
-
colors.push('#' + str.substr(i, 6));
|
|
27845
|
-
}
|
|
27846
|
-
return colors;
|
|
27847
|
-
}
|
|
27848
|
-
|
|
27849
|
-
function testLib() {
|
|
27850
|
-
var lib = require('d3-scale-chromatic');
|
|
27851
|
-
schemes(index.categorical);
|
|
27852
|
-
schemes(index.sequential);
|
|
27853
|
-
schemes(index.diverging);
|
|
27854
|
-
interpolators(index.sequential);
|
|
27855
|
-
interpolators(index.rainbow);
|
|
27856
|
-
interpolators(index.diverging);
|
|
27857
|
-
|
|
27858
|
-
function schemes(arr) {
|
|
27859
|
-
arr.forEach(function(name) {
|
|
27860
|
-
if (!lib['scheme' + name]) {
|
|
27861
|
-
message('Warning: missing data for', name);
|
|
27862
|
-
}
|
|
27863
|
-
});
|
|
27864
|
-
}
|
|
27865
|
-
|
|
27866
|
-
function interpolators(arr) {
|
|
27867
|
-
arr.forEach(function(name) {
|
|
27868
|
-
if (!lib['interpolate' + name]) {
|
|
27869
|
-
message('Missing interpolator for', name);
|
|
27870
|
-
}
|
|
27871
|
-
});
|
|
27872
|
-
}
|
|
27873
|
-
}
|
|
27874
|
-
|
|
27875
|
-
function printColorSchemeNames() {
|
|
27876
|
-
initSchemes();
|
|
27877
|
-
print('Built-in color schemes (from d3):');
|
|
27878
|
-
print ('Categorical\n' + formatStringsAsGrid(index.categorical));
|
|
27879
|
-
print ('\nSequential\n' + formatStringsAsGrid(index.sequential));
|
|
27880
|
-
print ('\nDiverging\n' + formatStringsAsGrid(index.diverging));
|
|
27881
|
-
print ('\nMulti-hue/rainbow\n' + formatStringsAsGrid(index.rainbow));
|
|
27882
|
-
}
|
|
27883
|
-
|
|
27884
|
-
function getCategoricalColorScheme(name, n) {
|
|
27885
|
-
var colors;
|
|
27886
|
-
initSchemes();
|
|
27887
|
-
if (!isColorSchemeName(name)) {
|
|
27888
|
-
stop('Unknown color scheme name:', name);
|
|
27889
|
-
} else if (isCategoricalColorScheme(name)) {
|
|
27890
|
-
colors = ramps[name] || require('d3-scale-chromatic')['scheme' + name];
|
|
27891
|
-
} else {
|
|
27892
|
-
colors = getColorRamp(name, n);
|
|
27893
|
-
}
|
|
27894
|
-
if (n > colors.length) {
|
|
27895
|
-
stop(name, 'does not contain', n, 'colors');
|
|
27896
|
-
}
|
|
27897
|
-
return colors.slice(0, n);
|
|
27898
|
-
}
|
|
27899
|
-
|
|
27900
|
-
function isColorSchemeName(name) {
|
|
27901
|
-
initSchemes();
|
|
27902
|
-
return index.categorical.includes(name) || index.sequential.includes(name) ||
|
|
27903
|
-
index.diverging.includes(name) || index.rainbow.includes(name);
|
|
27904
|
-
}
|
|
27905
|
-
|
|
27906
|
-
function isCategoricalColorScheme(name) {
|
|
27907
|
-
initSchemes();
|
|
27908
|
-
return index.categorical.includes(name);
|
|
27909
|
-
}
|
|
27910
|
-
|
|
27911
|
-
function getColorRamp(name, n, stops) {
|
|
27912
|
-
initSchemes();
|
|
27913
|
-
var lib = require('d3-scale-chromatic');
|
|
27914
|
-
var ramps = lib['scheme' + name];
|
|
27915
|
-
var interpolate = lib['interpolate' + name];
|
|
27916
|
-
var ramp;
|
|
27917
|
-
if (!ramps && !interpolate) {
|
|
27918
|
-
stop('Unknown color scheme name:', name);
|
|
27919
|
-
}
|
|
27920
|
-
if (index.categorical.includes(name)) {
|
|
27921
|
-
stop(name, ' is a categorical color scheme (expected a sequential color scheme)');
|
|
27922
|
-
}
|
|
27923
|
-
if (ramps && ramps[n]) {
|
|
27924
|
-
ramp = ramps[n];
|
|
27925
|
-
} else {
|
|
27926
|
-
ramp = getInterpolatedRamp(interpolate, n);
|
|
27927
|
-
}
|
|
27928
|
-
if (stops) {
|
|
27929
|
-
ramp = getStoppedValues(ramp, stops);
|
|
27930
|
-
}
|
|
27931
|
-
return ramp;
|
|
27932
|
-
}
|
|
27933
|
-
|
|
27934
|
-
function getInterpolatedRamp(interpolate, n) {
|
|
27935
|
-
if (n > 0 === false || !utils.isInteger(n)) {
|
|
27936
|
-
error('Expected a positive integer');
|
|
27937
|
-
}
|
|
27938
|
-
var ramp = [];
|
|
27939
|
-
for (var i=0; i<n; i++) {
|
|
27940
|
-
ramp.push(interpolate(i / (n - 1)));
|
|
27941
|
-
}
|
|
27942
|
-
return ramp;
|
|
27943
|
-
}
|
|
27944
|
-
|
|
27945
27737
|
var scaledIntervals =
|
|
27946
27738
|
[10,12,15,18,20,22,25,30,35,40,45,50,60,70,80,90,100];
|
|
27947
27739
|
var precisions =
|
|
@@ -28071,6 +27863,78 @@ ${svg}
|
|
|
28071
27863
|
return s;
|
|
28072
27864
|
}
|
|
28073
27865
|
|
|
27866
|
+
// TODO: support three or more stops
|
|
27867
|
+
function getGradientFunction(stops) {
|
|
27868
|
+
var min = stops[0] / 100,
|
|
27869
|
+
max = stops[1] / 100;
|
|
27870
|
+
if (stops.length != 2) {
|
|
27871
|
+
stop('Only two stops are currently supported');
|
|
27872
|
+
}
|
|
27873
|
+
if (!(min >= 0 && max <= 1 && min < max)) {
|
|
27874
|
+
stop('Invalid gradient stops:', stops);
|
|
27875
|
+
}
|
|
27876
|
+
return function(t) {
|
|
27877
|
+
return t * (max - min) + min;
|
|
27878
|
+
};
|
|
27879
|
+
}
|
|
27880
|
+
|
|
27881
|
+
function getStoppedValues(values, stops) {
|
|
27882
|
+
var interpolate = getInterpolatedValueGetter(values, null);
|
|
27883
|
+
var n = values.length;
|
|
27884
|
+
var fstop = getGradientFunction(stops);
|
|
27885
|
+
var values2 = [];
|
|
27886
|
+
var t, val;
|
|
27887
|
+
for (var i=0; i<n; i++) {
|
|
27888
|
+
t = fstop(i / (n - 1));
|
|
27889
|
+
val = interpolate(t * (n - 1));
|
|
27890
|
+
values2.push(val);
|
|
27891
|
+
}
|
|
27892
|
+
return values2;
|
|
27893
|
+
}
|
|
27894
|
+
|
|
27895
|
+
// convert a continuous index ([0, n-1], -1) to a corresponding interpolated value
|
|
27896
|
+
function getInterpolatedValueGetter(values, nullValue) {
|
|
27897
|
+
var d3 = require('d3-interpolate');
|
|
27898
|
+
var interpolators = [];
|
|
27899
|
+
var tmax = values.length - 1;
|
|
27900
|
+
for (var i=1; i<values.length; i++) {
|
|
27901
|
+
interpolators.push(d3.interpolate(values[i-1], values[i]));
|
|
27902
|
+
}
|
|
27903
|
+
return function(t) {
|
|
27904
|
+
if (t == -1) return nullValue;
|
|
27905
|
+
if ((t >= 0 && t <= tmax) === false) {
|
|
27906
|
+
error('Range error');
|
|
27907
|
+
}
|
|
27908
|
+
var i = t == tmax ? tmax - 1 : Math.floor(t);
|
|
27909
|
+
var j = t == tmax ? 1 : t % 1;
|
|
27910
|
+
return interpolators[i](j);
|
|
27911
|
+
};
|
|
27912
|
+
}
|
|
27913
|
+
|
|
27914
|
+
// return an array of n values
|
|
27915
|
+
// assumes that values can be interpolated by d3-interpolate
|
|
27916
|
+
// (colors and numbers should work)
|
|
27917
|
+
function interpolateValuesToClasses(values, n, stops) {
|
|
27918
|
+
if (values.length == n && !stops) return values;
|
|
27919
|
+
var d3 = require('d3-interpolate');
|
|
27920
|
+
var numPairs = values.length - 1;
|
|
27921
|
+
var output = [values[0]];
|
|
27922
|
+
var k, j, t, intVal;
|
|
27923
|
+
for (var i=1; i<n-1; i++) {
|
|
27924
|
+
k = i / (n-1) * numPairs;
|
|
27925
|
+
j = Math.floor(k);
|
|
27926
|
+
t = k - j;
|
|
27927
|
+
// if (convert) t = convert(t);
|
|
27928
|
+
intVal = d3.interpolate(values[j], values[j+1])(t);
|
|
27929
|
+
output.push(intVal);
|
|
27930
|
+
}
|
|
27931
|
+
output.push(values[values.length - 1]);
|
|
27932
|
+
if (stops) {
|
|
27933
|
+
output = getStoppedValues(output, stops);
|
|
27934
|
+
}
|
|
27935
|
+
return output;
|
|
27936
|
+
}
|
|
27937
|
+
|
|
28074
27938
|
// convert an index (0 ... n-1, -1, -2) to a corresponding discreet value
|
|
28075
27939
|
function getDiscreteValueGetter(values, nullValue, otherValue) {
|
|
28076
27940
|
var n = values.length;
|
|
@@ -28677,35 +28541,6 @@ ${svg}
|
|
|
28677
28541
|
};
|
|
28678
28542
|
}
|
|
28679
28543
|
|
|
28680
|
-
function getIndexedClassifier(values, nullVal, opts) {
|
|
28681
|
-
// TODO: handle continuous classification
|
|
28682
|
-
var numBuckets = values.length;
|
|
28683
|
-
var classToValue = getOutputFunction(values, nullVal, opts);
|
|
28684
|
-
|
|
28685
|
-
return function(val) {
|
|
28686
|
-
var idx = utils.isInteger(val) && val >= 0 && val < numBuckets ? val : -1;
|
|
28687
|
-
return classToValue(idx);
|
|
28688
|
-
};
|
|
28689
|
-
}
|
|
28690
|
-
|
|
28691
|
-
// returns the number of classes, based on the largest class index found
|
|
28692
|
-
function validateClassIndexField(records, name) {
|
|
28693
|
-
var invalid = [];
|
|
28694
|
-
var maxId = -1;
|
|
28695
|
-
records.forEach(function(d) {
|
|
28696
|
-
var val = (d || {})[name];
|
|
28697
|
-
if (!utils.isInteger(val) || val < -2) {
|
|
28698
|
-
invalid.push(val);
|
|
28699
|
-
} else {
|
|
28700
|
-
maxId = Math.max(maxId, val);
|
|
28701
|
-
}
|
|
28702
|
-
});
|
|
28703
|
-
if (invalid.length > 0) {
|
|
28704
|
-
stop(`Class index field contains invalid value(s): ${invalid.slice(0, 5)}`);
|
|
28705
|
-
}
|
|
28706
|
-
return maxId + 1;
|
|
28707
|
-
}
|
|
28708
|
-
|
|
28709
28544
|
// Returns a function for constructing a query function that accepts an arc id and
|
|
28710
28545
|
// returns information about the polygon or polygons that use the given arc.
|
|
28711
28546
|
// TODO: explain this better.
|
|
@@ -29002,64 +28837,321 @@ ${svg}
|
|
|
29002
28837
|
};
|
|
29003
28838
|
}
|
|
29004
28839
|
|
|
28840
|
+
function getIndexedClassifier(values, nullVal, opts) {
|
|
28841
|
+
// TODO: handle continuous classification
|
|
28842
|
+
var numBuckets = values.length;
|
|
28843
|
+
var classToValue = getOutputFunction(values, nullVal, opts);
|
|
28844
|
+
|
|
28845
|
+
return function(val) {
|
|
28846
|
+
var idx = utils.isInteger(val) && val >= 0 && val < numBuckets ? val : -1;
|
|
28847
|
+
return classToValue(idx);
|
|
28848
|
+
};
|
|
28849
|
+
}
|
|
28850
|
+
|
|
28851
|
+
// returns the number of classes, based on the largest class index found
|
|
28852
|
+
function getIndexedClassCount(records, name) {
|
|
28853
|
+
var invalid = [];
|
|
28854
|
+
var maxId = -1;
|
|
28855
|
+
records.forEach(function(d) {
|
|
28856
|
+
var val = (d || {})[name];
|
|
28857
|
+
if (!utils.isInteger(val) || val < -2) {
|
|
28858
|
+
invalid.push(val);
|
|
28859
|
+
} else {
|
|
28860
|
+
maxId = Math.max(maxId, val);
|
|
28861
|
+
}
|
|
28862
|
+
});
|
|
28863
|
+
if (invalid.length > 0) {
|
|
28864
|
+
stop(`Class index field contains invalid value(s): ${invalid.slice(0, 5)}`);
|
|
28865
|
+
}
|
|
28866
|
+
return maxId + 1;
|
|
28867
|
+
}
|
|
28868
|
+
|
|
28869
|
+
var index = {
|
|
28870
|
+
categorical: [],
|
|
28871
|
+
sequential: [],
|
|
28872
|
+
rainbow: [],
|
|
28873
|
+
diverging: []
|
|
28874
|
+
};
|
|
28875
|
+
var ramps;
|
|
28876
|
+
|
|
28877
|
+
function initSchemes() {
|
|
28878
|
+
if (ramps) return;
|
|
28879
|
+
ramps = {};
|
|
28880
|
+
addSchemesFromD3('categorical', 'Category10,Accent,Dark2,Paired,Pastel1,Pastel2,Set1,Set2,Set3,Tableau10');
|
|
28881
|
+
addSchemesFromD3('sequential', 'Blues,Greens,Greys,Purples,Reds,Oranges,BuGn,BuPu,GnBu,OrRd,PuBuGn,PuBu,PuRd,RdPu,YlGnBu,YlGn,YlOrBr,YlOrRd');
|
|
28882
|
+
addSchemesFromD3('rainbow', 'Cividis,CubehelixDefault,Rainbow,Warm,Cool,Sinebow,Turbo,Viridis,Magma,Inferno,Plasma');
|
|
28883
|
+
addSchemesFromD3('diverging', 'BrBG,PRGn,PRGn,PiYG,PuOr,RdBu,RdGy,RdYlBu,RdYlGn,Spectral');
|
|
28884
|
+
testLib(); // make sure these schemes are all available
|
|
28885
|
+
addCategoricalScheme('Category20',
|
|
28886
|
+
'1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5');
|
|
28887
|
+
addCategoricalScheme('Category20b',
|
|
28888
|
+
'393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6');
|
|
28889
|
+
addCategoricalScheme('Category20c',
|
|
28890
|
+
'3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9');
|
|
28891
|
+
addCategoricalScheme('Tableau20',
|
|
28892
|
+
'4c78a89ecae9f58518ffbf7954a24b88d27ab79a20f2cf5b43989483bcb6e45756ff9d9879706ebab0acd67195fcbfd2b279a2d6a5c99e765fd8b5a5');
|
|
28893
|
+
}
|
|
28894
|
+
|
|
28895
|
+
function addSchemesFromD3(type, names) {
|
|
28896
|
+
index[type] = index[type].concat(names.split(','));
|
|
28897
|
+
}
|
|
28898
|
+
|
|
28899
|
+
function addCategoricalScheme(name, str) {
|
|
28900
|
+
index.categorical.push(name);
|
|
28901
|
+
ramps[name] = unpackRamp(str);
|
|
28902
|
+
}
|
|
28903
|
+
|
|
28904
|
+
function unpackRamp(str) {
|
|
28905
|
+
var colors = [];
|
|
28906
|
+
for (var i=0, n=str.length; i<n; i+=6) {
|
|
28907
|
+
colors.push('#' + str.substr(i, 6));
|
|
28908
|
+
}
|
|
28909
|
+
return colors;
|
|
28910
|
+
}
|
|
28911
|
+
|
|
28912
|
+
function testLib() {
|
|
28913
|
+
var lib = require('d3-scale-chromatic');
|
|
28914
|
+
schemes(index.categorical);
|
|
28915
|
+
schemes(index.sequential);
|
|
28916
|
+
schemes(index.diverging);
|
|
28917
|
+
interpolators(index.sequential);
|
|
28918
|
+
interpolators(index.rainbow);
|
|
28919
|
+
interpolators(index.diverging);
|
|
28920
|
+
|
|
28921
|
+
function schemes(arr) {
|
|
28922
|
+
arr.forEach(function(name) {
|
|
28923
|
+
if (!lib['scheme' + name]) {
|
|
28924
|
+
message('Warning: missing data for', name);
|
|
28925
|
+
}
|
|
28926
|
+
});
|
|
28927
|
+
}
|
|
28928
|
+
|
|
28929
|
+
function interpolators(arr) {
|
|
28930
|
+
arr.forEach(function(name) {
|
|
28931
|
+
if (!lib['interpolate' + name]) {
|
|
28932
|
+
message('Missing interpolator for', name);
|
|
28933
|
+
}
|
|
28934
|
+
});
|
|
28935
|
+
}
|
|
28936
|
+
}
|
|
28937
|
+
|
|
28938
|
+
function printColorSchemeNames() {
|
|
28939
|
+
initSchemes();
|
|
28940
|
+
print('Built-in color schemes (from d3):');
|
|
28941
|
+
print ('Categorical\n' + formatStringsAsGrid(index.categorical));
|
|
28942
|
+
print ('\nSequential\n' + formatStringsAsGrid(index.sequential));
|
|
28943
|
+
print ('\nDiverging\n' + formatStringsAsGrid(index.diverging));
|
|
28944
|
+
print ('\nMulti-hue/rainbow\n' + formatStringsAsGrid(index.rainbow));
|
|
28945
|
+
}
|
|
28946
|
+
|
|
28947
|
+
function getCategoricalColorScheme(name, n) {
|
|
28948
|
+
var colors;
|
|
28949
|
+
initSchemes();
|
|
28950
|
+
if (!isColorSchemeName(name)) {
|
|
28951
|
+
stop('Unknown color scheme name:', name);
|
|
28952
|
+
} else if (isCategoricalColorScheme(name)) {
|
|
28953
|
+
colors = ramps[name] || require('d3-scale-chromatic')['scheme' + name];
|
|
28954
|
+
} else {
|
|
28955
|
+
colors = getColorRamp(name, n);
|
|
28956
|
+
}
|
|
28957
|
+
if (n > colors.length) {
|
|
28958
|
+
// stop(name, 'does not contain', n, 'colors');
|
|
28959
|
+
message('Color scheme has', colors.length, 'colors. Using duplication to match', n, 'categories.');
|
|
28960
|
+
colors = wrapColors(colors, n);
|
|
28961
|
+
} else {
|
|
28962
|
+
colors = colors.slice(0, n);
|
|
28963
|
+
}
|
|
28964
|
+
return colors;
|
|
28965
|
+
}
|
|
28966
|
+
|
|
28967
|
+
function wrapColors(colors, n) {
|
|
28968
|
+
while (colors.length > 0 && colors.length < n) {
|
|
28969
|
+
colors = colors.concat(colors.slice(0, n - colors.length));
|
|
28970
|
+
}
|
|
28971
|
+
return colors;
|
|
28972
|
+
}
|
|
28973
|
+
|
|
28974
|
+
function isColorSchemeName(name) {
|
|
28975
|
+
initSchemes();
|
|
28976
|
+
return index.categorical.includes(name) || index.sequential.includes(name) ||
|
|
28977
|
+
index.diverging.includes(name) || index.rainbow.includes(name);
|
|
28978
|
+
}
|
|
28979
|
+
|
|
28980
|
+
function isCategoricalColorScheme(name) {
|
|
28981
|
+
initSchemes();
|
|
28982
|
+
return index.categorical.includes(name);
|
|
28983
|
+
}
|
|
28984
|
+
|
|
28985
|
+
function getColorRamp(name, n, stops) {
|
|
28986
|
+
initSchemes();
|
|
28987
|
+
var lib = require('d3-scale-chromatic');
|
|
28988
|
+
var ramps = lib['scheme' + name];
|
|
28989
|
+
var interpolate = lib['interpolate' + name];
|
|
28990
|
+
var ramp;
|
|
28991
|
+
if (!ramps && !interpolate) {
|
|
28992
|
+
stop('Unknown color scheme name:', name);
|
|
28993
|
+
}
|
|
28994
|
+
if (index.categorical.includes(name)) {
|
|
28995
|
+
stop(name, ' is a categorical color scheme (expected a sequential color scheme)');
|
|
28996
|
+
}
|
|
28997
|
+
if (ramps && ramps[n]) {
|
|
28998
|
+
ramp = ramps[n];
|
|
28999
|
+
} else {
|
|
29000
|
+
ramp = getInterpolatedRamp(interpolate, n);
|
|
29001
|
+
}
|
|
29002
|
+
if (stops) {
|
|
29003
|
+
ramp = getStoppedValues(ramp, stops);
|
|
29004
|
+
}
|
|
29005
|
+
return ramp;
|
|
29006
|
+
}
|
|
29007
|
+
|
|
29008
|
+
function getInterpolatedRamp(interpolate, n) {
|
|
29009
|
+
if (n > 0 === false || !utils.isInteger(n)) {
|
|
29010
|
+
error('Expected a positive integer');
|
|
29011
|
+
}
|
|
29012
|
+
var ramp = [];
|
|
29013
|
+
for (var i=0; i<n; i++) {
|
|
29014
|
+
ramp.push(interpolate(i / (n - 1)));
|
|
29015
|
+
}
|
|
29016
|
+
return ramp;
|
|
29017
|
+
}
|
|
29018
|
+
|
|
29019
|
+
function getClassValues(method, n, opts) {
|
|
29020
|
+
var categorical = method == 'categorical' || method == 'non-adjacent';
|
|
29021
|
+
var colorArg = opts.colors ? opts.colors[0] : null;
|
|
29022
|
+
var colorScheme;
|
|
29023
|
+
|
|
29024
|
+
if (isColorSchemeName(colorArg)) {
|
|
29025
|
+
colorScheme = colorArg;
|
|
29026
|
+
} else if (colorArg == 'random') {
|
|
29027
|
+
colorScheme = categorical ? 'Tableau20' : 'BuGn'; // TODO: randomize
|
|
29028
|
+
} else if (opts.colors) {
|
|
29029
|
+
// validate colors
|
|
29030
|
+
opts.colors.forEach(parseColor);
|
|
29031
|
+
}
|
|
29032
|
+
|
|
29033
|
+
if (categorical) {
|
|
29034
|
+
if (colorScheme && isCategoricalColorScheme(colorScheme)) {
|
|
29035
|
+
return getCategoricalColorScheme(colorScheme, n);
|
|
29036
|
+
} else if (colorScheme) {
|
|
29037
|
+
// assume we have a sequential ramp
|
|
29038
|
+
return getColorRamp(colorScheme, n, opts.stops);
|
|
29039
|
+
} else if (opts.colors || opts.values) {
|
|
29040
|
+
return getCategoricalValues(opts.colors || opts.values, n);
|
|
29041
|
+
} else {
|
|
29042
|
+
// numerical indexes seem to make sense for non-adjacent and categorical colors
|
|
29043
|
+
return getIndexes(n);
|
|
29044
|
+
}
|
|
29045
|
+
} else {
|
|
29046
|
+
// sequential values
|
|
29047
|
+
if (colorScheme) {
|
|
29048
|
+
return getColorRamp(colorScheme, n, opts.stops);
|
|
29049
|
+
} else if (opts.colors || opts.values) {
|
|
29050
|
+
return getInterpolableValues(opts.colors || opts.values, n, opts);
|
|
29051
|
+
} else {
|
|
29052
|
+
// TODO: rethink this
|
|
29053
|
+
// return getInterpolableValues([0, 1], n, opts);
|
|
29054
|
+
return getIndexes(n);
|
|
29055
|
+
}
|
|
29056
|
+
}
|
|
29057
|
+
}
|
|
29058
|
+
|
|
29059
|
+
|
|
29060
|
+
function getCategoricalValues(values, n) {
|
|
29061
|
+
if (n != values.length) {
|
|
29062
|
+
stop('Mismatch in number of categories and number of values');
|
|
29063
|
+
}
|
|
29064
|
+
return values;
|
|
29065
|
+
}
|
|
29066
|
+
|
|
29067
|
+
function getIndexes(n) {
|
|
29068
|
+
var vals = [];
|
|
29069
|
+
for (var i=0; i<n; i++) {
|
|
29070
|
+
vals.push(i);
|
|
29071
|
+
}
|
|
29072
|
+
return vals;
|
|
29073
|
+
}
|
|
29074
|
+
|
|
29075
|
+
// TODO: check for non-interpolatable value types (e.g. boolean, text)
|
|
29076
|
+
function getInterpolableValues(arr, n, opts) {
|
|
29077
|
+
var values = parseValues(arr);
|
|
29078
|
+
if (n != values.length || opts.stops) {
|
|
29079
|
+
return interpolateValuesToClasses(values, n, opts.stops);
|
|
29080
|
+
}
|
|
29081
|
+
return values;
|
|
29082
|
+
}
|
|
29083
|
+
|
|
29084
|
+
// convert strings to numbers if they all parse as numbers
|
|
29085
|
+
// arr: an array of strings
|
|
29086
|
+
function parseValues(strings) {
|
|
29087
|
+
var values = strings;
|
|
29088
|
+
if (strings.every(utils.parseNumber)) {
|
|
29089
|
+
values = strings.map(function(str) {
|
|
29090
|
+
return +str;
|
|
29091
|
+
});
|
|
29092
|
+
}
|
|
29093
|
+
return values;
|
|
29094
|
+
}
|
|
29095
|
+
|
|
29096
|
+
var sequential = ['quantile', 'nice', 'equal-interval', 'hybrid'];
|
|
29097
|
+
var all = ['non-adjacent', 'indexed', 'categorical'].concat(sequential);
|
|
29098
|
+
|
|
29099
|
+
function getClassifyMethod(opts, dataFieldType) {
|
|
29100
|
+
var method;
|
|
29101
|
+
if (opts.method) {
|
|
29102
|
+
method = opts.method;
|
|
29103
|
+
} else if (opts.index_field) {
|
|
29104
|
+
method = 'indexed';
|
|
29105
|
+
} else if (opts.categories || dataFieldType == 'string') {
|
|
29106
|
+
method = 'categorical';
|
|
29107
|
+
} else if (dataFieldType == 'number') {
|
|
29108
|
+
method = 'quantile'; // TODO: validate data field
|
|
29109
|
+
} else {
|
|
29110
|
+
stop('Unable to determine which classification method to use.');
|
|
29111
|
+
}
|
|
29112
|
+
if (!all.includes(method)) {
|
|
29113
|
+
stop('Not a recognized classification method:', method);
|
|
29114
|
+
}
|
|
29115
|
+
if (sequential.includes(method) && dataFieldType != 'number') {
|
|
29116
|
+
stop('The', method, 'method requires a numerical data field');
|
|
29117
|
+
}
|
|
29118
|
+
return method;
|
|
29119
|
+
}
|
|
29120
|
+
|
|
29005
29121
|
cmd.classify = function(lyr, dataset, optsArg) {
|
|
29006
29122
|
if (!lyr.data) {
|
|
29007
29123
|
initDataTable(lyr);
|
|
29008
29124
|
}
|
|
29009
29125
|
var opts = optsArg || {};
|
|
29010
29126
|
var records = lyr.data && lyr.data.getRecords();
|
|
29011
|
-
var
|
|
29012
|
-
var
|
|
29013
|
-
var
|
|
29014
|
-
var
|
|
29127
|
+
var valuesAreColors = !!opts.colors;
|
|
29128
|
+
var dataField, dataFieldType, outputField;
|
|
29129
|
+
var values, nullValue;
|
|
29130
|
+
var classifyByValue, classifyByRecordId;
|
|
29015
29131
|
var numClasses, numValues;
|
|
29016
|
-
var dataField, outputField;
|
|
29017
29132
|
var method;
|
|
29018
29133
|
|
|
29019
|
-
|
|
29020
|
-
|
|
29021
|
-
if (!utils.isInteger(opts.classes) || opts.classes > 1 === false) {
|
|
29022
|
-
stop('Invalid number of classes:', opts.classes, '(expected a value greater than 1)');
|
|
29023
|
-
}
|
|
29024
|
-
numClasses = opts.classes;
|
|
29025
|
-
}
|
|
29026
|
-
|
|
29027
|
-
// TODO: better validation of breaks values
|
|
29028
|
-
if (opts.breaks) {
|
|
29029
|
-
numClasses = opts.breaks.length + 1;
|
|
29134
|
+
if (opts.color_scheme) {
|
|
29135
|
+
stop('color-scheme is not a valid option, use colors instead');
|
|
29030
29136
|
}
|
|
29031
29137
|
|
|
29138
|
+
// get data field to use for classification
|
|
29139
|
+
//
|
|
29032
29140
|
if (opts.index_field) {
|
|
29033
29141
|
dataField = opts.index_field;
|
|
29034
|
-
if (numClasses > 0 === false) {
|
|
29035
|
-
stop('The index-field= option requires the classes= option to be set');
|
|
29036
|
-
}
|
|
29037
|
-
// You can't infer the number of classes by looking at index values;
|
|
29038
|
-
// this can cause unwanted interpolation if one or more values are
|
|
29039
|
-
// not present in the index field
|
|
29040
|
-
// numClasses = validateClassIndexField(records, opts.index_field);
|
|
29041
|
-
|
|
29042
29142
|
} else if (opts.field) {
|
|
29043
29143
|
dataField = opts.field;
|
|
29144
|
+
dataFieldType = getColumnType(opts.field, records);
|
|
29044
29145
|
}
|
|
29045
|
-
|
|
29046
|
-
|
|
29047
|
-
if (dataField && opts.categories && opts.categories.includes('*')) {
|
|
29048
|
-
opts.categories = getUniqFieldValues(records, dataField);
|
|
29146
|
+
if (dataField) {
|
|
29147
|
+
requireDataField(lyr.data, dataField);
|
|
29049
29148
|
}
|
|
29050
29149
|
|
|
29051
29150
|
// get classification method
|
|
29052
29151
|
//
|
|
29053
|
-
|
|
29054
|
-
method = opts.method;
|
|
29055
|
-
} else if (opts.categories) {
|
|
29056
|
-
method = 'categorical';
|
|
29057
|
-
} else if (opts.index_field) {
|
|
29058
|
-
method = 'indexed';
|
|
29059
|
-
} else {
|
|
29060
|
-
method = 'quantile'; // TODO: validate data field
|
|
29061
|
-
}
|
|
29152
|
+
method = getClassifyMethod(opts, dataFieldType);
|
|
29062
29153
|
|
|
29154
|
+
// validate classification method
|
|
29063
29155
|
if (method == 'non-adjacent') {
|
|
29064
29156
|
if (lyr.geometry_type != 'polygon') {
|
|
29065
29157
|
stop('The non-adjacent option requires a polygon layer');
|
|
@@ -29069,83 +29161,70 @@ ${svg}
|
|
|
29069
29161
|
}
|
|
29070
29162
|
} else if (!dataField) {
|
|
29071
29163
|
stop('Missing a data field to classify');
|
|
29072
|
-
} else {
|
|
29073
|
-
requireDataField(lyr.data, dataField);
|
|
29074
29164
|
}
|
|
29075
29165
|
|
|
29076
|
-
if (numClasses) {
|
|
29077
|
-
numValues = opts.continuous ? numClasses + 1 : numClasses;
|
|
29078
|
-
}
|
|
29079
29166
|
|
|
29080
|
-
//
|
|
29081
|
-
|
|
29082
|
-
|
|
29083
|
-
|
|
29167
|
+
// get the number of classes and the number of values
|
|
29168
|
+
//
|
|
29169
|
+
// expand categories if value is '*'
|
|
29170
|
+
if (method == 'categorical') {
|
|
29171
|
+
if ((!opts.categories || opts.categories.includes('*')) && dataField) {
|
|
29172
|
+
opts.categories = getUniqFieldValues(records, dataField);
|
|
29084
29173
|
}
|
|
29085
|
-
colorScheme = opts.color_scheme;
|
|
29086
|
-
} else if (opts.colors && isColorSchemeName(opts.colors[0])) {
|
|
29087
|
-
colorScheme = opts.colors[0];
|
|
29088
|
-
} else if (opts.colors) {
|
|
29089
|
-
opts.colors.forEach(parseColor); // validate colors -- error if unparsable
|
|
29090
29174
|
}
|
|
29091
29175
|
|
|
29092
|
-
|
|
29093
|
-
|
|
29094
|
-
|
|
29095
|
-
if (method == 'non-adjacent') {
|
|
29096
|
-
numClasses = numValues = numClasses || 5;
|
|
29097
|
-
values = getCategoricalColorScheme(colorScheme, numValues);
|
|
29098
|
-
|
|
29099
|
-
} else if (method == 'categorical') {
|
|
29100
|
-
values = getCategoricalColorScheme(colorScheme, opts.categories.length);
|
|
29101
|
-
numClasses = numValues = values.length;
|
|
29102
|
-
|
|
29103
|
-
} else {
|
|
29104
|
-
if (!numClasses) {
|
|
29105
|
-
// stop('color-scheme= option requires classes= or breaks=');
|
|
29106
|
-
numClasses = 4; // use a default number of classes
|
|
29107
|
-
numValues = opts.continuous ? numClasses + 1 : numClasses;
|
|
29108
|
-
}
|
|
29109
|
-
values = getColorRamp(colorScheme, numValues, opts.stops);
|
|
29110
|
-
}
|
|
29111
|
-
|
|
29112
|
-
} else if (opts.colors || opts.values) {
|
|
29113
|
-
values = opts.values ? parseValues(opts.values) : opts.colors;
|
|
29114
|
-
if (!numValues) {
|
|
29115
|
-
numValues = values.length;
|
|
29116
|
-
}
|
|
29117
|
-
if ((values.length != numValues || opts.stops) && numValues > 1) {
|
|
29118
|
-
// TODO: handle numValues == 1
|
|
29119
|
-
// TODO: check for non-interpolatable value types (e.g. boolean, text)
|
|
29120
|
-
values = interpolateValuesToClasses(values, numValues, opts.stops);
|
|
29176
|
+
if (opts.classes) {
|
|
29177
|
+
if (!utils.isInteger(opts.classes) || opts.classes > 1 === false) {
|
|
29178
|
+
stop('Invalid number of classes:', opts.classes, '(expected a value greater than 1)');
|
|
29121
29179
|
}
|
|
29122
|
-
|
|
29123
|
-
} else if (
|
|
29124
|
-
|
|
29125
|
-
|
|
29126
|
-
|
|
29127
|
-
}
|
|
29128
|
-
|
|
29129
|
-
if (
|
|
29130
|
-
|
|
29180
|
+
numClasses = opts.classes;
|
|
29181
|
+
} else if (method == 'indexed' && dataField) {
|
|
29182
|
+
numClasses = getIndexedClassCount(records, dataField);
|
|
29183
|
+
} else if (opts.breaks) {
|
|
29184
|
+
numClasses = opts.breaks.length + 1;
|
|
29185
|
+
} else if (method == 'categorical' && opts.categories) {
|
|
29186
|
+
numClasses = opts.categories.length;
|
|
29187
|
+
} else if (opts.colors && opts.colors.length > 1) {
|
|
29188
|
+
numClasses = opts.colors.length;
|
|
29189
|
+
} else if (opts.values && opts.values.length > 1) {
|
|
29190
|
+
numClasses = opts.values.length;
|
|
29191
|
+
} else if (method == 'non-adjacent') {
|
|
29192
|
+
numClasses = 5;
|
|
29193
|
+
} else {
|
|
29194
|
+
numClasses = 4;
|
|
29131
29195
|
}
|
|
29132
|
-
|
|
29196
|
+
numValues = opts.continuous ? numClasses + 1 : numClasses;
|
|
29133
29197
|
if (numValues > 1 === false) {
|
|
29134
|
-
stop('Missing a valid number of
|
|
29198
|
+
stop('Missing a valid number of values');
|
|
29135
29199
|
}
|
|
29136
29200
|
|
|
29201
|
+
// get colors or other values
|
|
29202
|
+
//
|
|
29203
|
+
values = getClassValues(method, numValues, opts);
|
|
29137
29204
|
if (opts.invert) {
|
|
29138
29205
|
values = values.concat().reverse();
|
|
29139
29206
|
}
|
|
29140
|
-
|
|
29141
29207
|
if (valuesAreColors) {
|
|
29142
29208
|
message('Colors:', formatValuesForLogging(values));
|
|
29143
29209
|
}
|
|
29144
29210
|
|
|
29211
|
+
// get null value
|
|
29212
|
+
//
|
|
29213
|
+
if ('null_value' in opts) {
|
|
29214
|
+
nullValue = opts.null_value;
|
|
29215
|
+
} else if (valuesAreColors) {
|
|
29216
|
+
nullValue = '#eee';
|
|
29217
|
+
} else if (opts.values) {
|
|
29218
|
+
nullValue = null;
|
|
29219
|
+
} else {
|
|
29220
|
+
nullValue = -1; // kludge, to match behavior of getClassValues()
|
|
29221
|
+
}
|
|
29222
|
+
|
|
29223
|
+
|
|
29145
29224
|
// get a function to convert input data to class indexes
|
|
29146
29225
|
//
|
|
29147
29226
|
if (method == 'non-adjacent') {
|
|
29148
|
-
|
|
29227
|
+
classifyByRecordId = getNonAdjacentClassifier(lyr, dataset, values);
|
|
29149
29228
|
} else if (opts.index_field) {
|
|
29150
29229
|
// data is pre-classified... just read the index from a field
|
|
29151
29230
|
classifyByValue = getIndexedClassifier(values, nullValue, opts);
|
|
@@ -29156,13 +29235,12 @@ ${svg}
|
|
|
29156
29235
|
}
|
|
29157
29236
|
|
|
29158
29237
|
if (classifyByValue) {
|
|
29159
|
-
|
|
29238
|
+
classifyByRecordId = function(id) {
|
|
29160
29239
|
var d = records[id] || {};
|
|
29161
29240
|
return classifyByValue(d[dataField]);
|
|
29162
29241
|
};
|
|
29163
29242
|
}
|
|
29164
29243
|
|
|
29165
|
-
|
|
29166
29244
|
// get the name of the output field
|
|
29167
29245
|
//
|
|
29168
29246
|
if (valuesAreColors) {
|
|
@@ -29178,23 +29256,10 @@ ${svg}
|
|
|
29178
29256
|
}
|
|
29179
29257
|
|
|
29180
29258
|
records.forEach(function(d, i) {
|
|
29181
|
-
d[outputField] =
|
|
29259
|
+
d[outputField] = classifyByRecordId(i);
|
|
29182
29260
|
});
|
|
29183
29261
|
};
|
|
29184
29262
|
|
|
29185
|
-
|
|
29186
|
-
// convert strings to numbers if they all parse as numbers
|
|
29187
|
-
// arr: an array of strings
|
|
29188
|
-
function parseValues(strings) {
|
|
29189
|
-
var values = strings;
|
|
29190
|
-
if (strings.every(utils.parseNumber)) {
|
|
29191
|
-
values = strings.map(function(str) {
|
|
29192
|
-
return +str;
|
|
29193
|
-
});
|
|
29194
|
-
}
|
|
29195
|
-
return values;
|
|
29196
|
-
}
|
|
29197
|
-
|
|
29198
29263
|
function formatValuesForLogging(arr) {
|
|
29199
29264
|
if (arr.some(val => utils.isString(val) && val.indexOf('rgb(') === 0)) {
|
|
29200
29265
|
return formatColorsAsHex(arr);
|
|
@@ -29211,15 +29276,6 @@ ${svg}
|
|
|
29211
29276
|
});
|
|
29212
29277
|
}
|
|
29213
29278
|
|
|
29214
|
-
|
|
29215
|
-
function getIndexValues(n) {
|
|
29216
|
-
var vals = [];
|
|
29217
|
-
for (var i=0; i<n; i++) {
|
|
29218
|
-
vals.push(i);
|
|
29219
|
-
}
|
|
29220
|
-
return vals;
|
|
29221
|
-
}
|
|
29222
|
-
|
|
29223
29279
|
// Remove small-area polygon rings (very simple implementation of sliver removal)
|
|
29224
29280
|
// TODO: more sophisticated sliver detection (e.g. could consider ratio of area to perimeter)
|
|
29225
29281
|
// TODO: consider merging slivers into adjacent polygons to prevent gaps from forming
|
|
@@ -35053,7 +35109,6 @@ ${svg}
|
|
|
35053
35109
|
}
|
|
35054
35110
|
|
|
35055
35111
|
|
|
35056
|
-
|
|
35057
35112
|
function snapVerticesToPoint(ids, p, arcs, final) {
|
|
35058
35113
|
ids.forEach(function(idx) {
|
|
35059
35114
|
setVertexCoords(p[0], p[1], idx, arcs);
|
|
@@ -35133,7 +35188,7 @@ ${svg}
|
|
|
35133
35188
|
function findNearestVertex(x, y, shp, arcs, spherical) {
|
|
35134
35189
|
var calcLen = spherical ? geom.greatCircleDistance : geom.distance2D,
|
|
35135
35190
|
minLen = Infinity,
|
|
35136
|
-
minX, minY,
|
|
35191
|
+
minX, minY, dist, iter;
|
|
35137
35192
|
for (var i=0; i<shp.length; i++) {
|
|
35138
35193
|
iter = arcs.getShapeIter(shp[i]);
|
|
35139
35194
|
while (iter.hasNext()) {
|
|
@@ -35142,26 +35197,10 @@ ${svg}
|
|
|
35142
35197
|
minLen = dist;
|
|
35143
35198
|
minX = iter.x;
|
|
35144
35199
|
minY = iter.y;
|
|
35145
|
-
vId = iter.i;
|
|
35146
35200
|
}
|
|
35147
35201
|
}
|
|
35148
35202
|
}
|
|
35149
|
-
return minLen < Infinity ? {x: minX, y: minY
|
|
35150
|
-
}
|
|
35151
|
-
|
|
35152
|
-
// v: vertex in {x, y, i} format
|
|
35153
|
-
function findAdjacentVertex(v, shp, arcs, offs) {
|
|
35154
|
-
var p, i;
|
|
35155
|
-
var arcEnd = offs == 1 && vertexIsArcEnd(v.i, arcs);
|
|
35156
|
-
var arcStart = offs == -1 && vertexIsArcStart(v.i, arcs);
|
|
35157
|
-
if (arcEnd || arcStart) return null;
|
|
35158
|
-
i = v.i + offs;
|
|
35159
|
-
p = getVertexCoords(i, arcs);
|
|
35160
|
-
return {
|
|
35161
|
-
i: i,
|
|
35162
|
-
x: p[0],
|
|
35163
|
-
y: p[1]
|
|
35164
|
-
};
|
|
35203
|
+
return minLen < Infinity ? {x: minX, y: minY} : null;
|
|
35165
35204
|
}
|
|
35166
35205
|
|
|
35167
35206
|
var VertexUtils = /*#__PURE__*/Object.freeze({
|
|
@@ -35174,8 +35213,7 @@ ${svg}
|
|
|
35174
35213
|
vertexIsArcEnd: vertexIsArcEnd,
|
|
35175
35214
|
vertexIsArcStart: vertexIsArcStart,
|
|
35176
35215
|
setVertexCoords: setVertexCoords,
|
|
35177
|
-
findNearestVertex: findNearestVertex
|
|
35178
|
-
findAdjacentVertex: findAdjacentVertex
|
|
35216
|
+
findNearestVertex: findNearestVertex
|
|
35179
35217
|
});
|
|
35180
35218
|
|
|
35181
35219
|
// Returns x,y coordinates of the point that is at the midpoint of each polyline feature
|