mapshaper 0.5.81 → 0.5.85
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 +13 -0
- package/mapshaper.js +411 -178
- package/package.json +1 -1
- package/www/mapshaper.js +411 -178
package/www/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.5.
|
|
3
|
+
var VERSION = "0.5.83";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -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.
|
|
@@ -2359,6 +2369,12 @@
|
|
|
2359
2369
|
}, 0);
|
|
2360
2370
|
}
|
|
2361
2371
|
|
|
2372
|
+
// export function getEllipsoidalShapeArea(shp, arcs, crs) {
|
|
2373
|
+
// return (shp || []).reduce(function(area, ids) {
|
|
2374
|
+
// return area + getEllipsoidalPathArea(ids, arcs, crs);
|
|
2375
|
+
// }, 0);
|
|
2376
|
+
// }
|
|
2377
|
+
|
|
2362
2378
|
// Return true if point is inside or on boundary of a shape
|
|
2363
2379
|
//
|
|
2364
2380
|
function testPointInPolygon(x, y, shp, arcs) {
|
|
@@ -13692,14 +13708,21 @@
|
|
|
13692
13708
|
length: 'number', // e.g. arrow length
|
|
13693
13709
|
rotation: 'number',
|
|
13694
13710
|
radius: 'number',
|
|
13695
|
-
|
|
13696
|
-
|
|
13697
|
-
|
|
13698
|
-
|
|
13699
|
-
|
|
13700
|
-
|
|
13701
|
-
|
|
13702
|
-
'
|
|
13711
|
+
radii: null, // string, parsed by function
|
|
13712
|
+
flipped: 'boolean',
|
|
13713
|
+
rotated: 'boolean',
|
|
13714
|
+
direction: 'number',
|
|
13715
|
+
sides: 'number', // polygons and stars
|
|
13716
|
+
points: 'number', // polygons and stars
|
|
13717
|
+
anchor: null, // arrows; takes start, middle, end
|
|
13718
|
+
'head-angle': 'number',
|
|
13719
|
+
'head-width': 'number',
|
|
13720
|
+
'head-length': 'number',
|
|
13721
|
+
'stem-width': 'number',
|
|
13722
|
+
'stem-curve': 'number', // degrees of arc
|
|
13723
|
+
'stem-taper': 'number',
|
|
13724
|
+
'stem-length': 'number',
|
|
13725
|
+
'min-stem-ratio': 'number',
|
|
13703
13726
|
'arrow-scaling': 'number',
|
|
13704
13727
|
effect: null // e.g. "fade"
|
|
13705
13728
|
}, stylePropertyTypes);
|
|
@@ -13735,6 +13758,7 @@
|
|
|
13735
13758
|
function getSymbolDataAccessor(lyr, opts) {
|
|
13736
13759
|
var functions = {};
|
|
13737
13760
|
var properties = [];
|
|
13761
|
+
var fields = lyr.data ? lyr.data.getFields() : [];
|
|
13738
13762
|
|
|
13739
13763
|
Object.keys(opts).forEach(function(optName) {
|
|
13740
13764
|
var svgName = optName.replace(/_/g, '-');
|
|
@@ -13746,6 +13770,8 @@
|
|
|
13746
13770
|
properties.push(svgName);
|
|
13747
13771
|
});
|
|
13748
13772
|
|
|
13773
|
+
// TODO: consider applying values of existing fields with names of symbol properties
|
|
13774
|
+
|
|
13749
13775
|
return function(id) {
|
|
13750
13776
|
var d = {}, name;
|
|
13751
13777
|
for (var i=0; i<properties.length; i++) {
|
|
@@ -13761,8 +13787,9 @@
|
|
|
13761
13787
|
// * ???
|
|
13762
13788
|
//
|
|
13763
13789
|
function mightBeExpression(str, fields) {
|
|
13790
|
+
fields = fields || [];
|
|
13764
13791
|
if (fields.indexOf(str.trim()) > -1) return true;
|
|
13765
|
-
return /[(){}
|
|
13792
|
+
return /[(){}./*?:&|=\[+-]/.test(str);
|
|
13766
13793
|
}
|
|
13767
13794
|
|
|
13768
13795
|
function getSymbolPropertyAccessor(val, svgName, lyr) {
|
|
@@ -13783,6 +13810,7 @@
|
|
|
13783
13810
|
// treating the string as a literal value
|
|
13784
13811
|
literalVal = strVal;
|
|
13785
13812
|
}
|
|
13813
|
+
// console.log("literalVal:", mightBeExpression(strVal, fields), strVal, fields)
|
|
13786
13814
|
if (accessor) return accessor;
|
|
13787
13815
|
if (literalVal !== null) return function(id) {return literalVal;};
|
|
13788
13816
|
stop('Unexpected value for', svgName + ':', strVal);
|
|
@@ -13816,6 +13844,8 @@
|
|
|
13816
13844
|
val = isDashArray(strVal) ? strVal : null;
|
|
13817
13845
|
} else if (type == 'pattern') {
|
|
13818
13846
|
val = isPattern(strVal) ? strVal : null;
|
|
13847
|
+
} else if (type == 'boolean') {
|
|
13848
|
+
val = parseBoolean(strVal);
|
|
13819
13849
|
}
|
|
13820
13850
|
// else {
|
|
13821
13851
|
// // unknown type -- assume literal value
|
|
@@ -13836,10 +13866,17 @@
|
|
|
13836
13866
|
return /^( ?[_a-z][-_a-z0-9]*\b)+$/i.test(str);
|
|
13837
13867
|
}
|
|
13838
13868
|
|
|
13869
|
+
|
|
13839
13870
|
function isSvgNumber(o) {
|
|
13840
13871
|
return utils.isFiniteNumber(o) || utils.isString(o) && /^-?[.0-9]+$/.test(o);
|
|
13841
13872
|
}
|
|
13842
13873
|
|
|
13874
|
+
function parseBoolean(o) {
|
|
13875
|
+
if (o === true || o === 'true') return true;
|
|
13876
|
+
if (o === false || o === 'false') return false;
|
|
13877
|
+
return null;
|
|
13878
|
+
}
|
|
13879
|
+
|
|
13843
13880
|
function isSvgMeasure(o) {
|
|
13844
13881
|
return utils.isFiniteNumber(o) || utils.isString(o) && /^-?[.0-9]+[a-z]*$/.test(o);
|
|
13845
13882
|
}
|
|
@@ -13863,6 +13900,7 @@
|
|
|
13863
13900
|
getSymbolPropertyAccessor: getSymbolPropertyAccessor,
|
|
13864
13901
|
isSvgClassName: isSvgClassName,
|
|
13865
13902
|
isSvgNumber: isSvgNumber,
|
|
13903
|
+
parseBoolean: parseBoolean,
|
|
13866
13904
|
isSvgMeasure: isSvgMeasure,
|
|
13867
13905
|
parseSvgMeasure: parseSvgMeasure,
|
|
13868
13906
|
isSvgColor: isSvgColor
|
|
@@ -14081,6 +14119,9 @@
|
|
|
14081
14119
|
o = importLineString(coords[i]);
|
|
14082
14120
|
o.properties.d = d + o.properties.d + ' Z';
|
|
14083
14121
|
}
|
|
14122
|
+
if (coords.length > 1) {
|
|
14123
|
+
o.properties['fill-rule'] = 'evenodd'; // support polygons with holes
|
|
14124
|
+
}
|
|
14084
14125
|
return o;
|
|
14085
14126
|
}
|
|
14086
14127
|
|
|
@@ -17997,6 +18038,10 @@ ${svg}
|
|
|
17997
18038
|
return chunks;
|
|
17998
18039
|
}
|
|
17999
18040
|
|
|
18041
|
+
function parseNumberList(token) {
|
|
18042
|
+
return token.split(',').map(parseFloat);
|
|
18043
|
+
}
|
|
18044
|
+
|
|
18000
18045
|
// Split comma-delimited list, trim quotes from entire list and
|
|
18001
18046
|
// individual members
|
|
18002
18047
|
function parseStringList(token) {
|
|
@@ -18086,6 +18131,7 @@ ${svg}
|
|
|
18086
18131
|
var OptionParsingUtils = /*#__PURE__*/Object.freeze({
|
|
18087
18132
|
__proto__: null,
|
|
18088
18133
|
splitShellTokens: splitShellTokens,
|
|
18134
|
+
parseNumberList: parseNumberList,
|
|
18089
18135
|
parseStringList: parseStringList,
|
|
18090
18136
|
parseColorList: parseColorList,
|
|
18091
18137
|
cleanArgv: cleanArgv,
|
|
@@ -18277,7 +18323,7 @@ ${svg}
|
|
|
18277
18323
|
} else if (type == 'strings') {
|
|
18278
18324
|
val = parseStringList(token);
|
|
18279
18325
|
} else if (type == 'bbox' || type == 'numbers') {
|
|
18280
|
-
val = token
|
|
18326
|
+
val = parseNumberList(token);
|
|
18281
18327
|
} else if (type == 'percent') {
|
|
18282
18328
|
// val = utils.parsePercent(token);
|
|
18283
18329
|
val = token; // string value is parsed by command function
|
|
@@ -20068,47 +20114,82 @@ ${svg}
|
|
|
20068
20114
|
type: 'distance'
|
|
20069
20115
|
})
|
|
20070
20116
|
.option('sides', {
|
|
20071
|
-
describe: 'sides of a polygon
|
|
20117
|
+
describe: 'number of sides of a polygon symbol',
|
|
20072
20118
|
type: 'number'
|
|
20073
20119
|
})
|
|
20120
|
+
.option('orientation', {
|
|
20121
|
+
// TODO: removed (replaced by flipped and rotated)
|
|
20122
|
+
// describe: 'use orientation=b for a rotated or flipped orientation'
|
|
20123
|
+
})
|
|
20124
|
+
.option('flipped', {
|
|
20125
|
+
type: 'flag',
|
|
20126
|
+
describe: 'symbol is vertically flipped'
|
|
20127
|
+
})
|
|
20128
|
+
.option('rotated', {
|
|
20129
|
+
type: 'flag',
|
|
20130
|
+
describe: 'symbol is rotated to a different orientation'
|
|
20131
|
+
})
|
|
20074
20132
|
.option('rotation', {
|
|
20075
20133
|
describe: 'rotation of symbol in degrees'
|
|
20076
20134
|
})
|
|
20077
|
-
.option('
|
|
20078
|
-
describe: '
|
|
20135
|
+
.option('points', {
|
|
20136
|
+
describe: '(star) number of points'
|
|
20137
|
+
})
|
|
20138
|
+
.option('point-ratio', {
|
|
20139
|
+
old_alias: 'star-ratio',
|
|
20140
|
+
describe: '(star) ratio of minor to major radius of star',
|
|
20141
|
+
type: 'number'
|
|
20142
|
+
})
|
|
20143
|
+
.option('radii', {
|
|
20144
|
+
describe: '(ring) comma-sep. list of concentric radii, ascending order'
|
|
20079
20145
|
})
|
|
20080
20146
|
.option('length', {
|
|
20081
|
-
|
|
20147
|
+
old_alias: 'arrow-length',
|
|
20148
|
+
describe: '(arrow) length of arrow in pixels'
|
|
20082
20149
|
})
|
|
20083
|
-
.option('
|
|
20084
|
-
|
|
20085
|
-
|
|
20150
|
+
.option('direction', {
|
|
20151
|
+
old_alias: 'arrow-direction',
|
|
20152
|
+
describe: '(arrow) angle off vertical (-90 = left-pointing)'
|
|
20086
20153
|
})
|
|
20087
|
-
.option('
|
|
20088
|
-
|
|
20154
|
+
.option('head-angle', {
|
|
20155
|
+
old_alias: 'arrow-head-angle',
|
|
20156
|
+
describe: '(arrow) angle of tip of arrow (default is 40 degrees)'
|
|
20089
20157
|
})
|
|
20090
|
-
.option('
|
|
20091
|
-
|
|
20158
|
+
.option('head-width', {
|
|
20159
|
+
old_alias: 'arrow-head-width',
|
|
20160
|
+
describe: '(arrow) width of arrow head from side to side'
|
|
20092
20161
|
})
|
|
20093
|
-
.option('
|
|
20094
|
-
|
|
20162
|
+
.option('head-length', {
|
|
20163
|
+
old_alias: 'arrow-head-width',
|
|
20164
|
+
describe: '(arrow) length of head (alternative to head-angle)'
|
|
20095
20165
|
})
|
|
20096
|
-
.option('
|
|
20097
|
-
describe: '
|
|
20166
|
+
.option('head-shape', {
|
|
20167
|
+
// describe: 'options: a b c'
|
|
20098
20168
|
})
|
|
20099
|
-
.option('
|
|
20100
|
-
|
|
20169
|
+
.option('stem-width', {
|
|
20170
|
+
old_alias: 'arrow-stem-width',
|
|
20171
|
+
describe: '(arrow) width of stem at its widest point'
|
|
20101
20172
|
})
|
|
20102
|
-
.option('
|
|
20103
|
-
|
|
20173
|
+
.option('stem-length', {
|
|
20174
|
+
old_alias: 'arrow-stem-length',
|
|
20175
|
+
describe: '(arrow) alternative to length'
|
|
20104
20176
|
})
|
|
20105
|
-
.option('
|
|
20106
|
-
|
|
20177
|
+
.option('stem-taper', {
|
|
20178
|
+
old_alias: 'arrow-stem-taper',
|
|
20179
|
+
describe: '(arrow) factor for tapering the width of the stem (0-1)'
|
|
20107
20180
|
})
|
|
20108
|
-
.option('
|
|
20109
|
-
|
|
20181
|
+
.option('stem-curve', {
|
|
20182
|
+
old_alias: 'arrow-stem-curve',
|
|
20183
|
+
describe: '(arrow) curvature in degrees (default is 0)'
|
|
20184
|
+
})
|
|
20185
|
+
.option('min-stem-ratio', {
|
|
20186
|
+
old_alias: 'arrow-min-stem',
|
|
20187
|
+
describe: '(arrow) min ratio of stem to total length',
|
|
20110
20188
|
type: 'number'
|
|
20111
20189
|
})
|
|
20190
|
+
.option('anchor', {
|
|
20191
|
+
describe: '(arrow) takes one of: start, middle, end (default is start)'
|
|
20192
|
+
})
|
|
20112
20193
|
.option('stroke', {})
|
|
20113
20194
|
.option('stroke-width', {})
|
|
20114
20195
|
.option('fill', {
|
|
@@ -21643,7 +21724,7 @@ ${svg}
|
|
|
21643
21724
|
collectionType = 'mixed';
|
|
21644
21725
|
}
|
|
21645
21726
|
} else if (currType != t) {
|
|
21646
|
-
stop("Unable to import mixed-geometry
|
|
21727
|
+
stop("Unable to import mixed-geometry features");
|
|
21647
21728
|
}
|
|
21648
21729
|
}
|
|
21649
21730
|
|
|
@@ -21754,6 +21835,33 @@ ${svg}
|
|
|
21754
21835
|
importShp: importShp
|
|
21755
21836
|
});
|
|
21756
21837
|
|
|
21838
|
+
function importGeoJSON(src, optsArg) {
|
|
21839
|
+
var opts = optsArg || {};
|
|
21840
|
+
var supportedGeometries = Object.keys(GeoJSON.pathImporters),
|
|
21841
|
+
srcObj = utils.isString(src) ? JSON.parse(src) : src,
|
|
21842
|
+
importer = new GeoJSONParser(opts),
|
|
21843
|
+
srcCollection, dataset;
|
|
21844
|
+
|
|
21845
|
+
// Convert single feature or geometry into a collection with one member
|
|
21846
|
+
if (srcObj.type == 'Feature') {
|
|
21847
|
+
srcCollection = {
|
|
21848
|
+
type: 'FeatureCollection',
|
|
21849
|
+
features: [srcObj]
|
|
21850
|
+
};
|
|
21851
|
+
} else if (supportedGeometries.includes(srcObj.type)) {
|
|
21852
|
+
srcCollection = {
|
|
21853
|
+
type: 'GeometryCollection',
|
|
21854
|
+
geometries: [srcObj]
|
|
21855
|
+
};
|
|
21856
|
+
} else {
|
|
21857
|
+
srcCollection = srcObj;
|
|
21858
|
+
}
|
|
21859
|
+
(srcCollection.features || srcCollection.geometries || []).forEach(importer.parseObject);
|
|
21860
|
+
dataset = importer.done();
|
|
21861
|
+
importCRS(dataset, srcObj); // TODO: remove this
|
|
21862
|
+
return dataset;
|
|
21863
|
+
}
|
|
21864
|
+
|
|
21757
21865
|
function GeoJSONParser(opts) {
|
|
21758
21866
|
var idField = opts.id_field || GeoJSON.ID_FIELD,
|
|
21759
21867
|
importer = new PathImporter(opts),
|
|
@@ -21775,8 +21883,11 @@ ${svg}
|
|
|
21775
21883
|
geom = o;
|
|
21776
21884
|
}
|
|
21777
21885
|
// TODO: improve so geometry_type option skips features instead of creating null geometries
|
|
21778
|
-
|
|
21779
|
-
|
|
21886
|
+
if (geom && geom.type == 'GeometryCollection') {
|
|
21887
|
+
GeoJSON.importComplexFeature(importer, geom, rec, opts);
|
|
21888
|
+
} else {
|
|
21889
|
+
GeoJSON.importSimpleFeature(importer, geom, rec, opts);
|
|
21890
|
+
}
|
|
21780
21891
|
};
|
|
21781
21892
|
|
|
21782
21893
|
this.done = function() {
|
|
@@ -21784,50 +21895,58 @@ ${svg}
|
|
|
21784
21895
|
};
|
|
21785
21896
|
}
|
|
21786
21897
|
|
|
21787
|
-
function
|
|
21788
|
-
var
|
|
21789
|
-
|
|
21790
|
-
|
|
21791
|
-
|
|
21792
|
-
srcCollection, dataset;
|
|
21793
|
-
|
|
21794
|
-
// Convert single feature or geometry into a collection with one member
|
|
21795
|
-
if (srcObj.type == 'Feature') {
|
|
21796
|
-
srcCollection = {
|
|
21797
|
-
type: 'FeatureCollection',
|
|
21798
|
-
features: [srcObj]
|
|
21799
|
-
};
|
|
21800
|
-
} else if (supportedGeometries.includes(srcObj.type)) {
|
|
21801
|
-
srcCollection = {
|
|
21802
|
-
type: 'GeometryCollection',
|
|
21803
|
-
geometries: [srcObj]
|
|
21804
|
-
};
|
|
21805
|
-
} else {
|
|
21806
|
-
srcCollection = srcObj;
|
|
21898
|
+
GeoJSON.importComplexFeature = function(importer, geom, rec, opts) {
|
|
21899
|
+
var types = divideGeometriesByType(geom.geometries || []);
|
|
21900
|
+
if (types.length === 0) {
|
|
21901
|
+
importer.startShape(rec); // import a feature with null geometry
|
|
21902
|
+
return;
|
|
21807
21903
|
}
|
|
21808
|
-
(
|
|
21809
|
-
|
|
21810
|
-
|
|
21811
|
-
|
|
21904
|
+
types.forEach(function(geometries, i) {
|
|
21905
|
+
importer.startShape(copyRecord(rec));
|
|
21906
|
+
geometries.forEach(function(geom) {
|
|
21907
|
+
GeoJSON.importSimpleGeometry(importer, geom, opts);
|
|
21908
|
+
});
|
|
21909
|
+
});
|
|
21910
|
+
};
|
|
21911
|
+
|
|
21912
|
+
function divideGeometriesByType(geometries, index) {
|
|
21913
|
+
index = index || {};
|
|
21914
|
+
geometries.forEach(function(geom) {
|
|
21915
|
+
if (!geom) return;
|
|
21916
|
+
var mtype = GeoJSON.translateGeoJSONType(geom.type);
|
|
21917
|
+
if (mtype) {
|
|
21918
|
+
if (mtype in index === false) {
|
|
21919
|
+
index[mtype] = [];
|
|
21920
|
+
}
|
|
21921
|
+
index[mtype].push(geom);
|
|
21922
|
+
} else if (geom.type == 'GeometryCollection') {
|
|
21923
|
+
divideGeometriesByType(geom.geometries || [], index);
|
|
21924
|
+
}
|
|
21925
|
+
});
|
|
21926
|
+
return Object.values(index);
|
|
21812
21927
|
}
|
|
21813
21928
|
|
|
21814
|
-
GeoJSON.
|
|
21815
|
-
|
|
21816
|
-
|
|
21929
|
+
GeoJSON.importSimpleFeature = function(importer, geom, rec, opts) {
|
|
21930
|
+
importer.startShape(rec);
|
|
21931
|
+
GeoJSON.importSimpleGeometry(importer, geom, opts);
|
|
21932
|
+
};
|
|
21933
|
+
|
|
21934
|
+
GeoJSON.importSimpleGeometry = function(importer, geom, opts) {
|
|
21935
|
+
var type = geom ? geom.type : null;
|
|
21936
|
+
if (type === null) {
|
|
21937
|
+
// no geometry to import
|
|
21938
|
+
} else if (type in GeoJSON.pathImporters) {
|
|
21817
21939
|
if (opts.geometry_type && opts.geometry_type != GeoJSON.translateGeoJSONType(type)) {
|
|
21818
21940
|
// kludge to filter out all but one type of geometry
|
|
21819
21941
|
return;
|
|
21820
21942
|
}
|
|
21821
21943
|
GeoJSON.pathImporters[type](geom.coordinates, importer);
|
|
21822
|
-
} else if (type == 'GeometryCollection') {
|
|
21823
|
-
geom.geometries.forEach(function(geom) {
|
|
21824
|
-
GeoJSON.importGeometry(geom, importer, opts);
|
|
21825
|
-
});
|
|
21826
21944
|
} else {
|
|
21827
|
-
verbose("
|
|
21945
|
+
verbose("Unsupported geometry type:", geom.type);
|
|
21828
21946
|
}
|
|
21829
21947
|
};
|
|
21830
21948
|
|
|
21949
|
+
|
|
21831
21950
|
// Functions for importing geometry coordinates using a PathImporter
|
|
21832
21951
|
//
|
|
21833
21952
|
GeoJSON.pathImporters = {
|
|
@@ -21866,8 +21985,8 @@ ${svg}
|
|
|
21866
21985
|
|
|
21867
21986
|
var GeojsonImport = /*#__PURE__*/Object.freeze({
|
|
21868
21987
|
__proto__: null,
|
|
21869
|
-
GeoJSONParser: GeoJSONParser,
|
|
21870
21988
|
importGeoJSON: importGeoJSON,
|
|
21989
|
+
GeoJSONParser: GeoJSONParser,
|
|
21871
21990
|
importCRS: importCRS
|
|
21872
21991
|
});
|
|
21873
21992
|
|
|
@@ -37929,111 +38048,153 @@ ${svg}
|
|
|
37929
38048
|
points.push(p2);
|
|
37930
38049
|
}
|
|
37931
38050
|
|
|
37932
|
-
function getStickArrowCoords(d, totalLen) {
|
|
37933
|
-
|
|
37934
|
-
|
|
37935
|
-
|
|
37936
|
-
|
|
37937
|
-
|
|
37938
|
-
|
|
37939
|
-
|
|
37940
|
-
|
|
37941
|
-
|
|
37942
|
-
|
|
37943
|
-
|
|
37944
|
-
|
|
37945
|
-
|
|
37946
|
-
|
|
37947
|
-
|
|
37948
|
-
|
|
37949
|
-
|
|
37950
|
-
|
|
37951
|
-
|
|
37952
|
-
}
|
|
37953
|
-
|
|
37954
|
-
function
|
|
37955
|
-
|
|
37956
|
-
|
|
37957
|
-
|
|
37958
|
-
|
|
37959
|
-
|
|
37960
|
-
|
|
37961
|
-
|
|
37962
|
-
|
|
37963
|
-
|
|
37964
|
-
|
|
37965
|
-
scale = getScale(totalLen, unscaledHeadLen, minStemRatio),
|
|
37966
|
-
headWidth = unscaledHeadWidth * scale,
|
|
37967
|
-
headLen = unscaledHeadLen * scale,
|
|
37968
|
-
stemWidth = unscaledStemWidth * scale,
|
|
37969
|
-
stemTaper = d['arrow-stem-taper'] || 0,
|
|
37970
|
-
stemCurve = d['arrow-stem-curve'] || 0,
|
|
37971
|
-
stemLen = totalLen - headLen,
|
|
37972
|
-
coords;
|
|
37973
|
-
|
|
37974
|
-
var headDx = headWidth / 2,
|
|
37975
|
-
stemDx = stemWidth / 2,
|
|
37976
|
-
baseDx = stemDx * (1 - stemTaper);
|
|
37977
|
-
|
|
37978
|
-
if (unscaledHeadWidth < unscaledStemWidth) {
|
|
37979
|
-
stop('Arrow head must be at least as wide as the stem.');
|
|
37980
|
-
}
|
|
38051
|
+
// export function getStickArrowCoords(d, totalLen) {
|
|
38052
|
+
// var minStemRatio = getMinStemRatio(d);
|
|
38053
|
+
// var headAngle = d['arrow-head-angle'] || 90;
|
|
38054
|
+
// var curve = d['arrow-stem-curve'] || 0;
|
|
38055
|
+
// var unscaledHeadWidth = d['arrow-head-width'] || 9;
|
|
38056
|
+
// var unscaledHeadLen = getHeadLength(unscaledHeadWidth, headAngle);
|
|
38057
|
+
// var scale = getScale(totalLen, unscaledHeadLen, minStemRatio);
|
|
38058
|
+
// var headWidth = unscaledHeadWidth * scale;
|
|
38059
|
+
// var headLen = unscaledHeadLen * scale;
|
|
38060
|
+
// var tip = getStickArrowTip(totalLen, curve);
|
|
38061
|
+
// var stem = [[0, 0], tip.concat()];
|
|
38062
|
+
// if (curve) {
|
|
38063
|
+
// addBezierArcControlPoints(stem, curve);
|
|
38064
|
+
// }
|
|
38065
|
+
// if (!headLen) return [stem];
|
|
38066
|
+
// var head = [addPoints([-headWidth / 2, -headLen], tip), tip.concat(), addPoints([headWidth / 2, -headLen], tip)];
|
|
38067
|
+
|
|
38068
|
+
// rotateCoords(stem, d.rotation);
|
|
38069
|
+
// rotateCoords(head, d.rotation);
|
|
38070
|
+
// return [stem, head];
|
|
38071
|
+
// }
|
|
38072
|
+
|
|
38073
|
+
// function getStickArrowTip(totalLen, curve) {
|
|
38074
|
+
// // curve/2 intersects the arrowhead at 90deg (trigonometry)
|
|
38075
|
+
// var theta = Math.abs(curve/2) / 180 * Math.PI;
|
|
38076
|
+
// var dx = totalLen * Math.sin(theta) * (curve > 0 ? -1 : 1);
|
|
38077
|
+
// var dy = totalLen * Math.cos(theta);
|
|
38078
|
+
// return [dx, dy];
|
|
38079
|
+
// }
|
|
38080
|
+
|
|
38081
|
+
// function addPoints(a, b) {
|
|
38082
|
+
// return [a[0] + b[0], a[1] + b[1]];
|
|
38083
|
+
// }
|
|
37981
38084
|
|
|
37982
|
-
|
|
37983
|
-
|
|
38085
|
+
function calcStraightArrowCoords(stemLen, headLen, stemDx, headDx, baseDx) {
|
|
38086
|
+
return [[baseDx, 0], [stemDx, stemLen], [headDx, stemLen], [0, stemLen + headLen],
|
|
37984
38087
|
[-headDx, stemLen], [-stemDx, stemLen], [-baseDx, 0], [baseDx, 0]];
|
|
37985
|
-
|
|
37986
|
-
|
|
37987
|
-
|
|
38088
|
+
}
|
|
38089
|
+
|
|
38090
|
+
function calcArrowSize(d) {
|
|
38091
|
+
var totalLen = d.radius || d.length || d.r || 0,
|
|
38092
|
+
scale = 1,
|
|
38093
|
+
o = initArrowSize(d); // calc several parameters
|
|
38094
|
+
|
|
38095
|
+
if (totalLen > 0) {
|
|
38096
|
+
scale = calcScale(totalLen, o.headLen, d);
|
|
38097
|
+
o.stemWidth *= scale;
|
|
38098
|
+
o.headWidth *= scale;
|
|
38099
|
+
o.headLen *= scale;
|
|
38100
|
+
o.stemLen = totalLen - o.headLen;
|
|
37988
38101
|
}
|
|
37989
38102
|
|
|
37990
|
-
|
|
37991
|
-
|
|
38103
|
+
if (o.headWidth < o.stemWidth) {
|
|
38104
|
+
stop('Arrow head must be at least as wide as the stem.');
|
|
38105
|
+
}
|
|
38106
|
+
return o;
|
|
37992
38107
|
}
|
|
37993
38108
|
|
|
37994
|
-
|
|
37995
|
-
|
|
38109
|
+
function calcScale(totalLen, headLen, d) {
|
|
38110
|
+
var minStemRatio = d['min-stem-ratio'] >= 0 ? d['min-stem-ratio'] : 0;
|
|
38111
|
+
var stemLen = d['stem-length'] || 0;
|
|
37996
38112
|
var maxHeadPct = 1 - minStemRatio;
|
|
37997
38113
|
var headPct = headLen / totalLen;
|
|
38114
|
+
var scale = 1;
|
|
38115
|
+
|
|
37998
38116
|
if (headPct > maxHeadPct) {
|
|
37999
|
-
|
|
38117
|
+
scale = maxHeadPct / headPct;
|
|
38118
|
+
} else if (stemLen + headLen > totalLen) {
|
|
38119
|
+
scale = totalLen / (stemLen + headLen);
|
|
38000
38120
|
}
|
|
38001
|
-
return
|
|
38121
|
+
return scale;
|
|
38002
38122
|
}
|
|
38003
38123
|
|
|
38004
|
-
function
|
|
38005
|
-
|
|
38006
|
-
var
|
|
38007
|
-
|
|
38008
|
-
|
|
38009
|
-
|
|
38124
|
+
function initArrowSize(d) {
|
|
38125
|
+
var sizeRatio = getHeadSizeRatio(d['head-angle'] || 40); // length to width
|
|
38126
|
+
var o = {
|
|
38127
|
+
stemWidth: d['stem-width'] || 2,
|
|
38128
|
+
stemLen: d['stem-length'] || 0,
|
|
38129
|
+
headWidth: d['head-width'],
|
|
38130
|
+
headLen: d['head-length']
|
|
38131
|
+
};
|
|
38132
|
+
if (!o.headWidth) {
|
|
38133
|
+
if (o.headLen) {
|
|
38134
|
+
o.headWidth = o.headLen / sizeRatio;
|
|
38135
|
+
} else {
|
|
38136
|
+
o.headWidth = o.stemWidth * 3; // assumes stemWidth has been set
|
|
38137
|
+
}
|
|
38138
|
+
}
|
|
38139
|
+
if (!o.headLen) {
|
|
38140
|
+
o.headLen = o.headWidth * sizeRatio;
|
|
38141
|
+
}
|
|
38142
|
+
return o;
|
|
38010
38143
|
}
|
|
38011
38144
|
|
|
38012
|
-
function addPoints(a, b) {
|
|
38013
|
-
return [a[0] + b[0], a[1] + b[1]];
|
|
38014
|
-
}
|
|
38015
38145
|
|
|
38146
|
+
// Returns ratio of head length to head width
|
|
38147
|
+
function getHeadSizeRatio(headAngle) {
|
|
38148
|
+
return 1 / Math.tan(Math.PI * headAngle / 180 / 2) / 2;
|
|
38149
|
+
}
|
|
38150
|
+
|
|
38151
|
+
function getFilledArrowCoords(d) {
|
|
38152
|
+
var direction = d.rotation || d.direction || 0,
|
|
38153
|
+
stemTaper = d['stem-taper'] || 0,
|
|
38154
|
+
curvature = d['stem-curve'] || 0,
|
|
38155
|
+
size = calcArrowSize(d);
|
|
38156
|
+
if (!size) return null;
|
|
38157
|
+
var stemLen = size.stemLen,
|
|
38158
|
+
headLen = size.headLen,
|
|
38159
|
+
headDx = size.headWidth / 2,
|
|
38160
|
+
stemDx = size.stemWidth / 2,
|
|
38161
|
+
baseDx = stemDx * (1 - stemTaper),
|
|
38162
|
+
head, stem, coords, dx, dy;
|
|
38163
|
+
|
|
38164
|
+
if (curvature) {
|
|
38165
|
+
if (direction > 0) curvature = -curvature;
|
|
38166
|
+
var theta = Math.abs(curvature) / 180 * Math.PI;
|
|
38167
|
+
var sign = curvature > 0 ? 1 : -1;
|
|
38168
|
+
var ax = baseDx * Math.cos(theta); // rotate arrow base
|
|
38169
|
+
var ay = baseDx * Math.sin(theta) * -sign;
|
|
38170
|
+
dx = stemLen * Math.sin(theta / 2) * sign;
|
|
38171
|
+
dy = stemLen * Math.cos(theta / 2);
|
|
38172
|
+
var leftStem = getCurvedStemCoords(-ax, -ay, -stemDx + dx, dy, theta);
|
|
38173
|
+
var rightStem = getCurvedStemCoords(ax, ay, stemDx + dx, dy, theta);
|
|
38174
|
+
stem = leftStem.concat(rightStem.reverse());
|
|
38016
38175
|
|
|
38017
|
-
|
|
38018
|
-
|
|
38019
|
-
|
|
38020
|
-
|
|
38176
|
+
} else {
|
|
38177
|
+
dx = 0;
|
|
38178
|
+
dy = stemLen;
|
|
38179
|
+
stem = [[-baseDx, 0], [baseDx, 0], [baseDx, 0]];
|
|
38180
|
+
}
|
|
38021
38181
|
|
|
38022
|
-
function getCurvedArrowCoords(stemLen, headLen, curvature, stemDx, headDx, baseDx) {
|
|
38023
38182
|
// coordinates go counter clockwise, starting from the leftmost head coordinate
|
|
38024
|
-
|
|
38025
|
-
|
|
38026
|
-
|
|
38027
|
-
|
|
38028
|
-
|
|
38029
|
-
|
|
38030
|
-
|
|
38031
|
-
|
|
38032
|
-
|
|
38033
|
-
|
|
38034
|
-
|
|
38035
|
-
|
|
38036
|
-
|
|
38183
|
+
head = [[stemDx + dx, dy], [headDx + dx, dy],
|
|
38184
|
+
[dx, headLen + dy], [-headDx + dx, dy], [-stemDx + dx, dy]];
|
|
38185
|
+
|
|
38186
|
+
coords = stem.concat(head);
|
|
38187
|
+
if (d.anchor == 'end') {
|
|
38188
|
+
scaleAndShiftCoords(coords, 1, [-dx, -dy - headLen]);
|
|
38189
|
+
} else if (d.anchor == 'middle') {
|
|
38190
|
+
scaleAndShiftCoords(coords, 1, [-dx/2, (-dy - headLen)/2]);
|
|
38191
|
+
}
|
|
38192
|
+
|
|
38193
|
+
rotateCoords(coords, direction);
|
|
38194
|
+
if (d.flipped) {
|
|
38195
|
+
flipY(coords);
|
|
38196
|
+
}
|
|
38197
|
+
return [coords];
|
|
38037
38198
|
}
|
|
38038
38199
|
|
|
38039
38200
|
// ax, ay: point on the base
|
|
@@ -38070,15 +38231,45 @@ ${svg}
|
|
|
38070
38231
|
return coords;
|
|
38071
38232
|
}
|
|
38072
38233
|
|
|
38234
|
+
function getMinorRadius(points) {
|
|
38235
|
+
var innerAngle = 360 / points;
|
|
38236
|
+
var pointAngle = getDefaultPointAngle(points);
|
|
38237
|
+
var thetaA = Math.PI / 180 * innerAngle / 2;
|
|
38238
|
+
var thetaB = Math.PI / 180 * pointAngle / 2;
|
|
38239
|
+
var a = Math.tan(thetaB) / (Math.tan(thetaB) + Math.tan(thetaA));
|
|
38240
|
+
var c = a / Math.cos(thetaA);
|
|
38241
|
+
return c;
|
|
38242
|
+
}
|
|
38243
|
+
|
|
38244
|
+
|
|
38245
|
+
function getPointAngle(points, skip) {
|
|
38246
|
+
var unitAngle = 360 / points;
|
|
38247
|
+
var centerAngle = unitAngle * (skip + 1);
|
|
38248
|
+
return 180 - centerAngle;
|
|
38249
|
+
}
|
|
38250
|
+
|
|
38251
|
+
function getDefaultPointAngle(points) {
|
|
38252
|
+
var minSkip = 1;
|
|
38253
|
+
var maxSkip = Math.ceil(points / 2) - 2;
|
|
38254
|
+
var skip = Math.floor((maxSkip + minSkip) / 2);
|
|
38255
|
+
return getPointAngle(points, skip);
|
|
38256
|
+
}
|
|
38257
|
+
|
|
38073
38258
|
// sides: e.g. 5-pointed star has 10 sides
|
|
38074
38259
|
// radius: distance from center to point
|
|
38075
38260
|
//
|
|
38076
|
-
function getPolygonCoords(
|
|
38077
|
-
var
|
|
38078
|
-
|
|
38261
|
+
function getPolygonCoords(d) {
|
|
38262
|
+
var radius = d.radius || d.length || d.r;
|
|
38263
|
+
if (radius > 0 === false) return null;
|
|
38264
|
+
var type = d.type;
|
|
38265
|
+
var sides = +d.sides || getDefaultSides(type);
|
|
38079
38266
|
var isStar = type == 'star';
|
|
38080
|
-
if (isStar &&
|
|
38081
|
-
|
|
38267
|
+
if (isStar && d.points > 0) {
|
|
38268
|
+
sides = d.points * 2;
|
|
38269
|
+
}
|
|
38270
|
+
var starRatio = isStar ? d.star_ratio || getMinorRadius(sides / 2) : 0;
|
|
38271
|
+
if (isStar && (sides < 10 || sides % 2 !== 0)) {
|
|
38272
|
+
stop(`Invalid number of points for a star (${sides / 2})`);
|
|
38082
38273
|
} else if (sides >= 3 === false) {
|
|
38083
38274
|
stop(`Invalid number of sides (${sides})`);
|
|
38084
38275
|
}
|
|
@@ -38086,14 +38277,14 @@ ${svg}
|
|
|
38086
38277
|
angle = 360 / sides,
|
|
38087
38278
|
b = isStar ? 1 : 0.5,
|
|
38088
38279
|
theta, even, len;
|
|
38089
|
-
if (
|
|
38280
|
+
if (d.orientation == 'b' || d.flipped || d.rotated) {
|
|
38090
38281
|
b = 0;
|
|
38091
38282
|
}
|
|
38092
38283
|
for (var i=0; i<sides; i++) {
|
|
38093
38284
|
even = i % 2 == 0;
|
|
38094
38285
|
len = radius;
|
|
38095
38286
|
if (isStar && even) {
|
|
38096
|
-
len *=
|
|
38287
|
+
len *= starRatio;
|
|
38097
38288
|
}
|
|
38098
38289
|
theta = (i + b) * angle % 360;
|
|
38099
38290
|
coords.push(getPlanarSegmentEndpoint(0, 0, theta, len));
|
|
@@ -38117,6 +38308,37 @@ ${svg}
|
|
|
38117
38308
|
}[type] || 4;
|
|
38118
38309
|
}
|
|
38119
38310
|
|
|
38311
|
+
// Returns GeoJSON MultiPolygon coords
|
|
38312
|
+
function getRingCoords(d) {
|
|
38313
|
+
var radii = parseRings(d.radii || '2');
|
|
38314
|
+
var coords = [];
|
|
38315
|
+
var solidCenter = utils.isOdd(radii.length);
|
|
38316
|
+
var ring, hole;
|
|
38317
|
+
for (var i=0; i<radii.length; i++) {
|
|
38318
|
+
ring = getPolygonCoords({
|
|
38319
|
+
type: 'circle',
|
|
38320
|
+
radius: radii[i]
|
|
38321
|
+
});
|
|
38322
|
+
if (!solidCenter || i > 0) {
|
|
38323
|
+
i++;
|
|
38324
|
+
hole = ring;
|
|
38325
|
+
ring = getPolygonCoords({
|
|
38326
|
+
type: 'circle',
|
|
38327
|
+
radius: radii[i]
|
|
38328
|
+
});
|
|
38329
|
+
ring.push(hole[0]);
|
|
38330
|
+
}
|
|
38331
|
+
coords.push(ring);
|
|
38332
|
+
}
|
|
38333
|
+
return coords;
|
|
38334
|
+
}
|
|
38335
|
+
|
|
38336
|
+
function parseRings(arg) {
|
|
38337
|
+
var arr = Array.isArray(arg) ? arg : parseNumberList(arg);
|
|
38338
|
+
utils.genericSort(arr, true);
|
|
38339
|
+
return utils.uniq(arr);
|
|
38340
|
+
}
|
|
38341
|
+
|
|
38120
38342
|
// TODO: refactor to remove duplication in mapshaper-svg-style.js
|
|
38121
38343
|
cmd.symbols = function(inputLyr, dataset, opts) {
|
|
38122
38344
|
requireSinglePointLayer(inputLyr);
|
|
@@ -38133,16 +38355,17 @@ ${svg}
|
|
|
38133
38355
|
if (!shp) return null;
|
|
38134
38356
|
var d = getSymbolData(i);
|
|
38135
38357
|
var rec = records[i] || {};
|
|
38136
|
-
var
|
|
38358
|
+
var geojsonType = 'Polygon';
|
|
38359
|
+
var coords;
|
|
38137
38360
|
if (d.type == 'arrow') {
|
|
38138
|
-
|
|
38139
|
-
|
|
38361
|
+
coords = getFilledArrowCoords(d);
|
|
38362
|
+
} else if (d.type == 'ring') {
|
|
38363
|
+
coords = getRingCoords(d);
|
|
38364
|
+
geojsonType = 'MultiPolygon';
|
|
38140
38365
|
} else {
|
|
38141
|
-
|
|
38142
|
-
constructor = getPolygonCoords;
|
|
38366
|
+
coords = getPolygonCoords(d);
|
|
38143
38367
|
}
|
|
38144
|
-
if (
|
|
38145
|
-
coords = constructor(size, d, opts);
|
|
38368
|
+
if (!coords) return null;
|
|
38146
38369
|
rotateCoords(coords, +d.rotation || 0);
|
|
38147
38370
|
if (!polygonMode) {
|
|
38148
38371
|
flipY(coords);
|
|
@@ -38153,9 +38376,9 @@ ${svg}
|
|
|
38153
38376
|
if (polygonMode) {
|
|
38154
38377
|
scaleAndShiftCoords(coords, metersPerPx, shp[0]);
|
|
38155
38378
|
if (d.tfill) rec.fill = d.fill;
|
|
38156
|
-
return createGeometry(coords);
|
|
38379
|
+
return createGeometry(coords, geojsonType);
|
|
38157
38380
|
} else {
|
|
38158
|
-
rec['svg-symbol'] =
|
|
38381
|
+
rec['svg-symbol'] = makeSvgPolygonSymbol(coords, d, geojsonType);
|
|
38159
38382
|
}
|
|
38160
38383
|
});
|
|
38161
38384
|
|
|
@@ -38186,9 +38409,9 @@ ${svg}
|
|
|
38186
38409
|
return importGeoJSON(geojson);
|
|
38187
38410
|
}
|
|
38188
38411
|
|
|
38189
|
-
function createGeometry(coords) {
|
|
38412
|
+
function createGeometry(coords, type) {
|
|
38190
38413
|
return {
|
|
38191
|
-
type:
|
|
38414
|
+
type: type,
|
|
38192
38415
|
coordinates: coords
|
|
38193
38416
|
};
|
|
38194
38417
|
}
|
|
@@ -38201,7 +38424,12 @@ ${svg}
|
|
|
38201
38424
|
}
|
|
38202
38425
|
|
|
38203
38426
|
// Returns an svg-symbol data object for one symbol
|
|
38204
|
-
function
|
|
38427
|
+
function makeSvgPolygonSymbol(coords, properties, geojsonType) {
|
|
38428
|
+
if (geojsonType == 'MultiPolygon') {
|
|
38429
|
+
coords = convertMultiPolygonCoords(coords);
|
|
38430
|
+
} else if (geojsonType != 'Polygon') {
|
|
38431
|
+
error('Unsupported type:', geojsonType);
|
|
38432
|
+
}
|
|
38205
38433
|
roundCoordsForSVG(coords);
|
|
38206
38434
|
return {
|
|
38207
38435
|
type: 'polygon',
|
|
@@ -38210,9 +38438,14 @@ ${svg}
|
|
|
38210
38438
|
};
|
|
38211
38439
|
}
|
|
38212
38440
|
|
|
38441
|
+
function convertMultiPolygonCoords(coords) {
|
|
38442
|
+
return coords.reduce(function(memo, poly) {
|
|
38443
|
+
return memo.concat(poly);
|
|
38444
|
+
}, []);
|
|
38445
|
+
}
|
|
38446
|
+
|
|
38213
38447
|
var Symbols = /*#__PURE__*/Object.freeze({
|
|
38214
|
-
__proto__: null
|
|
38215
|
-
makeSvgSymbol: makeSvgSymbol
|
|
38448
|
+
__proto__: null
|
|
38216
38449
|
});
|
|
38217
38450
|
|
|
38218
38451
|
cmd.target = function(catalog, opts) {
|