mapshaper 0.5.95 → 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 +4 -0
- package/mapshaper.js +418 -383
- package/package.json +1 -1
- package/www/mapshaper-gui.js +63 -47
- package/www/mapshaper.js +418 -383
package/www/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();
|
|
@@ -19152,7 +19152,7 @@ ${svg}
|
|
|
19152
19152
|
describe: 'value (or color) to use for invalid or missing data'
|
|
19153
19153
|
})
|
|
19154
19154
|
.option('method', {
|
|
19155
|
-
describe: '
|
|
19155
|
+
describe: 'quantile, nice, equal-interval, categorical, etc.'
|
|
19156
19156
|
})
|
|
19157
19157
|
.option('quantile', {
|
|
19158
19158
|
//describe: 'shortcut for method=quantile (the default)',
|
|
@@ -27734,217 +27734,6 @@ ${svg}
|
|
|
27734
27734
|
return [lyr2];
|
|
27735
27735
|
}
|
|
27736
27736
|
|
|
27737
|
-
// TODO: support three or more stops
|
|
27738
|
-
function getGradientFunction(stops) {
|
|
27739
|
-
var min = stops[0] / 100,
|
|
27740
|
-
max = stops[1] / 100;
|
|
27741
|
-
if (stops.length != 2) {
|
|
27742
|
-
stop('Only two stops are currently supported');
|
|
27743
|
-
}
|
|
27744
|
-
if (!(min >= 0 && max <= 1 && min < max)) {
|
|
27745
|
-
stop('Invalid gradient stops:', stops);
|
|
27746
|
-
}
|
|
27747
|
-
return function(t) {
|
|
27748
|
-
return t * (max - min) + min;
|
|
27749
|
-
};
|
|
27750
|
-
}
|
|
27751
|
-
|
|
27752
|
-
function getStoppedValues(values, stops) {
|
|
27753
|
-
var interpolate = getInterpolatedValueGetter(values, null);
|
|
27754
|
-
var n = values.length;
|
|
27755
|
-
var fstop = getGradientFunction(stops);
|
|
27756
|
-
var values2 = [];
|
|
27757
|
-
var t, val;
|
|
27758
|
-
for (var i=0; i<n; i++) {
|
|
27759
|
-
t = fstop(i / (n - 1));
|
|
27760
|
-
val = interpolate(t * (n - 1));
|
|
27761
|
-
values2.push(val);
|
|
27762
|
-
}
|
|
27763
|
-
return values2;
|
|
27764
|
-
}
|
|
27765
|
-
|
|
27766
|
-
// convert a continuous index ([0, n-1], -1) to a corresponding interpolated value
|
|
27767
|
-
function getInterpolatedValueGetter(values, nullValue) {
|
|
27768
|
-
var d3 = require('d3-interpolate');
|
|
27769
|
-
var interpolators = [];
|
|
27770
|
-
var tmax = values.length - 1;
|
|
27771
|
-
for (var i=1; i<values.length; i++) {
|
|
27772
|
-
interpolators.push(d3.interpolate(values[i-1], values[i]));
|
|
27773
|
-
}
|
|
27774
|
-
return function(t) {
|
|
27775
|
-
if (t == -1) return nullValue;
|
|
27776
|
-
if ((t >= 0 && t <= tmax) === false) {
|
|
27777
|
-
error('Range error');
|
|
27778
|
-
}
|
|
27779
|
-
var i = t == tmax ? tmax - 1 : Math.floor(t);
|
|
27780
|
-
var j = t == tmax ? 1 : t % 1;
|
|
27781
|
-
return interpolators[i](j);
|
|
27782
|
-
};
|
|
27783
|
-
}
|
|
27784
|
-
|
|
27785
|
-
// return an array of n values
|
|
27786
|
-
// assumes that values can be interpolated by d3-interpolate
|
|
27787
|
-
// (colors and numbers should work)
|
|
27788
|
-
function interpolateValuesToClasses(values, n, stops) {
|
|
27789
|
-
if (values.length == n && !stops) return values;
|
|
27790
|
-
var d3 = require('d3-interpolate');
|
|
27791
|
-
var numPairs = values.length - 1;
|
|
27792
|
-
var output = [values[0]];
|
|
27793
|
-
var k, j, t, intVal;
|
|
27794
|
-
for (var i=1; i<n-1; i++) {
|
|
27795
|
-
k = i / (n-1) * numPairs;
|
|
27796
|
-
j = Math.floor(k);
|
|
27797
|
-
t = k - j;
|
|
27798
|
-
// if (convert) t = convert(t);
|
|
27799
|
-
intVal = d3.interpolate(values[j], values[j+1])(t);
|
|
27800
|
-
output.push(intVal);
|
|
27801
|
-
}
|
|
27802
|
-
output.push(values[values.length - 1]);
|
|
27803
|
-
if (stops) {
|
|
27804
|
-
output = getStoppedValues(output, stops);
|
|
27805
|
-
}
|
|
27806
|
-
return output;
|
|
27807
|
-
}
|
|
27808
|
-
|
|
27809
|
-
var index = {
|
|
27810
|
-
categorical: [],
|
|
27811
|
-
sequential: [],
|
|
27812
|
-
rainbow: [],
|
|
27813
|
-
diverging: []
|
|
27814
|
-
};
|
|
27815
|
-
var ramps;
|
|
27816
|
-
|
|
27817
|
-
function initSchemes() {
|
|
27818
|
-
if (ramps) return;
|
|
27819
|
-
ramps = {};
|
|
27820
|
-
addSchemesFromD3('categorical', 'Category10,Accent,Dark2,Paired,Pastel1,Pastel2,Set1,Set2,Set3,Tableau10');
|
|
27821
|
-
addSchemesFromD3('sequential', 'Blues,Greens,Greys,Purples,Reds,Oranges,BuGn,BuPu,GnBu,OrRd,PuBuGn,PuBu,PuRd,RdPu,YlGnBu,YlGn,YlOrBr,YlOrRd');
|
|
27822
|
-
addSchemesFromD3('rainbow', 'Cividis,CubehelixDefault,Rainbow,Warm,Cool,Sinebow,Turbo,Viridis,Magma,Inferno,Plasma');
|
|
27823
|
-
addSchemesFromD3('diverging', 'BrBG,PRGn,PRGn,PiYG,PuOr,RdBu,RdGy,RdYlBu,RdYlGn,Spectral');
|
|
27824
|
-
testLib(); // make sure these schemes are all available
|
|
27825
|
-
addCategoricalScheme('Category20',
|
|
27826
|
-
'1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5');
|
|
27827
|
-
addCategoricalScheme('Category20b',
|
|
27828
|
-
'393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6');
|
|
27829
|
-
addCategoricalScheme('Category20c',
|
|
27830
|
-
'3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9');
|
|
27831
|
-
addCategoricalScheme('Tableau20',
|
|
27832
|
-
'4c78a89ecae9f58518ffbf7954a24b88d27ab79a20f2cf5b43989483bcb6e45756ff9d9879706ebab0acd67195fcbfd2b279a2d6a5c99e765fd8b5a5');
|
|
27833
|
-
}
|
|
27834
|
-
|
|
27835
|
-
function addSchemesFromD3(type, names) {
|
|
27836
|
-
index[type] = index[type].concat(names.split(','));
|
|
27837
|
-
}
|
|
27838
|
-
|
|
27839
|
-
function addCategoricalScheme(name, str) {
|
|
27840
|
-
index.categorical.push(name);
|
|
27841
|
-
ramps[name] = unpackRamp(str);
|
|
27842
|
-
}
|
|
27843
|
-
|
|
27844
|
-
function unpackRamp(str) {
|
|
27845
|
-
var colors = [];
|
|
27846
|
-
for (var i=0, n=str.length; i<n; i+=6) {
|
|
27847
|
-
colors.push('#' + str.substr(i, 6));
|
|
27848
|
-
}
|
|
27849
|
-
return colors;
|
|
27850
|
-
}
|
|
27851
|
-
|
|
27852
|
-
function testLib() {
|
|
27853
|
-
var lib = require('d3-scale-chromatic');
|
|
27854
|
-
schemes(index.categorical);
|
|
27855
|
-
schemes(index.sequential);
|
|
27856
|
-
schemes(index.diverging);
|
|
27857
|
-
interpolators(index.sequential);
|
|
27858
|
-
interpolators(index.rainbow);
|
|
27859
|
-
interpolators(index.diverging);
|
|
27860
|
-
|
|
27861
|
-
function schemes(arr) {
|
|
27862
|
-
arr.forEach(function(name) {
|
|
27863
|
-
if (!lib['scheme' + name]) {
|
|
27864
|
-
message('Warning: missing data for', name);
|
|
27865
|
-
}
|
|
27866
|
-
});
|
|
27867
|
-
}
|
|
27868
|
-
|
|
27869
|
-
function interpolators(arr) {
|
|
27870
|
-
arr.forEach(function(name) {
|
|
27871
|
-
if (!lib['interpolate' + name]) {
|
|
27872
|
-
message('Missing interpolator for', name);
|
|
27873
|
-
}
|
|
27874
|
-
});
|
|
27875
|
-
}
|
|
27876
|
-
}
|
|
27877
|
-
|
|
27878
|
-
function printColorSchemeNames() {
|
|
27879
|
-
initSchemes();
|
|
27880
|
-
print('Built-in color schemes (from d3):');
|
|
27881
|
-
print ('Categorical\n' + formatStringsAsGrid(index.categorical));
|
|
27882
|
-
print ('\nSequential\n' + formatStringsAsGrid(index.sequential));
|
|
27883
|
-
print ('\nDiverging\n' + formatStringsAsGrid(index.diverging));
|
|
27884
|
-
print ('\nMulti-hue/rainbow\n' + formatStringsAsGrid(index.rainbow));
|
|
27885
|
-
}
|
|
27886
|
-
|
|
27887
|
-
function getCategoricalColorScheme(name, n) {
|
|
27888
|
-
var colors;
|
|
27889
|
-
initSchemes();
|
|
27890
|
-
if (!isColorSchemeName(name)) {
|
|
27891
|
-
stop('Unknown color scheme name:', name);
|
|
27892
|
-
} else if (isCategoricalColorScheme(name)) {
|
|
27893
|
-
colors = ramps[name] || require('d3-scale-chromatic')['scheme' + name];
|
|
27894
|
-
} else {
|
|
27895
|
-
colors = getColorRamp(name, n);
|
|
27896
|
-
}
|
|
27897
|
-
if (n > colors.length) {
|
|
27898
|
-
stop(name, 'does not contain', n, 'colors');
|
|
27899
|
-
}
|
|
27900
|
-
return colors.slice(0, n);
|
|
27901
|
-
}
|
|
27902
|
-
|
|
27903
|
-
function isColorSchemeName(name) {
|
|
27904
|
-
initSchemes();
|
|
27905
|
-
return index.categorical.includes(name) || index.sequential.includes(name) ||
|
|
27906
|
-
index.diverging.includes(name) || index.rainbow.includes(name);
|
|
27907
|
-
}
|
|
27908
|
-
|
|
27909
|
-
function isCategoricalColorScheme(name) {
|
|
27910
|
-
initSchemes();
|
|
27911
|
-
return index.categorical.includes(name);
|
|
27912
|
-
}
|
|
27913
|
-
|
|
27914
|
-
function getColorRamp(name, n, stops) {
|
|
27915
|
-
initSchemes();
|
|
27916
|
-
var lib = require('d3-scale-chromatic');
|
|
27917
|
-
var ramps = lib['scheme' + name];
|
|
27918
|
-
var interpolate = lib['interpolate' + name];
|
|
27919
|
-
var ramp;
|
|
27920
|
-
if (!ramps && !interpolate) {
|
|
27921
|
-
stop('Unknown color scheme name:', name);
|
|
27922
|
-
}
|
|
27923
|
-
if (index.categorical.includes(name)) {
|
|
27924
|
-
stop(name, ' is a categorical color scheme (expected a sequential color scheme)');
|
|
27925
|
-
}
|
|
27926
|
-
if (ramps && ramps[n]) {
|
|
27927
|
-
ramp = ramps[n];
|
|
27928
|
-
} else {
|
|
27929
|
-
ramp = getInterpolatedRamp(interpolate, n);
|
|
27930
|
-
}
|
|
27931
|
-
if (stops) {
|
|
27932
|
-
ramp = getStoppedValues(ramp, stops);
|
|
27933
|
-
}
|
|
27934
|
-
return ramp;
|
|
27935
|
-
}
|
|
27936
|
-
|
|
27937
|
-
function getInterpolatedRamp(interpolate, n) {
|
|
27938
|
-
if (n > 0 === false || !utils.isInteger(n)) {
|
|
27939
|
-
error('Expected a positive integer');
|
|
27940
|
-
}
|
|
27941
|
-
var ramp = [];
|
|
27942
|
-
for (var i=0; i<n; i++) {
|
|
27943
|
-
ramp.push(interpolate(i / (n - 1)));
|
|
27944
|
-
}
|
|
27945
|
-
return ramp;
|
|
27946
|
-
}
|
|
27947
|
-
|
|
27948
27737
|
var scaledIntervals =
|
|
27949
27738
|
[10,12,15,18,20,22,25,30,35,40,45,50,60,70,80,90,100];
|
|
27950
27739
|
var precisions =
|
|
@@ -28074,6 +27863,78 @@ ${svg}
|
|
|
28074
27863
|
return s;
|
|
28075
27864
|
}
|
|
28076
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
|
+
|
|
28077
27938
|
// convert an index (0 ... n-1, -1, -2) to a corresponding discreet value
|
|
28078
27939
|
function getDiscreteValueGetter(values, nullValue, otherValue) {
|
|
28079
27940
|
var n = values.length;
|
|
@@ -28680,35 +28541,6 @@ ${svg}
|
|
|
28680
28541
|
};
|
|
28681
28542
|
}
|
|
28682
28543
|
|
|
28683
|
-
function getIndexedClassifier(values, nullVal, opts) {
|
|
28684
|
-
// TODO: handle continuous classification
|
|
28685
|
-
var numBuckets = values.length;
|
|
28686
|
-
var classToValue = getOutputFunction(values, nullVal, opts);
|
|
28687
|
-
|
|
28688
|
-
return function(val) {
|
|
28689
|
-
var idx = utils.isInteger(val) && val >= 0 && val < numBuckets ? val : -1;
|
|
28690
|
-
return classToValue(idx);
|
|
28691
|
-
};
|
|
28692
|
-
}
|
|
28693
|
-
|
|
28694
|
-
// returns the number of classes, based on the largest class index found
|
|
28695
|
-
function validateClassIndexField(records, name) {
|
|
28696
|
-
var invalid = [];
|
|
28697
|
-
var maxId = -1;
|
|
28698
|
-
records.forEach(function(d) {
|
|
28699
|
-
var val = (d || {})[name];
|
|
28700
|
-
if (!utils.isInteger(val) || val < -2) {
|
|
28701
|
-
invalid.push(val);
|
|
28702
|
-
} else {
|
|
28703
|
-
maxId = Math.max(maxId, val);
|
|
28704
|
-
}
|
|
28705
|
-
});
|
|
28706
|
-
if (invalid.length > 0) {
|
|
28707
|
-
stop(`Class index field contains invalid value(s): ${invalid.slice(0, 5)}`);
|
|
28708
|
-
}
|
|
28709
|
-
return maxId + 1;
|
|
28710
|
-
}
|
|
28711
|
-
|
|
28712
28544
|
// Returns a function for constructing a query function that accepts an arc id and
|
|
28713
28545
|
// returns information about the polygon or polygons that use the given arc.
|
|
28714
28546
|
// TODO: explain this better.
|
|
@@ -29005,64 +28837,321 @@ ${svg}
|
|
|
29005
28837
|
};
|
|
29006
28838
|
}
|
|
29007
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
|
+
|
|
29008
29121
|
cmd.classify = function(lyr, dataset, optsArg) {
|
|
29009
29122
|
if (!lyr.data) {
|
|
29010
29123
|
initDataTable(lyr);
|
|
29011
29124
|
}
|
|
29012
29125
|
var opts = optsArg || {};
|
|
29013
29126
|
var records = lyr.data && lyr.data.getRecords();
|
|
29014
|
-
var
|
|
29015
|
-
var
|
|
29016
|
-
var
|
|
29017
|
-
var
|
|
29127
|
+
var valuesAreColors = !!opts.colors;
|
|
29128
|
+
var dataField, dataFieldType, outputField;
|
|
29129
|
+
var values, nullValue;
|
|
29130
|
+
var classifyByValue, classifyByRecordId;
|
|
29018
29131
|
var numClasses, numValues;
|
|
29019
|
-
var dataField, outputField;
|
|
29020
29132
|
var method;
|
|
29021
29133
|
|
|
29022
|
-
|
|
29023
|
-
|
|
29024
|
-
if (!utils.isInteger(opts.classes) || opts.classes > 1 === false) {
|
|
29025
|
-
stop('Invalid number of classes:', opts.classes, '(expected a value greater than 1)');
|
|
29026
|
-
}
|
|
29027
|
-
numClasses = opts.classes;
|
|
29028
|
-
}
|
|
29029
|
-
|
|
29030
|
-
// TODO: better validation of breaks values
|
|
29031
|
-
if (opts.breaks) {
|
|
29032
|
-
numClasses = opts.breaks.length + 1;
|
|
29134
|
+
if (opts.color_scheme) {
|
|
29135
|
+
stop('color-scheme is not a valid option, use colors instead');
|
|
29033
29136
|
}
|
|
29034
29137
|
|
|
29138
|
+
// get data field to use for classification
|
|
29139
|
+
//
|
|
29035
29140
|
if (opts.index_field) {
|
|
29036
29141
|
dataField = opts.index_field;
|
|
29037
|
-
if (numClasses > 0 === false) {
|
|
29038
|
-
stop('The index-field= option requires the classes= option to be set');
|
|
29039
|
-
}
|
|
29040
|
-
// You can't infer the number of classes by looking at index values;
|
|
29041
|
-
// this can cause unwanted interpolation if one or more values are
|
|
29042
|
-
// not present in the index field
|
|
29043
|
-
// numClasses = validateClassIndexField(records, opts.index_field);
|
|
29044
|
-
|
|
29045
29142
|
} else if (opts.field) {
|
|
29046
29143
|
dataField = opts.field;
|
|
29144
|
+
dataFieldType = getColumnType(opts.field, records);
|
|
29047
29145
|
}
|
|
29048
|
-
|
|
29049
|
-
|
|
29050
|
-
if (dataField && opts.categories && opts.categories.includes('*')) {
|
|
29051
|
-
opts.categories = getUniqFieldValues(records, dataField);
|
|
29146
|
+
if (dataField) {
|
|
29147
|
+
requireDataField(lyr.data, dataField);
|
|
29052
29148
|
}
|
|
29053
29149
|
|
|
29054
29150
|
// get classification method
|
|
29055
29151
|
//
|
|
29056
|
-
|
|
29057
|
-
method = opts.method;
|
|
29058
|
-
} else if (opts.categories) {
|
|
29059
|
-
method = 'categorical';
|
|
29060
|
-
} else if (opts.index_field) {
|
|
29061
|
-
method = 'indexed';
|
|
29062
|
-
} else {
|
|
29063
|
-
method = 'quantile'; // TODO: validate data field
|
|
29064
|
-
}
|
|
29152
|
+
method = getClassifyMethod(opts, dataFieldType);
|
|
29065
29153
|
|
|
29154
|
+
// validate classification method
|
|
29066
29155
|
if (method == 'non-adjacent') {
|
|
29067
29156
|
if (lyr.geometry_type != 'polygon') {
|
|
29068
29157
|
stop('The non-adjacent option requires a polygon layer');
|
|
@@ -29072,83 +29161,70 @@ ${svg}
|
|
|
29072
29161
|
}
|
|
29073
29162
|
} else if (!dataField) {
|
|
29074
29163
|
stop('Missing a data field to classify');
|
|
29075
|
-
} else {
|
|
29076
|
-
requireDataField(lyr.data, dataField);
|
|
29077
29164
|
}
|
|
29078
29165
|
|
|
29079
|
-
if (numClasses) {
|
|
29080
|
-
numValues = opts.continuous ? numClasses + 1 : numClasses;
|
|
29081
|
-
}
|
|
29082
29166
|
|
|
29083
|
-
//
|
|
29084
|
-
|
|
29085
|
-
|
|
29086
|
-
|
|
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);
|
|
29087
29173
|
}
|
|
29088
|
-
colorScheme = opts.color_scheme;
|
|
29089
|
-
} else if (opts.colors && isColorSchemeName(opts.colors[0])) {
|
|
29090
|
-
colorScheme = opts.colors[0];
|
|
29091
|
-
} else if (opts.colors) {
|
|
29092
|
-
opts.colors.forEach(parseColor); // validate colors -- error if unparsable
|
|
29093
29174
|
}
|
|
29094
29175
|
|
|
29095
|
-
|
|
29096
|
-
|
|
29097
|
-
|
|
29098
|
-
if (method == 'non-adjacent') {
|
|
29099
|
-
numClasses = numValues = numClasses || 5;
|
|
29100
|
-
values = getCategoricalColorScheme(colorScheme, numValues);
|
|
29101
|
-
|
|
29102
|
-
} else if (method == 'categorical') {
|
|
29103
|
-
values = getCategoricalColorScheme(colorScheme, opts.categories.length);
|
|
29104
|
-
numClasses = numValues = values.length;
|
|
29105
|
-
|
|
29106
|
-
} else {
|
|
29107
|
-
if (!numClasses) {
|
|
29108
|
-
// stop('color-scheme= option requires classes= or breaks=');
|
|
29109
|
-
numClasses = 4; // use a default number of classes
|
|
29110
|
-
numValues = opts.continuous ? numClasses + 1 : numClasses;
|
|
29111
|
-
}
|
|
29112
|
-
values = getColorRamp(colorScheme, numValues, opts.stops);
|
|
29113
|
-
}
|
|
29114
|
-
|
|
29115
|
-
} else if (opts.colors || opts.values) {
|
|
29116
|
-
values = opts.values ? parseValues(opts.values) : opts.colors;
|
|
29117
|
-
if (!numValues) {
|
|
29118
|
-
numValues = values.length;
|
|
29119
|
-
}
|
|
29120
|
-
if ((values.length != numValues || opts.stops) && numValues > 1) {
|
|
29121
|
-
// TODO: handle numValues == 1
|
|
29122
|
-
// TODO: check for non-interpolatable value types (e.g. boolean, text)
|
|
29123
|
-
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)');
|
|
29124
29179
|
}
|
|
29125
|
-
|
|
29126
|
-
} else if (
|
|
29127
|
-
|
|
29128
|
-
|
|
29129
|
-
|
|
29130
|
-
}
|
|
29131
|
-
|
|
29132
|
-
if (
|
|
29133
|
-
|
|
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;
|
|
29134
29195
|
}
|
|
29135
|
-
|
|
29196
|
+
numValues = opts.continuous ? numClasses + 1 : numClasses;
|
|
29136
29197
|
if (numValues > 1 === false) {
|
|
29137
|
-
stop('Missing a valid number of
|
|
29198
|
+
stop('Missing a valid number of values');
|
|
29138
29199
|
}
|
|
29139
29200
|
|
|
29201
|
+
// get colors or other values
|
|
29202
|
+
//
|
|
29203
|
+
values = getClassValues(method, numValues, opts);
|
|
29140
29204
|
if (opts.invert) {
|
|
29141
29205
|
values = values.concat().reverse();
|
|
29142
29206
|
}
|
|
29143
|
-
|
|
29144
29207
|
if (valuesAreColors) {
|
|
29145
29208
|
message('Colors:', formatValuesForLogging(values));
|
|
29146
29209
|
}
|
|
29147
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
|
+
|
|
29148
29224
|
// get a function to convert input data to class indexes
|
|
29149
29225
|
//
|
|
29150
29226
|
if (method == 'non-adjacent') {
|
|
29151
|
-
|
|
29227
|
+
classifyByRecordId = getNonAdjacentClassifier(lyr, dataset, values);
|
|
29152
29228
|
} else if (opts.index_field) {
|
|
29153
29229
|
// data is pre-classified... just read the index from a field
|
|
29154
29230
|
classifyByValue = getIndexedClassifier(values, nullValue, opts);
|
|
@@ -29159,13 +29235,12 @@ ${svg}
|
|
|
29159
29235
|
}
|
|
29160
29236
|
|
|
29161
29237
|
if (classifyByValue) {
|
|
29162
|
-
|
|
29238
|
+
classifyByRecordId = function(id) {
|
|
29163
29239
|
var d = records[id] || {};
|
|
29164
29240
|
return classifyByValue(d[dataField]);
|
|
29165
29241
|
};
|
|
29166
29242
|
}
|
|
29167
29243
|
|
|
29168
|
-
|
|
29169
29244
|
// get the name of the output field
|
|
29170
29245
|
//
|
|
29171
29246
|
if (valuesAreColors) {
|
|
@@ -29181,23 +29256,10 @@ ${svg}
|
|
|
29181
29256
|
}
|
|
29182
29257
|
|
|
29183
29258
|
records.forEach(function(d, i) {
|
|
29184
|
-
d[outputField] =
|
|
29259
|
+
d[outputField] = classifyByRecordId(i);
|
|
29185
29260
|
});
|
|
29186
29261
|
};
|
|
29187
29262
|
|
|
29188
|
-
|
|
29189
|
-
// convert strings to numbers if they all parse as numbers
|
|
29190
|
-
// arr: an array of strings
|
|
29191
|
-
function parseValues(strings) {
|
|
29192
|
-
var values = strings;
|
|
29193
|
-
if (strings.every(utils.parseNumber)) {
|
|
29194
|
-
values = strings.map(function(str) {
|
|
29195
|
-
return +str;
|
|
29196
|
-
});
|
|
29197
|
-
}
|
|
29198
|
-
return values;
|
|
29199
|
-
}
|
|
29200
|
-
|
|
29201
29263
|
function formatValuesForLogging(arr) {
|
|
29202
29264
|
if (arr.some(val => utils.isString(val) && val.indexOf('rgb(') === 0)) {
|
|
29203
29265
|
return formatColorsAsHex(arr);
|
|
@@ -29214,15 +29276,6 @@ ${svg}
|
|
|
29214
29276
|
});
|
|
29215
29277
|
}
|
|
29216
29278
|
|
|
29217
|
-
|
|
29218
|
-
function getIndexValues(n) {
|
|
29219
|
-
var vals = [];
|
|
29220
|
-
for (var i=0; i<n; i++) {
|
|
29221
|
-
vals.push(i);
|
|
29222
|
-
}
|
|
29223
|
-
return vals;
|
|
29224
|
-
}
|
|
29225
|
-
|
|
29226
29279
|
// Remove small-area polygon rings (very simple implementation of sliver removal)
|
|
29227
29280
|
// TODO: more sophisticated sliver detection (e.g. could consider ratio of area to perimeter)
|
|
29228
29281
|
// TODO: consider merging slivers into adjacent polygons to prevent gaps from forming
|
|
@@ -35056,7 +35109,6 @@ ${svg}
|
|
|
35056
35109
|
}
|
|
35057
35110
|
|
|
35058
35111
|
|
|
35059
|
-
|
|
35060
35112
|
function snapVerticesToPoint(ids, p, arcs, final) {
|
|
35061
35113
|
ids.forEach(function(idx) {
|
|
35062
35114
|
setVertexCoords(p[0], p[1], idx, arcs);
|
|
@@ -35136,7 +35188,7 @@ ${svg}
|
|
|
35136
35188
|
function findNearestVertex(x, y, shp, arcs, spherical) {
|
|
35137
35189
|
var calcLen = spherical ? geom.greatCircleDistance : geom.distance2D,
|
|
35138
35190
|
minLen = Infinity,
|
|
35139
|
-
minX, minY,
|
|
35191
|
+
minX, minY, dist, iter;
|
|
35140
35192
|
for (var i=0; i<shp.length; i++) {
|
|
35141
35193
|
iter = arcs.getShapeIter(shp[i]);
|
|
35142
35194
|
while (iter.hasNext()) {
|
|
@@ -35145,26 +35197,10 @@ ${svg}
|
|
|
35145
35197
|
minLen = dist;
|
|
35146
35198
|
minX = iter.x;
|
|
35147
35199
|
minY = iter.y;
|
|
35148
|
-
vId = iter.i;
|
|
35149
35200
|
}
|
|
35150
35201
|
}
|
|
35151
35202
|
}
|
|
35152
|
-
return minLen < Infinity ? {x: minX, y: minY
|
|
35153
|
-
}
|
|
35154
|
-
|
|
35155
|
-
// v: vertex in {x, y, i} format
|
|
35156
|
-
function findAdjacentVertex(v, shp, arcs, offs) {
|
|
35157
|
-
var p, i;
|
|
35158
|
-
var arcEnd = offs == 1 && vertexIsArcEnd(v.i, arcs);
|
|
35159
|
-
var arcStart = offs == -1 && vertexIsArcStart(v.i, arcs);
|
|
35160
|
-
if (arcEnd || arcStart) return null;
|
|
35161
|
-
i = v.i + offs;
|
|
35162
|
-
p = getVertexCoords(i, arcs);
|
|
35163
|
-
return {
|
|
35164
|
-
i: i,
|
|
35165
|
-
x: p[0],
|
|
35166
|
-
y: p[1]
|
|
35167
|
-
};
|
|
35203
|
+
return minLen < Infinity ? {x: minX, y: minY} : null;
|
|
35168
35204
|
}
|
|
35169
35205
|
|
|
35170
35206
|
var VertexUtils = /*#__PURE__*/Object.freeze({
|
|
@@ -35177,8 +35213,7 @@ ${svg}
|
|
|
35177
35213
|
vertexIsArcEnd: vertexIsArcEnd,
|
|
35178
35214
|
vertexIsArcStart: vertexIsArcStart,
|
|
35179
35215
|
setVertexCoords: setVertexCoords,
|
|
35180
|
-
findNearestVertex: findNearestVertex
|
|
35181
|
-
findAdjacentVertex: findAdjacentVertex
|
|
35216
|
+
findNearestVertex: findNearestVertex
|
|
35182
35217
|
});
|
|
35183
35218
|
|
|
35184
35219
|
// Returns x,y coordinates of the point that is at the midpoint of each polyline feature
|