mapshaper 0.5.82 → 0.5.83
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 +282 -134
- package/package.json +1 -1
- package/www/mapshaper.js +282 -134
package/mapshaper.js
CHANGED
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
get isFiniteNumber () { return isFiniteNumber; },
|
|
17
17
|
get isNonNegNumber () { return isNonNegNumber; },
|
|
18
18
|
get isInteger () { return isInteger; },
|
|
19
|
+
get isEven () { return isEven; },
|
|
20
|
+
get isOdd () { return isOdd; },
|
|
19
21
|
get isString () { return isString; },
|
|
20
22
|
get isDate () { return isDate; },
|
|
21
23
|
get isBoolean () { return isBoolean; },
|
|
@@ -149,6 +151,14 @@
|
|
|
149
151
|
return isNumber(obj) && ((obj | 0) === obj);
|
|
150
152
|
}
|
|
151
153
|
|
|
154
|
+
function isEven(obj) {
|
|
155
|
+
return (obj % 2) === 0;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function isOdd(obj) {
|
|
159
|
+
return (obj % 2) === 1;
|
|
160
|
+
}
|
|
161
|
+
|
|
152
162
|
function isString(obj) {
|
|
153
163
|
return obj != null && obj.toString === String.prototype.toString;
|
|
154
164
|
// TODO: replace w/ something better.
|
|
@@ -13698,16 +13708,18 @@
|
|
|
13698
13708
|
length: 'number', // e.g. arrow length
|
|
13699
13709
|
rotation: 'number',
|
|
13700
13710
|
radius: 'number',
|
|
13701
|
-
|
|
13702
|
-
|
|
13703
|
-
|
|
13704
|
-
|
|
13705
|
-
'
|
|
13706
|
-
'
|
|
13707
|
-
'
|
|
13708
|
-
'
|
|
13709
|
-
'
|
|
13710
|
-
'
|
|
13711
|
+
radii: null, // string, parsed by function
|
|
13712
|
+
flipped: 'boolean',
|
|
13713
|
+
rotated: 'boolean',
|
|
13714
|
+
direction: 'number',
|
|
13715
|
+
'head-angle': 'number',
|
|
13716
|
+
'head-width': 'number',
|
|
13717
|
+
'head-length': 'number',
|
|
13718
|
+
'stem-width': 'number',
|
|
13719
|
+
'stem-curve': 'number', // degrees of arc
|
|
13720
|
+
'stem-taper': 'number',
|
|
13721
|
+
'stem-length': 'number',
|
|
13722
|
+
'min-stem': 'number',
|
|
13711
13723
|
'arrow-scaling': 'number',
|
|
13712
13724
|
effect: null // e.g. "fade"
|
|
13713
13725
|
}, stylePropertyTypes);
|
|
@@ -13743,6 +13755,7 @@
|
|
|
13743
13755
|
function getSymbolDataAccessor(lyr, opts) {
|
|
13744
13756
|
var functions = {};
|
|
13745
13757
|
var properties = [];
|
|
13758
|
+
var fields = lyr.data ? lyr.data.getFields() : [];
|
|
13746
13759
|
|
|
13747
13760
|
Object.keys(opts).forEach(function(optName) {
|
|
13748
13761
|
var svgName = optName.replace(/_/g, '-');
|
|
@@ -13754,6 +13767,8 @@
|
|
|
13754
13767
|
properties.push(svgName);
|
|
13755
13768
|
});
|
|
13756
13769
|
|
|
13770
|
+
// TODO: consider applying values of existing fields with names of symbol properties
|
|
13771
|
+
|
|
13757
13772
|
return function(id) {
|
|
13758
13773
|
var d = {}, name;
|
|
13759
13774
|
for (var i=0; i<properties.length; i++) {
|
|
@@ -13769,8 +13784,9 @@
|
|
|
13769
13784
|
// * ???
|
|
13770
13785
|
//
|
|
13771
13786
|
function mightBeExpression(str, fields) {
|
|
13787
|
+
fields = fields || [];
|
|
13772
13788
|
if (fields.indexOf(str.trim()) > -1) return true;
|
|
13773
|
-
return /[(){}
|
|
13789
|
+
return /[(){}./*?:&|=\[+-]/.test(str);
|
|
13774
13790
|
}
|
|
13775
13791
|
|
|
13776
13792
|
function getSymbolPropertyAccessor(val, svgName, lyr) {
|
|
@@ -13791,6 +13807,7 @@
|
|
|
13791
13807
|
// treating the string as a literal value
|
|
13792
13808
|
literalVal = strVal;
|
|
13793
13809
|
}
|
|
13810
|
+
// console.log("literalVal:", mightBeExpression(strVal, fields), strVal, fields)
|
|
13794
13811
|
if (accessor) return accessor;
|
|
13795
13812
|
if (literalVal !== null) return function(id) {return literalVal;};
|
|
13796
13813
|
stop('Unexpected value for', svgName + ':', strVal);
|
|
@@ -13824,6 +13841,8 @@
|
|
|
13824
13841
|
val = isDashArray(strVal) ? strVal : null;
|
|
13825
13842
|
} else if (type == 'pattern') {
|
|
13826
13843
|
val = isPattern(strVal) ? strVal : null;
|
|
13844
|
+
} else if (type == 'boolean') {
|
|
13845
|
+
val = parseBoolean(strVal);
|
|
13827
13846
|
}
|
|
13828
13847
|
// else {
|
|
13829
13848
|
// // unknown type -- assume literal value
|
|
@@ -13844,10 +13863,17 @@
|
|
|
13844
13863
|
return /^( ?[_a-z][-_a-z0-9]*\b)+$/i.test(str);
|
|
13845
13864
|
}
|
|
13846
13865
|
|
|
13866
|
+
|
|
13847
13867
|
function isSvgNumber(o) {
|
|
13848
13868
|
return utils.isFiniteNumber(o) || utils.isString(o) && /^-?[.0-9]+$/.test(o);
|
|
13849
13869
|
}
|
|
13850
13870
|
|
|
13871
|
+
function parseBoolean(o) {
|
|
13872
|
+
if (o === true || o === 'true') return true;
|
|
13873
|
+
if (o === false || o === 'false') return false;
|
|
13874
|
+
return null;
|
|
13875
|
+
}
|
|
13876
|
+
|
|
13851
13877
|
function isSvgMeasure(o) {
|
|
13852
13878
|
return utils.isFiniteNumber(o) || utils.isString(o) && /^-?[.0-9]+[a-z]*$/.test(o);
|
|
13853
13879
|
}
|
|
@@ -13871,6 +13897,7 @@
|
|
|
13871
13897
|
getSymbolPropertyAccessor: getSymbolPropertyAccessor,
|
|
13872
13898
|
isSvgClassName: isSvgClassName,
|
|
13873
13899
|
isSvgNumber: isSvgNumber,
|
|
13900
|
+
parseBoolean: parseBoolean,
|
|
13874
13901
|
isSvgMeasure: isSvgMeasure,
|
|
13875
13902
|
parseSvgMeasure: parseSvgMeasure,
|
|
13876
13903
|
isSvgColor: isSvgColor
|
|
@@ -14089,6 +14116,9 @@
|
|
|
14089
14116
|
o = importLineString(coords[i]);
|
|
14090
14117
|
o.properties.d = d + o.properties.d + ' Z';
|
|
14091
14118
|
}
|
|
14119
|
+
if (coords.length > 1) {
|
|
14120
|
+
o.properties['fill-rule'] = 'evenodd'; // support polygons with holes
|
|
14121
|
+
}
|
|
14092
14122
|
return o;
|
|
14093
14123
|
}
|
|
14094
14124
|
|
|
@@ -18005,6 +18035,10 @@ ${svg}
|
|
|
18005
18035
|
return chunks;
|
|
18006
18036
|
}
|
|
18007
18037
|
|
|
18038
|
+
function parseNumberList(token) {
|
|
18039
|
+
return token.split(',').map(parseFloat);
|
|
18040
|
+
}
|
|
18041
|
+
|
|
18008
18042
|
// Split comma-delimited list, trim quotes from entire list and
|
|
18009
18043
|
// individual members
|
|
18010
18044
|
function parseStringList(token) {
|
|
@@ -18094,6 +18128,7 @@ ${svg}
|
|
|
18094
18128
|
var OptionParsingUtils = /*#__PURE__*/Object.freeze({
|
|
18095
18129
|
__proto__: null,
|
|
18096
18130
|
splitShellTokens: splitShellTokens,
|
|
18131
|
+
parseNumberList: parseNumberList,
|
|
18097
18132
|
parseStringList: parseStringList,
|
|
18098
18133
|
parseColorList: parseColorList,
|
|
18099
18134
|
cleanArgv: cleanArgv,
|
|
@@ -18285,7 +18320,7 @@ ${svg}
|
|
|
18285
18320
|
} else if (type == 'strings') {
|
|
18286
18321
|
val = parseStringList(token);
|
|
18287
18322
|
} else if (type == 'bbox' || type == 'numbers') {
|
|
18288
|
-
val = token
|
|
18323
|
+
val = parseNumberList(token);
|
|
18289
18324
|
} else if (type == 'percent') {
|
|
18290
18325
|
// val = utils.parsePercent(token);
|
|
18291
18326
|
val = token; // string value is parsed by command function
|
|
@@ -20079,51 +20114,73 @@ ${svg}
|
|
|
20079
20114
|
describe: 'sides of a polygon or star symbol',
|
|
20080
20115
|
type: 'number'
|
|
20081
20116
|
})
|
|
20117
|
+
.option('orientation', {
|
|
20118
|
+
// describe: 'use orientation=b for a rotated or flipped orientation'
|
|
20119
|
+
})
|
|
20120
|
+
.option('flipped', {
|
|
20121
|
+
type: 'flag',
|
|
20122
|
+
describe: 'symbol is vertically flipped'
|
|
20123
|
+
})
|
|
20124
|
+
.option('rotated', {
|
|
20125
|
+
type: 'flag',
|
|
20126
|
+
describe: 'symbol is rotated to a different orientation'
|
|
20127
|
+
})
|
|
20082
20128
|
.option('rotation', {
|
|
20083
20129
|
describe: 'rotation of symbol in degrees'
|
|
20084
20130
|
})
|
|
20085
|
-
.option('orientation', {
|
|
20086
|
-
describe: 'use orientation=b for a rotated or flipped orientation'
|
|
20087
|
-
})
|
|
20088
20131
|
.option('length', {
|
|
20089
20132
|
// alias for arrow-length
|
|
20090
20133
|
})
|
|
20091
|
-
.option('
|
|
20092
|
-
|
|
20134
|
+
.option('point-ratio', {
|
|
20135
|
+
old_alias: 'star-ratio',
|
|
20136
|
+
describe: '(star) ratio of minor to major radius of star',
|
|
20093
20137
|
type: 'number'
|
|
20094
20138
|
})
|
|
20095
|
-
.option('
|
|
20096
|
-
describe: '
|
|
20139
|
+
.option('radii', {
|
|
20140
|
+
describe: '(ring) comma-sep. list of concentric radii, ascending order'
|
|
20141
|
+
})
|
|
20142
|
+
.option('length', {
|
|
20143
|
+
old_alias: 'arrow-length',
|
|
20144
|
+
describe: '(arrow) length of arrow in pixels'
|
|
20097
20145
|
})
|
|
20098
|
-
.option('
|
|
20099
|
-
|
|
20146
|
+
.option('direction', {
|
|
20147
|
+
old_alias: 'arrow-direction',
|
|
20148
|
+
describe: '(arrow) angle off vertical (-90 = left-pointing)'
|
|
20100
20149
|
})
|
|
20101
|
-
.option('
|
|
20102
|
-
|
|
20150
|
+
.option('head-angle', {
|
|
20151
|
+
old_alias: 'arrow-head-angle',
|
|
20152
|
+
describe: '(arrow) angle of tip of arrow (default is 40 degrees)'
|
|
20103
20153
|
})
|
|
20104
|
-
.option('
|
|
20105
|
-
|
|
20154
|
+
.option('head-width', {
|
|
20155
|
+
old_alias: 'arrow-head-width',
|
|
20156
|
+
describe: '(arrow) width of arrow head from side to side'
|
|
20106
20157
|
})
|
|
20107
|
-
.option('
|
|
20108
|
-
|
|
20158
|
+
.option('head-length', {
|
|
20159
|
+
old_alias: 'arrow-head-width',
|
|
20160
|
+
describe: '(arrow) length of head (alternative to head-angle)'
|
|
20109
20161
|
})
|
|
20110
|
-
.option('
|
|
20162
|
+
.option('head-shape', {
|
|
20111
20163
|
// describe: 'options: a b c'
|
|
20112
20164
|
})
|
|
20113
|
-
.option('
|
|
20114
|
-
|
|
20165
|
+
.option('stem-width', {
|
|
20166
|
+
old_alias: 'arrow-stem-width',
|
|
20167
|
+
describe: '(arrow) width of stem at its widest point'
|
|
20115
20168
|
})
|
|
20116
|
-
.option('
|
|
20117
|
-
|
|
20169
|
+
.option('stem-length', {
|
|
20170
|
+
old_alias: 'arrow-stem-length',
|
|
20171
|
+
describe: '(arrow) alternative to length'
|
|
20118
20172
|
})
|
|
20119
|
-
.option('
|
|
20120
|
-
|
|
20173
|
+
.option('stem-taper', {
|
|
20174
|
+
old_alias: 'arrow-stem-taper',
|
|
20175
|
+
describe: '(arrow) factor for tapering the width of the stem (0-1)'
|
|
20121
20176
|
})
|
|
20122
|
-
.option('
|
|
20123
|
-
|
|
20177
|
+
.option('stem-curve', {
|
|
20178
|
+
old_alias: 'arrow-stem-curve',
|
|
20179
|
+
describe: '(arrow) curvature in degrees (default is 0)'
|
|
20124
20180
|
})
|
|
20125
|
-
.option('
|
|
20126
|
-
|
|
20181
|
+
.option('min-stem-ratio', {
|
|
20182
|
+
old_alias: 'arrow-min-stem',
|
|
20183
|
+
describe: '(arrow) min ratio of stem to total length',
|
|
20127
20184
|
type: 'number'
|
|
20128
20185
|
})
|
|
20129
20186
|
.option('stroke', {})
|
|
@@ -21660,7 +21717,7 @@ ${svg}
|
|
|
21660
21717
|
collectionType = 'mixed';
|
|
21661
21718
|
}
|
|
21662
21719
|
} else if (currType != t) {
|
|
21663
|
-
stop("Unable to import mixed-geometry
|
|
21720
|
+
stop("Unable to import mixed-geometry features");
|
|
21664
21721
|
}
|
|
21665
21722
|
}
|
|
21666
21723
|
|
|
@@ -21771,6 +21828,33 @@ ${svg}
|
|
|
21771
21828
|
importShp: importShp
|
|
21772
21829
|
});
|
|
21773
21830
|
|
|
21831
|
+
function importGeoJSON(src, optsArg) {
|
|
21832
|
+
var opts = optsArg || {};
|
|
21833
|
+
var supportedGeometries = Object.keys(GeoJSON.pathImporters),
|
|
21834
|
+
srcObj = utils.isString(src) ? JSON.parse(src) : src,
|
|
21835
|
+
importer = new GeoJSONParser(opts),
|
|
21836
|
+
srcCollection, dataset;
|
|
21837
|
+
|
|
21838
|
+
// Convert single feature or geometry into a collection with one member
|
|
21839
|
+
if (srcObj.type == 'Feature') {
|
|
21840
|
+
srcCollection = {
|
|
21841
|
+
type: 'FeatureCollection',
|
|
21842
|
+
features: [srcObj]
|
|
21843
|
+
};
|
|
21844
|
+
} else if (supportedGeometries.includes(srcObj.type)) {
|
|
21845
|
+
srcCollection = {
|
|
21846
|
+
type: 'GeometryCollection',
|
|
21847
|
+
geometries: [srcObj]
|
|
21848
|
+
};
|
|
21849
|
+
} else {
|
|
21850
|
+
srcCollection = srcObj;
|
|
21851
|
+
}
|
|
21852
|
+
(srcCollection.features || srcCollection.geometries || []).forEach(importer.parseObject);
|
|
21853
|
+
dataset = importer.done();
|
|
21854
|
+
importCRS(dataset, srcObj); // TODO: remove this
|
|
21855
|
+
return dataset;
|
|
21856
|
+
}
|
|
21857
|
+
|
|
21774
21858
|
function GeoJSONParser(opts) {
|
|
21775
21859
|
var idField = opts.id_field || GeoJSON.ID_FIELD,
|
|
21776
21860
|
importer = new PathImporter(opts),
|
|
@@ -21792,8 +21876,11 @@ ${svg}
|
|
|
21792
21876
|
geom = o;
|
|
21793
21877
|
}
|
|
21794
21878
|
// TODO: improve so geometry_type option skips features instead of creating null geometries
|
|
21795
|
-
|
|
21796
|
-
|
|
21879
|
+
if (geom && geom.type == 'GeometryCollection') {
|
|
21880
|
+
GeoJSON.importComplexFeature(importer, geom, rec, opts);
|
|
21881
|
+
} else {
|
|
21882
|
+
GeoJSON.importSimpleFeature(importer, geom, rec, opts);
|
|
21883
|
+
}
|
|
21797
21884
|
};
|
|
21798
21885
|
|
|
21799
21886
|
this.done = function() {
|
|
@@ -21801,50 +21888,58 @@ ${svg}
|
|
|
21801
21888
|
};
|
|
21802
21889
|
}
|
|
21803
21890
|
|
|
21804
|
-
function
|
|
21805
|
-
var
|
|
21806
|
-
|
|
21807
|
-
|
|
21808
|
-
|
|
21809
|
-
srcCollection, dataset;
|
|
21810
|
-
|
|
21811
|
-
// Convert single feature or geometry into a collection with one member
|
|
21812
|
-
if (srcObj.type == 'Feature') {
|
|
21813
|
-
srcCollection = {
|
|
21814
|
-
type: 'FeatureCollection',
|
|
21815
|
-
features: [srcObj]
|
|
21816
|
-
};
|
|
21817
|
-
} else if (supportedGeometries.includes(srcObj.type)) {
|
|
21818
|
-
srcCollection = {
|
|
21819
|
-
type: 'GeometryCollection',
|
|
21820
|
-
geometries: [srcObj]
|
|
21821
|
-
};
|
|
21822
|
-
} else {
|
|
21823
|
-
srcCollection = srcObj;
|
|
21891
|
+
GeoJSON.importComplexFeature = function(importer, geom, rec, opts) {
|
|
21892
|
+
var types = divideGeometriesByType(geom.geometries || []);
|
|
21893
|
+
if (types.length === 0) {
|
|
21894
|
+
importer.startShape(rec); // import a feature with null geometry
|
|
21895
|
+
return;
|
|
21824
21896
|
}
|
|
21825
|
-
(
|
|
21826
|
-
|
|
21827
|
-
|
|
21828
|
-
|
|
21897
|
+
types.forEach(function(geometries, i) {
|
|
21898
|
+
importer.startShape(copyRecord(rec));
|
|
21899
|
+
geometries.forEach(function(geom) {
|
|
21900
|
+
GeoJSON.importSimpleGeometry(importer, geom, opts);
|
|
21901
|
+
});
|
|
21902
|
+
});
|
|
21903
|
+
};
|
|
21904
|
+
|
|
21905
|
+
function divideGeometriesByType(geometries, index) {
|
|
21906
|
+
index = index || {};
|
|
21907
|
+
geometries.forEach(function(geom) {
|
|
21908
|
+
if (!geom) return;
|
|
21909
|
+
var mtype = GeoJSON.translateGeoJSONType(geom.type);
|
|
21910
|
+
if (mtype) {
|
|
21911
|
+
if (mtype in index === false) {
|
|
21912
|
+
index[mtype] = [];
|
|
21913
|
+
}
|
|
21914
|
+
index[mtype].push(geom);
|
|
21915
|
+
} else if (geom.type == 'GeometryCollection') {
|
|
21916
|
+
divideGeometriesByType(geom.geometries || [], index);
|
|
21917
|
+
}
|
|
21918
|
+
});
|
|
21919
|
+
return Object.values(index);
|
|
21829
21920
|
}
|
|
21830
21921
|
|
|
21831
|
-
GeoJSON.
|
|
21832
|
-
|
|
21833
|
-
|
|
21922
|
+
GeoJSON.importSimpleFeature = function(importer, geom, rec, opts) {
|
|
21923
|
+
importer.startShape(rec);
|
|
21924
|
+
GeoJSON.importSimpleGeometry(importer, geom, opts);
|
|
21925
|
+
};
|
|
21926
|
+
|
|
21927
|
+
GeoJSON.importSimpleGeometry = function(importer, geom, opts) {
|
|
21928
|
+
var type = geom ? geom.type : null;
|
|
21929
|
+
if (type === null) {
|
|
21930
|
+
// no geometry to import
|
|
21931
|
+
} else if (type in GeoJSON.pathImporters) {
|
|
21834
21932
|
if (opts.geometry_type && opts.geometry_type != GeoJSON.translateGeoJSONType(type)) {
|
|
21835
21933
|
// kludge to filter out all but one type of geometry
|
|
21836
21934
|
return;
|
|
21837
21935
|
}
|
|
21838
21936
|
GeoJSON.pathImporters[type](geom.coordinates, importer);
|
|
21839
|
-
} else if (type == 'GeometryCollection') {
|
|
21840
|
-
geom.geometries.forEach(function(geom) {
|
|
21841
|
-
GeoJSON.importGeometry(geom, importer, opts);
|
|
21842
|
-
});
|
|
21843
21937
|
} else {
|
|
21844
|
-
verbose("
|
|
21938
|
+
verbose("Unsupported geometry type:", geom.type);
|
|
21845
21939
|
}
|
|
21846
21940
|
};
|
|
21847
21941
|
|
|
21942
|
+
|
|
21848
21943
|
// Functions for importing geometry coordinates using a PathImporter
|
|
21849
21944
|
//
|
|
21850
21945
|
GeoJSON.pathImporters = {
|
|
@@ -21883,8 +21978,8 @@ ${svg}
|
|
|
21883
21978
|
|
|
21884
21979
|
var GeojsonImport = /*#__PURE__*/Object.freeze({
|
|
21885
21980
|
__proto__: null,
|
|
21886
|
-
GeoJSONParser: GeoJSONParser,
|
|
21887
21981
|
importGeoJSON: importGeoJSON,
|
|
21982
|
+
GeoJSONParser: GeoJSONParser,
|
|
21888
21983
|
importCRS: importCRS
|
|
21889
21984
|
});
|
|
21890
21985
|
|
|
@@ -37968,70 +38063,80 @@ ${svg}
|
|
|
37968
38063
|
// return [stem, head];
|
|
37969
38064
|
// }
|
|
37970
38065
|
|
|
37971
|
-
function getMinStemRatio(d) {
|
|
37972
|
-
return d['arrow-min-stem'] >= 0 ? d['arrow-min-stem'] : 0.4;
|
|
37973
|
-
}
|
|
37974
38066
|
|
|
37975
38067
|
function getFilledArrowCoords(d) {
|
|
37976
|
-
var
|
|
37977
|
-
|
|
37978
|
-
|
|
37979
|
-
|
|
37980
|
-
unscaledHeadLen = getHeadLength(unscaledHeadWidth, d),
|
|
37981
|
-
stemTaper = d['arrow-stem-taper'] || 0,
|
|
37982
|
-
stemCurve = d['arrow-stem-curve'] || 0;
|
|
38068
|
+
var direction = d.rotation || d.direction || 0,
|
|
38069
|
+
stemTaper = d['stem-taper'] || 0,
|
|
38070
|
+
stemCurve = d['stem-curve'] || 0,
|
|
38071
|
+
size = calcArrowSize(d);
|
|
37983
38072
|
|
|
37984
|
-
|
|
38073
|
+
if (!size) return null;
|
|
37985
38074
|
|
|
37986
|
-
var
|
|
37987
|
-
|
|
37988
|
-
|
|
37989
|
-
|
|
37990
|
-
headWidth = unscaledHeadWidth * scale;
|
|
37991
|
-
headLen = unscaledHeadLen * scale;
|
|
37992
|
-
stemWidth = unscaledStemWidth * scale;
|
|
37993
|
-
stemLen = totalLen - headLen;
|
|
38075
|
+
var headDx = size.headWidth / 2,
|
|
38076
|
+
stemDx = size.stemWidth / 2,
|
|
38077
|
+
baseDx = stemDx * (1 - stemTaper),
|
|
38078
|
+
coords;
|
|
37994
38079
|
|
|
38080
|
+
if (!stemCurve || Math.abs(stemCurve) > 90) {
|
|
38081
|
+
coords = calcStraightArrowCoords(size.stemLen, size.headLen, stemDx, headDx, baseDx);
|
|
37995
38082
|
} else {
|
|
37996
|
-
|
|
37997
|
-
|
|
37998
|
-
stemWidth = unscaledStemWidth;
|
|
37999
|
-
stemLen = d['arrow-stem-length'] || 0;
|
|
38000
|
-
totalLen = headLen + stemLen;
|
|
38083
|
+
if (direction > 0) stemCurve = -stemCurve;
|
|
38084
|
+
coords = getCurvedArrowCoords(size.stemLen, size.headLen, size.stemCurve, stemDx, headDx, baseDx);
|
|
38001
38085
|
}
|
|
38002
38086
|
|
|
38003
|
-
|
|
38087
|
+
rotateCoords(coords, direction);
|
|
38088
|
+
if (d.flipped) {
|
|
38089
|
+
flipY(coords);
|
|
38090
|
+
}
|
|
38091
|
+
return [coords];
|
|
38092
|
+
}
|
|
38004
38093
|
|
|
38005
|
-
|
|
38094
|
+
function calcStraightArrowCoords(stemLen, headLen, stemDx, headDx, baseDx) {
|
|
38095
|
+
return [[baseDx, 0], [stemDx, stemLen], [headDx, stemLen], [0, stemLen + headLen],
|
|
38096
|
+
[-headDx, stemLen], [-stemDx, stemLen], [-baseDx, 0], [baseDx, 0]];
|
|
38097
|
+
}
|
|
38006
38098
|
|
|
38007
|
-
|
|
38008
|
-
|
|
38009
|
-
|
|
38099
|
+
function calcArrowSize(d) {
|
|
38100
|
+
var totalLen = d.radius || d.length || d.r || 0,
|
|
38101
|
+
unscaledStemWidth = d['stem-width'] || 2,
|
|
38102
|
+
unscaledHeadWidth = d['head-width'] || unscaledStemWidth * 3,
|
|
38103
|
+
unscaledHeadLen = d['head-length'] || calcHeadLength(unscaledHeadWidth, d),
|
|
38104
|
+
scale = 1,
|
|
38105
|
+
o = {};
|
|
38010
38106
|
|
|
38011
|
-
if (
|
|
38012
|
-
|
|
38013
|
-
|
|
38107
|
+
if (totalLen > 0) {
|
|
38108
|
+
scale = calcScale(totalLen, unscaledHeadLen, d);
|
|
38109
|
+
o.headWidth = unscaledHeadWidth * scale;
|
|
38110
|
+
o.headLen = unscaledHeadLen * scale;
|
|
38111
|
+
o.stemWidth = unscaledStemWidth * scale;
|
|
38112
|
+
o.stemLen = totalLen - o.headLen;
|
|
38014
38113
|
|
|
38015
|
-
if (!stemCurve || Math.abs(stemCurve) > 90) {
|
|
38016
|
-
coords = [[baseDx, 0], [stemDx, stemLen], [headDx, stemLen], [0, stemLen + headLen],
|
|
38017
|
-
[-headDx, stemLen], [-stemDx, stemLen], [-baseDx, 0], [baseDx, 0]];
|
|
38018
38114
|
} else {
|
|
38019
|
-
|
|
38020
|
-
|
|
38115
|
+
o.headWidth = unscaledHeadWidth;
|
|
38116
|
+
o.headLen = unscaledHeadLen;
|
|
38117
|
+
o.stemWidth = unscaledStemWidth;
|
|
38118
|
+
o.stemLen = d['stem-length'] || 0;
|
|
38021
38119
|
}
|
|
38022
38120
|
|
|
38023
|
-
|
|
38024
|
-
|
|
38121
|
+
if (unscaledHeadWidth < unscaledStemWidth) {
|
|
38122
|
+
stop('Arrow head must be at least as wide as the stem.');
|
|
38123
|
+
}
|
|
38124
|
+
return o;
|
|
38025
38125
|
}
|
|
38026
38126
|
|
|
38027
|
-
|
|
38028
|
-
|
|
38127
|
+
function calcScale(totalLen, headLen, d) {
|
|
38128
|
+
var minStemRatio = d['min-stem'] >= 0 ? d['min-stem'] : 0;
|
|
38129
|
+
var stemLen = d['stem-length'] || 0;
|
|
38029
38130
|
var maxHeadPct = 1 - minStemRatio;
|
|
38030
38131
|
var headPct = headLen / totalLen;
|
|
38132
|
+
var scale = 1;
|
|
38133
|
+
|
|
38031
38134
|
if (headPct > maxHeadPct) {
|
|
38032
|
-
|
|
38135
|
+
scale = maxHeadPct / headPct;
|
|
38136
|
+
} else if (stemLen + headLen > totalLen) {
|
|
38137
|
+
scale = totalLen / (stemLen + headLen);
|
|
38033
38138
|
}
|
|
38034
|
-
return
|
|
38139
|
+
return scale;
|
|
38035
38140
|
}
|
|
38036
38141
|
|
|
38037
38142
|
// function getStickArrowTip(totalLen, curve) {
|
|
@@ -38047,10 +38152,8 @@ ${svg}
|
|
|
38047
38152
|
}
|
|
38048
38153
|
|
|
38049
38154
|
|
|
38050
|
-
function
|
|
38051
|
-
var
|
|
38052
|
-
if (headLength > 0) return headLength;
|
|
38053
|
-
var headAngle = d['arrow-head-angle'] || 40;
|
|
38155
|
+
function calcHeadLength(headWidth, d) {
|
|
38156
|
+
var headAngle = d['head-angle'] || 40;
|
|
38054
38157
|
var headRatio = 1 / Math.tan(Math.PI * headAngle / 180 / 2) / 2; // length-to-width head ratio
|
|
38055
38158
|
return headWidth * headRatio;
|
|
38056
38159
|
}
|
|
@@ -38109,11 +38212,11 @@ ${svg}
|
|
|
38109
38212
|
// sides: e.g. 5-pointed star has 10 sides
|
|
38110
38213
|
// radius: distance from center to point
|
|
38111
38214
|
//
|
|
38112
|
-
function getPolygonCoords(
|
|
38113
|
-
var radius =
|
|
38215
|
+
function getPolygonCoords(d) {
|
|
38216
|
+
var radius = d.radius || d.length || d.r;
|
|
38114
38217
|
if (radius > 0 === false) return null;
|
|
38115
|
-
var type =
|
|
38116
|
-
var sides = +
|
|
38218
|
+
var type = d.type;
|
|
38219
|
+
var sides = +d.sides || getDefaultSides(type);
|
|
38117
38220
|
var isStar = type == 'star';
|
|
38118
38221
|
if (isStar && (sides < 6 || sides % 2 !== 0)) {
|
|
38119
38222
|
stop(`Invalid number of sides for a star (${sides})`);
|
|
@@ -38124,14 +38227,14 @@ ${svg}
|
|
|
38124
38227
|
angle = 360 / sides,
|
|
38125
38228
|
b = isStar ? 1 : 0.5,
|
|
38126
38229
|
theta, even, len;
|
|
38127
|
-
if (
|
|
38230
|
+
if (d.orientation == 'b' || d.flipped || d.rotated) {
|
|
38128
38231
|
b = 0;
|
|
38129
38232
|
}
|
|
38130
38233
|
for (var i=0; i<sides; i++) {
|
|
38131
38234
|
even = i % 2 == 0;
|
|
38132
38235
|
len = radius;
|
|
38133
38236
|
if (isStar && even) {
|
|
38134
|
-
len *= (
|
|
38237
|
+
len *= (d.star_ratio || 0.5);
|
|
38135
38238
|
}
|
|
38136
38239
|
theta = (i + b) * angle % 360;
|
|
38137
38240
|
coords.push(getPlanarSegmentEndpoint(0, 0, theta, len));
|
|
@@ -38155,6 +38258,37 @@ ${svg}
|
|
|
38155
38258
|
}[type] || 4;
|
|
38156
38259
|
}
|
|
38157
38260
|
|
|
38261
|
+
// Returns GeoJSON MultiPolygon coords
|
|
38262
|
+
function getRingCoords(d) {
|
|
38263
|
+
var radii = parseRings(d.radii || '2');
|
|
38264
|
+
var coords = [];
|
|
38265
|
+
var solidCenter = utils.isOdd(radii.length);
|
|
38266
|
+
var ring, hole;
|
|
38267
|
+
for (var i=0; i<radii.length; i++) {
|
|
38268
|
+
ring = getPolygonCoords({
|
|
38269
|
+
type: 'circle',
|
|
38270
|
+
radius: radii[i]
|
|
38271
|
+
});
|
|
38272
|
+
if (!solidCenter || i > 0) {
|
|
38273
|
+
i++;
|
|
38274
|
+
hole = ring;
|
|
38275
|
+
ring = getPolygonCoords({
|
|
38276
|
+
type: 'circle',
|
|
38277
|
+
radius: radii[i]
|
|
38278
|
+
});
|
|
38279
|
+
ring.push(hole[0]);
|
|
38280
|
+
}
|
|
38281
|
+
coords.push(ring);
|
|
38282
|
+
}
|
|
38283
|
+
return coords;
|
|
38284
|
+
}
|
|
38285
|
+
|
|
38286
|
+
function parseRings(arg) {
|
|
38287
|
+
var arr = Array.isArray(arg) ? arg : parseNumberList(arg);
|
|
38288
|
+
utils.genericSort(arr, true);
|
|
38289
|
+
return utils.uniq(arr);
|
|
38290
|
+
}
|
|
38291
|
+
|
|
38158
38292
|
// TODO: refactor to remove duplication in mapshaper-svg-style.js
|
|
38159
38293
|
cmd.symbols = function(inputLyr, dataset, opts) {
|
|
38160
38294
|
requireSinglePointLayer(inputLyr);
|
|
@@ -38171,9 +38305,13 @@ ${svg}
|
|
|
38171
38305
|
if (!shp) return null;
|
|
38172
38306
|
var d = getSymbolData(i);
|
|
38173
38307
|
var rec = records[i] || {};
|
|
38308
|
+
var geojsonType = 'Polygon';
|
|
38174
38309
|
var coords;
|
|
38175
38310
|
if (d.type == 'arrow') {
|
|
38176
38311
|
coords = getFilledArrowCoords(d);
|
|
38312
|
+
} else if (d.type == 'ring') {
|
|
38313
|
+
coords = getRingCoords(d);
|
|
38314
|
+
geojsonType = 'MultiPolygon';
|
|
38177
38315
|
} else {
|
|
38178
38316
|
coords = getPolygonCoords(d);
|
|
38179
38317
|
}
|
|
@@ -38188,9 +38326,9 @@ ${svg}
|
|
|
38188
38326
|
if (polygonMode) {
|
|
38189
38327
|
scaleAndShiftCoords(coords, metersPerPx, shp[0]);
|
|
38190
38328
|
if (d.tfill) rec.fill = d.fill;
|
|
38191
|
-
return createGeometry(coords);
|
|
38329
|
+
return createGeometry(coords, geojsonType);
|
|
38192
38330
|
} else {
|
|
38193
|
-
rec['svg-symbol'] =
|
|
38331
|
+
rec['svg-symbol'] = makeSvgPolygonSymbol(coords, d, geojsonType);
|
|
38194
38332
|
}
|
|
38195
38333
|
});
|
|
38196
38334
|
|
|
@@ -38221,9 +38359,9 @@ ${svg}
|
|
|
38221
38359
|
return importGeoJSON(geojson);
|
|
38222
38360
|
}
|
|
38223
38361
|
|
|
38224
|
-
function createGeometry(coords) {
|
|
38362
|
+
function createGeometry(coords, type) {
|
|
38225
38363
|
return {
|
|
38226
|
-
type:
|
|
38364
|
+
type: type,
|
|
38227
38365
|
coordinates: coords
|
|
38228
38366
|
};
|
|
38229
38367
|
}
|
|
@@ -38236,7 +38374,12 @@ ${svg}
|
|
|
38236
38374
|
}
|
|
38237
38375
|
|
|
38238
38376
|
// Returns an svg-symbol data object for one symbol
|
|
38239
|
-
function
|
|
38377
|
+
function makeSvgPolygonSymbol(coords, properties, geojsonType) {
|
|
38378
|
+
if (geojsonType == 'MultiPolygon') {
|
|
38379
|
+
coords = convertMultiPolygonCoords(coords);
|
|
38380
|
+
} else if (geojsonType != 'Polygon') {
|
|
38381
|
+
error('Unsupported type:', geojsonType);
|
|
38382
|
+
}
|
|
38240
38383
|
roundCoordsForSVG(coords);
|
|
38241
38384
|
return {
|
|
38242
38385
|
type: 'polygon',
|
|
@@ -38245,9 +38388,14 @@ ${svg}
|
|
|
38245
38388
|
};
|
|
38246
38389
|
}
|
|
38247
38390
|
|
|
38391
|
+
function convertMultiPolygonCoords(coords) {
|
|
38392
|
+
return coords.reduce(function(memo, poly) {
|
|
38393
|
+
return memo.concat(poly);
|
|
38394
|
+
}, []);
|
|
38395
|
+
}
|
|
38396
|
+
|
|
38248
38397
|
var Symbols = /*#__PURE__*/Object.freeze({
|
|
38249
|
-
__proto__: null
|
|
38250
|
-
makeSvgSymbol: makeSvgSymbol
|
|
38398
|
+
__proto__: null
|
|
38251
38399
|
});
|
|
38252
38400
|
|
|
38253
38401
|
cmd.target = function(catalog, opts) {
|