mapshaper 0.6.0 → 0.6.2
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/README.md +3 -3
- package/mapshaper.js +205 -193
- package/package.json +6 -3
- package/www/mapshaper-gui.js +37 -41
- package/www/mapshaper.js +205 -193
package/www/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
3
|
+
var VERSION = "0.6.2";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -258,7 +258,7 @@
|
|
|
258
258
|
'/': '/'
|
|
259
259
|
};
|
|
260
260
|
function htmlEscape(s) {
|
|
261
|
-
return String(s).replace(/[&<>"'
|
|
261
|
+
return String(s).replace(/[&<>"'/]/g, function(s) {
|
|
262
262
|
return entityMap[s];
|
|
263
263
|
});
|
|
264
264
|
}
|
|
@@ -901,8 +901,8 @@
|
|
|
901
901
|
var type = matches[4];
|
|
902
902
|
var isString = type == 's',
|
|
903
903
|
isHex = type == 'x' || type == 'X',
|
|
904
|
-
isInt = type == 'd' || type == 'i',
|
|
905
|
-
isFloat = type == 'f',
|
|
904
|
+
// isInt = type == 'd' || type == 'i',
|
|
905
|
+
// isFloat = type == 'f',
|
|
906
906
|
isNumber = !isString;
|
|
907
907
|
|
|
908
908
|
var sign = "",
|
|
@@ -961,7 +961,7 @@
|
|
|
961
961
|
|
|
962
962
|
// Get a function for interpolating formatted values into a string.
|
|
963
963
|
function formatter(fmt) {
|
|
964
|
-
var codeRxp = /%([
|
|
964
|
+
var codeRxp = /%([',+0]*)([1-9]?)((?:\.[1-9])?)([sdifxX%])/g;
|
|
965
965
|
var literals = [],
|
|
966
966
|
formatCodes = [],
|
|
967
967
|
startIdx = 0,
|
|
@@ -3522,7 +3522,7 @@
|
|
|
3522
3522
|
if (typeof require == 'function') {
|
|
3523
3523
|
f = require;
|
|
3524
3524
|
} else {
|
|
3525
|
-
f = function(
|
|
3525
|
+
f = function() {
|
|
3526
3526
|
// console.error('Unable to load module', name);
|
|
3527
3527
|
};
|
|
3528
3528
|
}
|
|
@@ -6479,12 +6479,12 @@
|
|
|
6479
6479
|
// Accessor function for arcs
|
|
6480
6480
|
Object.defineProperty(this, 'arcs', {value: arcs});
|
|
6481
6481
|
|
|
6482
|
-
|
|
6482
|
+
this.toArray = function() {
|
|
6483
6483
|
var chains = getNodeChains(),
|
|
6484
6484
|
flags = new Uint8Array(chains.length),
|
|
6485
6485
|
arr = [];
|
|
6486
6486
|
utils.forEach(chains, function(nextIdx, thisIdx) {
|
|
6487
|
-
var node,
|
|
6487
|
+
var node, p;
|
|
6488
6488
|
if (flags[thisIdx] == 1) return;
|
|
6489
6489
|
p = getEndpoint(thisIdx);
|
|
6490
6490
|
if (!p) return; // endpoints of an excluded arc
|
|
@@ -12059,10 +12059,6 @@
|
|
|
12059
12059
|
// if point x,y falls on an endpoint
|
|
12060
12060
|
// Assumes: i <= j
|
|
12061
12061
|
function getCutPoint(x, y, i, j, xx, yy) {
|
|
12062
|
-
var ix = xx[i],
|
|
12063
|
-
iy = yy[i],
|
|
12064
|
-
jx = xx[j],
|
|
12065
|
-
jy = yy[j];
|
|
12066
12062
|
if (j < i || j > i + 1) {
|
|
12067
12063
|
error("Out-of-sequence arc ids:", i, j);
|
|
12068
12064
|
}
|
|
@@ -14048,18 +14044,18 @@
|
|
|
14048
14044
|
// accept variations on type names (dot, dots, square, squares, hatch, hatches, hatched)
|
|
14049
14045
|
if (first.startsWith('dot')) {
|
|
14050
14046
|
parts[0] = 'dots';
|
|
14051
|
-
obj = parseDots(parts
|
|
14047
|
+
obj = parseDots(parts);
|
|
14052
14048
|
} else if (first.startsWith('square')) {
|
|
14053
14049
|
parts[0] = 'squares';
|
|
14054
|
-
obj = parseDots(parts
|
|
14050
|
+
obj = parseDots(parts);
|
|
14055
14051
|
} else if (first.startsWith('hatch')) {
|
|
14056
14052
|
parts[0] = 'hatches';
|
|
14057
|
-
obj = parseHatches(parts
|
|
14053
|
+
obj = parseHatches(parts);
|
|
14058
14054
|
} else if (first.startsWith('dash')) {
|
|
14059
|
-
obj = parseDashes(parts
|
|
14055
|
+
obj = parseDashes(parts);
|
|
14060
14056
|
} else if (!isNaN(parseFloat(first))) {
|
|
14061
14057
|
parts.unshift('hatches');
|
|
14062
|
-
obj = parseHatches(parts
|
|
14058
|
+
obj = parseHatches(parts); // hatches is the default, name can be omitted
|
|
14063
14059
|
}
|
|
14064
14060
|
if (!obj) {
|
|
14065
14061
|
// consider
|
|
@@ -14068,7 +14064,7 @@
|
|
|
14068
14064
|
return obj;
|
|
14069
14065
|
}
|
|
14070
14066
|
|
|
14071
|
-
function parseDashes(parts
|
|
14067
|
+
function parseDashes(parts) {
|
|
14072
14068
|
// format:
|
|
14073
14069
|
// "dashes" dash-len dash-space width color1 [color2...] space bg-color
|
|
14074
14070
|
// examples:
|
|
@@ -14109,7 +14105,7 @@
|
|
|
14109
14105
|
};
|
|
14110
14106
|
}
|
|
14111
14107
|
|
|
14112
|
-
function parseHatches(parts
|
|
14108
|
+
function parseHatches(parts) {
|
|
14113
14109
|
// format:
|
|
14114
14110
|
// [hatches] [rotation] width1 color1 [width2 color2 ...]
|
|
14115
14111
|
// examples:
|
|
@@ -14136,7 +14132,7 @@
|
|
|
14136
14132
|
return parseInt(str) > 0;
|
|
14137
14133
|
}
|
|
14138
14134
|
|
|
14139
|
-
function parseDots(parts
|
|
14135
|
+
function parseDots(parts) {
|
|
14140
14136
|
// format:
|
|
14141
14137
|
// "dots"|"squares" [rotation] size color1 [color2 ...] spacing bg-color
|
|
14142
14138
|
// examples:
|
|
@@ -14300,6 +14296,7 @@
|
|
|
14300
14296
|
'stroke-opacity': 'number',
|
|
14301
14297
|
'stroke-miterlimit': 'number',
|
|
14302
14298
|
'fill-opacity': 'number',
|
|
14299
|
+
'vector-effect': null,
|
|
14303
14300
|
'text-anchor': null
|
|
14304
14301
|
};
|
|
14305
14302
|
|
|
@@ -14329,7 +14326,7 @@
|
|
|
14329
14326
|
effect: null // e.g. "fade"
|
|
14330
14327
|
}, stylePropertyTypes);
|
|
14331
14328
|
|
|
14332
|
-
var commonProperties = 'css,class,opacity,stroke,stroke-width,stroke-dasharray,stroke-opacity,fill-opacity'.split(',');
|
|
14329
|
+
var commonProperties = 'css,class,opacity,stroke,stroke-width,stroke-dasharray,stroke-opacity,fill-opacity,vector-effect'.split(',');
|
|
14333
14330
|
|
|
14334
14331
|
var propertiesBySymbolType = {
|
|
14335
14332
|
polygon: utils.arrayToIndex(commonProperties.concat('fill', 'fill-pattern')),
|
|
@@ -14409,7 +14406,7 @@
|
|
|
14409
14406
|
function mightBeExpression(str, fields) {
|
|
14410
14407
|
fields = fields || [];
|
|
14411
14408
|
if (fields.indexOf(str.trim()) > -1) return true;
|
|
14412
|
-
return /[(){}
|
|
14409
|
+
return /[(){}./*?:&|=[+-]/.test(str);
|
|
14413
14410
|
}
|
|
14414
14411
|
|
|
14415
14412
|
function getSymbolPropertyAccessor(val, svgName, lyr) {
|
|
@@ -14536,7 +14533,7 @@
|
|
|
14536
14533
|
|
|
14537
14534
|
function importGeoJSONFeatures(features, opts) {
|
|
14538
14535
|
opts = opts || {};
|
|
14539
|
-
return features.map(function(obj
|
|
14536
|
+
return features.map(function(obj) {
|
|
14540
14537
|
var geom = obj.type == 'Feature' ? obj.geometry : obj; // could be null
|
|
14541
14538
|
var geomType = geom && geom.type;
|
|
14542
14539
|
var msType = GeoJSON.translateGeoJSONType(geomType);
|
|
@@ -14852,7 +14849,7 @@
|
|
|
14852
14849
|
}
|
|
14853
14850
|
|
|
14854
14851
|
// polyline coords are like GeoJSON MultiLineString coords: an array of 0 or more paths
|
|
14855
|
-
function polyline(d
|
|
14852
|
+
function polyline(d) {
|
|
14856
14853
|
var coords = d.coordinates || [];
|
|
14857
14854
|
var o = importMultiLineString(coords);
|
|
14858
14855
|
applyStyleAttributes(o, 'polyline', d);
|
|
@@ -14860,7 +14857,7 @@
|
|
|
14860
14857
|
}
|
|
14861
14858
|
|
|
14862
14859
|
// polygon coords are an array of rings (and holes), like flattened MultiPolygon coords
|
|
14863
|
-
function polygon(d
|
|
14860
|
+
function polygon(d) {
|
|
14864
14861
|
var coords = d.coordinates || [];
|
|
14865
14862
|
var o = importPolygon(coords);
|
|
14866
14863
|
applyStyleAttributes(o, 'polygon', d);
|
|
@@ -15407,7 +15404,6 @@ ${svg}
|
|
|
15407
15404
|
var geojson = exportDatasetAsGeoJSON(d, opts);
|
|
15408
15405
|
var features = geojson.features || geojson.geometries || (geojson.type ? [geojson] : []);
|
|
15409
15406
|
var children = importGeoJSONFeatures(features, opts);
|
|
15410
|
-
var data;
|
|
15411
15407
|
if (opts.svg_data && lyr.data) {
|
|
15412
15408
|
addDataAttributesToSVG(children, lyr.data, opts.svg_data);
|
|
15413
15409
|
}
|
|
@@ -16336,7 +16332,7 @@ ${svg}
|
|
|
16336
16332
|
return readFixedWidthRecordsFromString(str, opts);
|
|
16337
16333
|
}
|
|
16338
16334
|
|
|
16339
|
-
function readFixedWidthRecordsFromString(str
|
|
16335
|
+
function readFixedWidthRecordsFromString(str) {
|
|
16340
16336
|
var fields = parseFixedWidthInfo(str.substring(0, 2000));
|
|
16341
16337
|
if (!fields) return [];
|
|
16342
16338
|
var lines = utils.splitLines(str);
|
|
@@ -16483,11 +16479,6 @@ ${svg}
|
|
|
16483
16479
|
return formatRow(rec);
|
|
16484
16480
|
}
|
|
16485
16481
|
|
|
16486
|
-
function formatDelimHeader(fields, delim) {
|
|
16487
|
-
var formatValue = getDelimValueFormatter(delim);
|
|
16488
|
-
return fields.map(formatValue).join(delim);
|
|
16489
|
-
}
|
|
16490
|
-
|
|
16491
16482
|
function getDelimRowFormatter(fields, delim, opts) {
|
|
16492
16483
|
var formatValue = getDelimValueFormatter(delim, opts);
|
|
16493
16484
|
return function(rec) {
|
|
@@ -18170,8 +18161,7 @@ ${svg}
|
|
|
18170
18161
|
// @chars String of chars to look for in @str
|
|
18171
18162
|
function getCharScore(str, chars) {
|
|
18172
18163
|
var index = {},
|
|
18173
|
-
count = 0
|
|
18174
|
-
score;
|
|
18164
|
+
count = 0;
|
|
18175
18165
|
str = str.toLowerCase();
|
|
18176
18166
|
for (var i=0, n=chars.length; i<n; i++) {
|
|
18177
18167
|
index[chars[i]] = 1;
|
|
@@ -18192,7 +18182,7 @@ ${svg}
|
|
|
18192
18182
|
// TODO: remove duplication with importJSON()
|
|
18193
18183
|
var readFromFile = !data.content && data.content !== '',
|
|
18194
18184
|
content = data.content,
|
|
18195
|
-
|
|
18185
|
+
reader, records, delimiter, table, encoding;
|
|
18196
18186
|
opts = opts || {};
|
|
18197
18187
|
|
|
18198
18188
|
// // read content of all but very large files into a buffer
|
|
@@ -18434,43 +18424,19 @@ ${svg}
|
|
|
18434
18424
|
}
|
|
18435
18425
|
}
|
|
18436
18426
|
|
|
18437
|
-
// var intervalStr = o.interval;
|
|
18438
|
-
// if (intervalStr) {
|
|
18439
|
-
// o.interval = Number(intervalStr);
|
|
18440
|
-
// if (o.interval >= 0 === false) {
|
|
18441
|
-
// error(utils.format("Out-of-range interval value: %s", intervalStr));
|
|
18442
|
-
// }
|
|
18443
|
-
// }
|
|
18444
|
-
|
|
18445
18427
|
if (!o.interval && !o.percentage && !o.resolution) {
|
|
18446
18428
|
error("Command requires an interval, percentage or resolution parameter");
|
|
18447
18429
|
}
|
|
18448
18430
|
}
|
|
18449
18431
|
|
|
18450
18432
|
function validateProjOpts(cmd) {
|
|
18451
|
-
var _ = cmd._
|
|
18452
|
-
proj4 = [];
|
|
18433
|
+
var _ = cmd._;
|
|
18453
18434
|
|
|
18454
18435
|
if (_.length > 0 && !cmd.options.crs) {
|
|
18455
18436
|
cmd.options.crs = _.join(' ');
|
|
18456
18437
|
_ = [];
|
|
18457
18438
|
}
|
|
18458
18439
|
|
|
18459
|
-
// separate proj4 options
|
|
18460
|
-
// _ = _.filter(function(arg) {
|
|
18461
|
-
// if (/^\+[a-z]/i.test(arg)) {
|
|
18462
|
-
// proj4.push(arg);
|
|
18463
|
-
// return false;
|
|
18464
|
-
// }
|
|
18465
|
-
// return true;
|
|
18466
|
-
// });
|
|
18467
|
-
|
|
18468
|
-
// if (proj4.length > 0) {
|
|
18469
|
-
// cmd.options.crs = proj4.join(' ');
|
|
18470
|
-
// } else if (_.length > 0) {
|
|
18471
|
-
// cmd.options.crs = _.shift();
|
|
18472
|
-
// }
|
|
18473
|
-
|
|
18474
18440
|
if (_.length > 0) {
|
|
18475
18441
|
error("Received one or more unexpected parameters: " + _.join(', '));
|
|
18476
18442
|
}
|
|
@@ -18565,7 +18531,7 @@ ${svg}
|
|
|
18565
18531
|
}
|
|
18566
18532
|
}
|
|
18567
18533
|
|
|
18568
|
-
var assignmentRxp = /^([a-z0-9_+-]+)=(
|
|
18534
|
+
var assignmentRxp = /^([a-z0-9_+-]+)=(?!=)(.*)$/i; // exclude ==
|
|
18569
18535
|
|
|
18570
18536
|
function splitShellTokens(str) {
|
|
18571
18537
|
var BAREWORD = '([^\'"\\s])+';
|
|
@@ -20953,6 +20919,10 @@ ${svg}
|
|
|
20953
20919
|
// describe: (0-1) inset grid shapes by a percentage
|
|
20954
20920
|
type: 'number'
|
|
20955
20921
|
})
|
|
20922
|
+
.option('aligned', {
|
|
20923
|
+
// describe: all grids of a given cell size will be aligned
|
|
20924
|
+
type: 'flag'
|
|
20925
|
+
})
|
|
20956
20926
|
.option('calc', calcOpt)
|
|
20957
20927
|
.option('name', nameOpt)
|
|
20958
20928
|
.option('target', targetOpt)
|
|
@@ -21099,6 +21069,9 @@ ${svg}
|
|
|
21099
21069
|
})
|
|
21100
21070
|
.option('target', targetOpt);
|
|
21101
21071
|
|
|
21072
|
+
parser.command('stop')
|
|
21073
|
+
.describe('stop processing (skip remaining commands)');
|
|
21074
|
+
|
|
21102
21075
|
parser.section('Informational commands');
|
|
21103
21076
|
|
|
21104
21077
|
parser.command('calc')
|
|
@@ -22760,7 +22733,6 @@ ${svg}
|
|
|
22760
22733
|
shapes = [], // topological ids
|
|
22761
22734
|
types = [],
|
|
22762
22735
|
dataNulls = 0,
|
|
22763
|
-
shapeNulls = 0,
|
|
22764
22736
|
collectionType = null,
|
|
22765
22737
|
shapeId;
|
|
22766
22738
|
|
|
@@ -22777,15 +22749,12 @@ ${svg}
|
|
|
22777
22749
|
if (geom.type) {
|
|
22778
22750
|
this.addShape(geom);
|
|
22779
22751
|
}
|
|
22780
|
-
if (shapes[shapeId] === null) {
|
|
22781
|
-
shapeNulls++;
|
|
22782
|
-
}
|
|
22783
22752
|
};
|
|
22784
22753
|
|
|
22785
22754
|
this.addShape = function(geom) {
|
|
22786
22755
|
var curr = shapes[shapeId];
|
|
22787
22756
|
var type = GeoJSON.translateGeoJSONType(geom.type);
|
|
22788
|
-
var shape
|
|
22757
|
+
var shape;
|
|
22789
22758
|
if (geom.type == "GeometryCollection") {
|
|
22790
22759
|
geom.geometries.forEach(this.addShape, this);
|
|
22791
22760
|
} else if (type) {
|
|
@@ -24065,12 +24034,12 @@ ${svg}
|
|
|
24065
24034
|
function Job(catalog) {
|
|
24066
24035
|
var currentCmd;
|
|
24067
24036
|
|
|
24068
|
-
|
|
24037
|
+
var job = {
|
|
24069
24038
|
catalog: catalog || new Catalog(),
|
|
24070
24039
|
defs: {},
|
|
24071
24040
|
settings: {},
|
|
24072
24041
|
input_files: []
|
|
24073
|
-
|
|
24042
|
+
};
|
|
24074
24043
|
|
|
24075
24044
|
job.initSettings = function(o) {
|
|
24076
24045
|
job.settings = o;
|
|
@@ -27125,10 +27094,6 @@ ${svg}
|
|
|
27125
27094
|
// polyline output could be used for debugging
|
|
27126
27095
|
var outputGeom = opts.output_geometry == 'polyline' ? 'polyline' : 'polygon';
|
|
27127
27096
|
|
|
27128
|
-
function polygonCoords(ring) {
|
|
27129
|
-
return [ring];
|
|
27130
|
-
}
|
|
27131
|
-
|
|
27132
27097
|
function pathBufferCoords(pathArcs, dist) {
|
|
27133
27098
|
var pathCoords = maker(pathArcs, dist);
|
|
27134
27099
|
var revPathArcs;
|
|
@@ -27158,13 +27123,9 @@ ${svg}
|
|
|
27158
27123
|
var backtrackSteps = opts.backtrack >= 0 ? opts.backtrack : 50;
|
|
27159
27124
|
var pathIter = new ShapeIter(arcs);
|
|
27160
27125
|
var capStyle = opts.cap_style || 'round'; // expect 'round' or 'flat'
|
|
27161
|
-
var tolerance;
|
|
27126
|
+
// var tolerance;
|
|
27162
27127
|
// TODO: implement other join styles than round
|
|
27163
27128
|
|
|
27164
|
-
function updateTolerance(dist) {
|
|
27165
|
-
|
|
27166
|
-
}
|
|
27167
|
-
|
|
27168
27129
|
function addRoundJoin(arr, x, y, startDir, angle, dist) {
|
|
27169
27130
|
var increment = 10;
|
|
27170
27131
|
var endDir = startDir + angle;
|
|
@@ -27175,15 +27136,15 @@ ${svg}
|
|
|
27175
27136
|
}
|
|
27176
27137
|
}
|
|
27177
27138
|
|
|
27178
|
-
function addRoundJoin2(arr, x, y, startDir, angle, dist) {
|
|
27179
|
-
|
|
27180
|
-
|
|
27181
|
-
|
|
27182
|
-
|
|
27183
|
-
|
|
27184
|
-
|
|
27185
|
-
|
|
27186
|
-
}
|
|
27139
|
+
// function addRoundJoin2(arr, x, y, startDir, angle, dist) {
|
|
27140
|
+
// var increment = 10;
|
|
27141
|
+
// var endDir = startDir + angle;
|
|
27142
|
+
// var dir = startDir + increment;
|
|
27143
|
+
// while (dir < endDir) {
|
|
27144
|
+
// addBufferVertex(arr, geod(x, y, dir, dist), backtrackSteps);
|
|
27145
|
+
// dir += increment;
|
|
27146
|
+
// }
|
|
27147
|
+
// }
|
|
27187
27148
|
|
|
27188
27149
|
// Test if two points are within a snapping tolerance
|
|
27189
27150
|
// TODO: calculate the tolerance more sensibly
|
|
@@ -27430,15 +27391,14 @@ ${svg}
|
|
|
27430
27391
|
function getPathBufferMaker2(arcs, geod, getBearing, opts) {
|
|
27431
27392
|
var backtrackSteps = opts.backtrack >= 0 ? opts.backtrack : 50;
|
|
27432
27393
|
var pathIter = new ShapeIter(arcs);
|
|
27433
|
-
var capStyle = opts.cap_style || 'round'; // expect 'round' or 'flat'
|
|
27434
|
-
var tolerance;
|
|
27394
|
+
// var capStyle = opts.cap_style || 'round'; // expect 'round' or 'flat'
|
|
27435
27395
|
var partials, left, center;
|
|
27436
27396
|
var bounds;
|
|
27437
27397
|
// TODO: implement other join styles than round
|
|
27438
27398
|
|
|
27439
|
-
function updateTolerance(dist) {
|
|
27399
|
+
// function updateTolerance(dist) {
|
|
27440
27400
|
|
|
27441
|
-
}
|
|
27401
|
+
// }
|
|
27442
27402
|
|
|
27443
27403
|
function addRoundJoin(x, y, startDir, angle, dist) {
|
|
27444
27404
|
var increment = 10;
|
|
@@ -27482,24 +27442,24 @@ ${svg}
|
|
|
27482
27442
|
}
|
|
27483
27443
|
}
|
|
27484
27444
|
|
|
27485
|
-
function makeCap(x, y, direction, dist) {
|
|
27486
|
-
|
|
27487
|
-
|
|
27488
|
-
|
|
27489
|
-
|
|
27490
|
-
}
|
|
27445
|
+
// function makeCap(x, y, direction, dist) {
|
|
27446
|
+
// if (capStyle == 'flat') {
|
|
27447
|
+
// return [[x, y]];
|
|
27448
|
+
// }
|
|
27449
|
+
// return makeRoundCap(x, y, direction, dist);
|
|
27450
|
+
// }
|
|
27491
27451
|
|
|
27492
|
-
function makeRoundCap(x, y, segmentDir, dist) {
|
|
27493
|
-
|
|
27494
|
-
|
|
27495
|
-
|
|
27496
|
-
|
|
27497
|
-
|
|
27498
|
-
|
|
27499
|
-
|
|
27500
|
-
|
|
27501
|
-
|
|
27502
|
-
}
|
|
27452
|
+
// function makeRoundCap(x, y, segmentDir, dist) {
|
|
27453
|
+
// var points = [];
|
|
27454
|
+
// var increment = 10;
|
|
27455
|
+
// var startDir = segmentDir - 90;
|
|
27456
|
+
// var angle = increment;
|
|
27457
|
+
// while (angle < 180) {
|
|
27458
|
+
// points.push(geod(x, y, startDir + angle, dist));
|
|
27459
|
+
// angle += increment;
|
|
27460
|
+
// }
|
|
27461
|
+
// return points;
|
|
27462
|
+
// }
|
|
27503
27463
|
|
|
27504
27464
|
// get angle between two extruded segments in degrees
|
|
27505
27465
|
// positive angle means join in convex (range: 0-180 degrees)
|
|
@@ -27596,18 +27556,20 @@ ${svg}
|
|
|
27596
27556
|
}
|
|
27597
27557
|
|
|
27598
27558
|
return function(path, dist) {
|
|
27599
|
-
var x0, y0
|
|
27559
|
+
// var x0, y0;
|
|
27560
|
+
var x1, y1, x2, y2;
|
|
27600
27561
|
var p1, p2;
|
|
27601
|
-
var
|
|
27562
|
+
// var firstBearing;
|
|
27563
|
+
var bearing, prevBearing, joinAngle;
|
|
27602
27564
|
partials = [];
|
|
27603
27565
|
left = [];
|
|
27604
27566
|
center = [];
|
|
27605
27567
|
pathIter.init(path);
|
|
27606
27568
|
|
|
27607
|
-
if (pathIter.hasNext()) {
|
|
27608
|
-
|
|
27609
|
-
|
|
27610
|
-
}
|
|
27569
|
+
// if (pathIter.hasNext()) {
|
|
27570
|
+
// x0 = x2 = pathIter.x;
|
|
27571
|
+
// y0 = y2 = pathIter.y;
|
|
27572
|
+
// }
|
|
27611
27573
|
while (pathIter.hasNext()) {
|
|
27612
27574
|
// TODO: use a tolerance
|
|
27613
27575
|
if (pathIter.x === x2 && pathIter.y === y2) continue; // skip duplicate points
|
|
@@ -27624,9 +27586,9 @@ ${svg}
|
|
|
27624
27586
|
|
|
27625
27587
|
if (center.length === 0) {
|
|
27626
27588
|
// first loop, second point in this partial
|
|
27627
|
-
if (partials.length === 0) {
|
|
27628
|
-
|
|
27629
|
-
}
|
|
27589
|
+
// if (partials.length === 0) {
|
|
27590
|
+
// firstBearing = bearing;
|
|
27591
|
+
// }
|
|
27630
27592
|
left.push(p1, p2);
|
|
27631
27593
|
center.push([x1, y1], [x2, y2]);
|
|
27632
27594
|
} else {
|
|
@@ -28207,7 +28169,7 @@ ${svg}
|
|
|
28207
28169
|
rings.push([
|
|
28208
28170
|
[[180, 90], [180, -90], [0, -90], [-180, -90], [-180, 90], [0, 90], [180, 90]],
|
|
28209
28171
|
coords
|
|
28210
|
-
|
|
28172
|
+
]);
|
|
28211
28173
|
} else {
|
|
28212
28174
|
rings.push([coords]);
|
|
28213
28175
|
}
|
|
@@ -34899,6 +34861,7 @@ ${svg}
|
|
|
34899
34861
|
// }).join(",") + "}");
|
|
34900
34862
|
// };
|
|
34901
34863
|
|
|
34864
|
+
// Removes points that are far from other points
|
|
34902
34865
|
cmd.filterPoints = function(lyr, dataset, opts) {
|
|
34903
34866
|
requireSinglePointLayer(lyr);
|
|
34904
34867
|
if (opts.group_interval > 0 === false) {
|
|
@@ -34913,7 +34876,7 @@ ${svg}
|
|
|
34913
34876
|
var index = new Uint8Array(points.length);
|
|
34914
34877
|
var a, b, c, ai, bi, ci;
|
|
34915
34878
|
for (var i=0, n=triangles.length; i<n; i+=3) {
|
|
34916
|
-
// a, b, c: triangle
|
|
34879
|
+
// a, b, c: triangle vertices in CCW order
|
|
34917
34880
|
ai = triangles[i];
|
|
34918
34881
|
bi = triangles[i+1];
|
|
34919
34882
|
ci = triangles[i+2];
|
|
@@ -36085,7 +36048,7 @@ ${svg}
|
|
|
36085
36048
|
var arcId = o.arcId,
|
|
36086
36049
|
key = classify(arcId),
|
|
36087
36050
|
isContinuation, line;
|
|
36088
|
-
if (
|
|
36051
|
+
if (key) {
|
|
36089
36052
|
line = key in index ? index[key] : null;
|
|
36090
36053
|
isContinuation = key == prevKey && o.shapeId == prev.shapeId && o.partId == prev.partId;
|
|
36091
36054
|
if (!line) {
|
|
@@ -36765,6 +36728,14 @@ ${svg}
|
|
|
36765
36728
|
job.control = null;
|
|
36766
36729
|
}
|
|
36767
36730
|
|
|
36731
|
+
function stopJob(job) {
|
|
36732
|
+
getState(job).stopped = true;
|
|
36733
|
+
}
|
|
36734
|
+
|
|
36735
|
+
function jobIsStopped(job) {
|
|
36736
|
+
return getState(job).stopped === true;
|
|
36737
|
+
}
|
|
36738
|
+
|
|
36768
36739
|
function inControlBlock(job) {
|
|
36769
36740
|
return !!getState(job).inControlBlock;
|
|
36770
36741
|
}
|
|
@@ -36833,6 +36804,7 @@ ${svg}
|
|
|
36833
36804
|
|
|
36834
36805
|
function skipCommand(cmdName, job) {
|
|
36835
36806
|
// allow all control commands to run
|
|
36807
|
+
if (jobIsStopped(job)) return true;
|
|
36836
36808
|
if (isControlFlowCommand(cmdName)) return false;
|
|
36837
36809
|
return inControlBlock(job) && !inActiveBranch(job);
|
|
36838
36810
|
}
|
|
@@ -38761,7 +38733,7 @@ ${svg}
|
|
|
38761
38733
|
stop('Expected a non-negative interval parameter');
|
|
38762
38734
|
}
|
|
38763
38735
|
if (opts.radius > 0 === false) {
|
|
38764
|
-
stop('Expected a non-negative radius parameter');
|
|
38736
|
+
// stop('Expected a non-negative radius parameter');
|
|
38765
38737
|
}
|
|
38766
38738
|
// var bbox = getLayerBounds(pointLyr).toArray();
|
|
38767
38739
|
// Use target dataset, so grids are aligned between layers
|
|
@@ -38789,27 +38761,24 @@ ${svg}
|
|
|
38789
38761
|
};
|
|
38790
38762
|
|
|
38791
38763
|
function getPolygonDataset(pointLyr, gridBBox, opts) {
|
|
38792
|
-
var interval = opts.interval;
|
|
38793
38764
|
var points = getPointsInLayer(pointLyr);
|
|
38794
|
-
var
|
|
38795
|
-
var
|
|
38796
|
-
var
|
|
38765
|
+
var cellSize = opts.interval;
|
|
38766
|
+
var grid = getGridData(gridBBox, cellSize, opts);
|
|
38767
|
+
var pointCircleRadius = getPointCircleRadius(opts);
|
|
38768
|
+
var findPointIdsByCellId = getPointIndex(points, grid, pointCircleRadius);
|
|
38797
38769
|
var geojson = {
|
|
38798
38770
|
type: 'FeatureCollection',
|
|
38799
38771
|
features: []
|
|
38800
38772
|
};
|
|
38801
|
-
var calc = null;
|
|
38802
|
-
var
|
|
38803
|
-
if (opts.calc) {
|
|
38804
|
-
calc = getJoinCalc(pointLyr.data, opts.calc);
|
|
38805
|
-
}
|
|
38773
|
+
var calc = opts.calc ? getJoinCalc(pointLyr.data, opts.calc) : null;
|
|
38774
|
+
var candidateIds, weights, center, weight, d;
|
|
38806
38775
|
|
|
38807
|
-
for (var i=0; i<n; i++) {
|
|
38808
|
-
|
|
38809
|
-
if (!
|
|
38776
|
+
for (var i=0, n=grid.cells(); i<n; i++) {
|
|
38777
|
+
candidateIds = findPointIdsByCellId(i);
|
|
38778
|
+
if (!candidateIds.length) continue;
|
|
38810
38779
|
center = grid.idxToPoint(i);
|
|
38811
|
-
|
|
38812
|
-
|
|
38780
|
+
weights = calcWeights(center, cellSize, points, candidateIds, pointCircleRadius);
|
|
38781
|
+
d = calcCellProperties(candidateIds, weights, calc);
|
|
38813
38782
|
if (d.weight > 0.05 === false) continue;
|
|
38814
38783
|
d.id = i;
|
|
38815
38784
|
geojson.features.push({
|
|
@@ -38818,44 +38787,43 @@ ${svg}
|
|
|
38818
38787
|
geometry: makeCellPolygon(i, grid, opts)
|
|
38819
38788
|
});
|
|
38820
38789
|
}
|
|
38821
|
-
|
|
38822
|
-
return dataset;
|
|
38790
|
+
return importGeoJSON(geojson, {});
|
|
38823
38791
|
}
|
|
38824
38792
|
|
|
38825
|
-
function
|
|
38826
|
-
|
|
38827
|
-
|
|
38828
|
-
|
|
38829
|
-
|
|
38830
|
-
|
|
38831
|
-
var
|
|
38832
|
-
var
|
|
38833
|
-
var
|
|
38834
|
-
|
|
38835
|
-
|
|
38836
|
-
|
|
38837
|
-
|
|
38838
|
-
|
|
38839
|
-
|
|
38840
|
-
|
|
38793
|
+
function getPointCircleRadius(opts) {
|
|
38794
|
+
var cellRadius = opts.interval * Math.sqrt(1 / Math.PI);
|
|
38795
|
+
return opts.radius > 0 ? opts.radius : cellRadius;
|
|
38796
|
+
}
|
|
38797
|
+
|
|
38798
|
+
function calcCellProperties(pointIds, weights, calc) {
|
|
38799
|
+
var hitIds = [];
|
|
38800
|
+
var weight = 0;
|
|
38801
|
+
var partial;
|
|
38802
|
+
var d;
|
|
38803
|
+
for (var i=0; i<pointIds.length; i++) {
|
|
38804
|
+
partial = weights[i];
|
|
38805
|
+
if (partial > 0 === false) continue;
|
|
38806
|
+
weight += partial;
|
|
38807
|
+
hitIds.push(pointIds[i]);
|
|
38808
|
+
}
|
|
38809
|
+
d = {weight: weight};
|
|
38841
38810
|
if (calc) {
|
|
38842
|
-
calc(
|
|
38811
|
+
calc(hitIds, d);
|
|
38843
38812
|
}
|
|
38844
38813
|
return d;
|
|
38845
38814
|
}
|
|
38846
38815
|
|
|
38847
|
-
|
|
38848
|
-
|
|
38849
|
-
|
|
38850
|
-
|
|
38851
|
-
|
|
38852
|
-
|
|
38853
|
-
|
|
38854
|
-
|
|
38855
|
-
|
|
38856
|
-
|
|
38857
|
-
|
|
38858
|
-
// }
|
|
38816
|
+
function calcWeights(cellCenter, cellSize, points, pointIds, pointRadius) {
|
|
38817
|
+
var weights = [];
|
|
38818
|
+
var cellRadius = cellSize * Math.sqrt(1 / Math.PI); // radius of circle with same area as cell
|
|
38819
|
+
var cellArea = cellSize * cellSize;
|
|
38820
|
+
var w;
|
|
38821
|
+
for (var i=0; i<pointIds.length; i++) {
|
|
38822
|
+
w = twoCircleIntersection(cellCenter, cellRadius, points[pointIds[i]], pointRadius) / cellArea;
|
|
38823
|
+
weights.push(w);
|
|
38824
|
+
}
|
|
38825
|
+
return weights;
|
|
38826
|
+
}
|
|
38859
38827
|
|
|
38860
38828
|
// Source: https://diego.assencio.com/?index=8d6ca3d82151bad815f78addf9b5c1c6
|
|
38861
38829
|
function twoCircleIntersection(c1, r1, c2, r2) {
|
|
@@ -38910,10 +38878,19 @@ ${svg}
|
|
|
38910
38878
|
return function(i) {
|
|
38911
38879
|
if (!gridIndex.hasId(i)) return empty;
|
|
38912
38880
|
var bbox = grid.idxToBBox(i);
|
|
38913
|
-
|
|
38881
|
+
var indices = bboxIndex.search.apply(bboxIndex, bbox);
|
|
38882
|
+
return indices;
|
|
38914
38883
|
};
|
|
38915
38884
|
}
|
|
38916
38885
|
|
|
38886
|
+
function getPointsByIndex(points, indices) {
|
|
38887
|
+
var arr = [];
|
|
38888
|
+
for (var i=0; i<indices.length; i++) {
|
|
38889
|
+
arr.push(points[indices[i]]);
|
|
38890
|
+
}
|
|
38891
|
+
return arr;
|
|
38892
|
+
}
|
|
38893
|
+
|
|
38917
38894
|
function addPointToGridIndex(p, index, grid) {
|
|
38918
38895
|
var i = grid.pointToIdx(p);
|
|
38919
38896
|
var c = grid.idxToCol(i);
|
|
@@ -38939,23 +38916,52 @@ ${svg}
|
|
|
38939
38916
|
return [p[0] - radius, p[1] - radius, p[0] + radius, p[1] + radius];
|
|
38940
38917
|
}
|
|
38941
38918
|
|
|
38942
|
-
|
|
38943
|
-
|
|
38944
|
-
|
|
38945
|
-
|
|
38946
|
-
|
|
38947
|
-
|
|
38948
|
-
|
|
38949
|
-
|
|
38950
|
-
function
|
|
38951
|
-
var
|
|
38952
|
-
var
|
|
38953
|
-
var
|
|
38954
|
-
|
|
38955
|
-
|
|
38956
|
-
|
|
38957
|
-
|
|
38958
|
-
var
|
|
38919
|
+
// grid boundaries includes the origin
|
|
38920
|
+
// (this way, grids calculated from different sets of points will all align)
|
|
38921
|
+
function getAlignedRange(minCoord, maxCoord, interval) {
|
|
38922
|
+
var idx = Math.floor(minCoord / interval) - 1;
|
|
38923
|
+
var idx2 = Math.ceil(maxCoord / interval) + 1;
|
|
38924
|
+
return [idx * interval, idx2 * interval];
|
|
38925
|
+
}
|
|
38926
|
+
|
|
38927
|
+
function getCenteredRange(minCoord, maxCoord, interval) {
|
|
38928
|
+
var w = maxCoord - minCoord;
|
|
38929
|
+
var w2 = Math.ceil(w / interval) * interval;
|
|
38930
|
+
var pad = (w2 - w) / 2 + interval;
|
|
38931
|
+
return [minCoord - pad, maxCoord + pad];
|
|
38932
|
+
}
|
|
38933
|
+
|
|
38934
|
+
function getAlignedGridBounds(bbox, interval) {
|
|
38935
|
+
var xx = getAlignedRange(bbox[0], bbox[2], interval);
|
|
38936
|
+
var yy = getAlignedRange(bbox[1], bbox[3], interval);
|
|
38937
|
+
return [xx[0], yy[0], xx[1], yy[1]];
|
|
38938
|
+
}
|
|
38939
|
+
|
|
38940
|
+
function getCenteredGridBounds(bbox, interval) {
|
|
38941
|
+
var xx = getCenteredRange(bbox[0], bbox[2], interval);
|
|
38942
|
+
var yy = getCenteredRange(bbox[1], bbox[3], interval);
|
|
38943
|
+
return [xx[0], yy[0], xx[1], yy[1]];
|
|
38944
|
+
}
|
|
38945
|
+
|
|
38946
|
+
// TODO: Use this function for other grid-based commands
|
|
38947
|
+
function getGridData(bbox, interval, opts) {
|
|
38948
|
+
var extent = opts && opts.aligned ?
|
|
38949
|
+
getAlignedGridBounds(bbox, interval) :
|
|
38950
|
+
getCenteredGridBounds(bbox, interval);
|
|
38951
|
+
var xmin = extent[0];
|
|
38952
|
+
var ymin = extent[1];
|
|
38953
|
+
var w = extent[2] - xmin;
|
|
38954
|
+
var h = extent[3] - ymin;
|
|
38955
|
+
var cols = Math.round(w / interval);
|
|
38956
|
+
var rows = Math.round(h / interval);
|
|
38957
|
+
// var xmin = bbox[0] - interval;
|
|
38958
|
+
// var ymin = bbox[1] - interval;
|
|
38959
|
+
// var xmax = bbox[2] + interval;
|
|
38960
|
+
// var ymax = bbox[3] + interval;
|
|
38961
|
+
// var w = xmax - xmin;
|
|
38962
|
+
// var h = ymax - ymin;
|
|
38963
|
+
// var cols = Math.ceil(w / interval);
|
|
38964
|
+
// var rows = Math.ceil(h / interval);
|
|
38959
38965
|
function size() {
|
|
38960
38966
|
return [cols, rows];
|
|
38961
38967
|
}
|
|
@@ -40493,6 +40499,10 @@ ${svg}
|
|
|
40493
40499
|
getSplitNameFunction: getSplitNameFunction
|
|
40494
40500
|
});
|
|
40495
40501
|
|
|
40502
|
+
cmd.stop = function(job) {
|
|
40503
|
+
stopJob(job);
|
|
40504
|
+
};
|
|
40505
|
+
|
|
40496
40506
|
cmd.svgStyle = function(lyr, dataset, opts) {
|
|
40497
40507
|
var filter;
|
|
40498
40508
|
if (!lyr.data) {
|
|
@@ -40638,10 +40648,10 @@ ${svg}
|
|
|
40638
40648
|
dy = stemLen * Math.cos(theta / 2);
|
|
40639
40649
|
|
|
40640
40650
|
if (stickArrow) {
|
|
40641
|
-
stem = getCurvedStemCoords(-ax, -ay, dx, dy
|
|
40651
|
+
stem = getCurvedStemCoords(-ax, -ay, dx, dy);
|
|
40642
40652
|
} else {
|
|
40643
|
-
var leftStem = getCurvedStemCoords(-ax, -ay, -stemDx + dx, dy
|
|
40644
|
-
var rightStem = getCurvedStemCoords(ax, ay, stemDx + dx, dy
|
|
40653
|
+
var leftStem = getCurvedStemCoords(-ax, -ay, -stemDx + dx, dy);
|
|
40654
|
+
var rightStem = getCurvedStemCoords(ax, ay, stemDx + dx, dy);
|
|
40645
40655
|
stem = leftStem.concat(rightStem.reverse());
|
|
40646
40656
|
}
|
|
40647
40657
|
|
|
@@ -40685,10 +40695,10 @@ ${svg}
|
|
|
40685
40695
|
return coords;
|
|
40686
40696
|
}
|
|
40687
40697
|
|
|
40688
|
-
function calcStraightArrowCoords(stemLen, headLen, stemDx, headDx, baseDx) {
|
|
40689
|
-
|
|
40690
|
-
|
|
40691
|
-
}
|
|
40698
|
+
// function calcStraightArrowCoords(stemLen, headLen, stemDx, headDx, baseDx) {
|
|
40699
|
+
// return [[baseDx, 0], [stemDx, stemLen], [headDx, stemLen], [0, stemLen + headLen],
|
|
40700
|
+
// [-headDx, stemLen], [-stemDx, stemLen], [-baseDx, 0], [baseDx, 0]];
|
|
40701
|
+
// }
|
|
40692
40702
|
|
|
40693
40703
|
function calcArrowSize(d, stickArrow) {
|
|
40694
40704
|
// don't display arrows with negative length
|
|
@@ -40755,7 +40765,7 @@ ${svg}
|
|
|
40755
40765
|
|
|
40756
40766
|
// ax, ay: point on the base
|
|
40757
40767
|
// bx, by: point on the stem
|
|
40758
|
-
function getCurvedStemCoords(ax, ay, bx, by
|
|
40768
|
+
function getCurvedStemCoords(ax, ay, bx, by) {
|
|
40759
40769
|
// case: curved side intrudes into head (because stem is too short)
|
|
40760
40770
|
if (ay > by) {
|
|
40761
40771
|
return [[ax * by / ay, by]];
|
|
@@ -41478,7 +41488,7 @@ ${svg}
|
|
|
41478
41488
|
return name == 'graticule' || name == 'i' || name == 'help' ||
|
|
41479
41489
|
name == 'point-grid' || name == 'shape' || name == 'rectangle' ||
|
|
41480
41490
|
name == 'include' || name == 'print' || name == 'comment' || name == 'if' || name == 'elif' ||
|
|
41481
|
-
name == 'else' || name == 'endif';
|
|
41491
|
+
name == 'else' || name == 'endif' || name == 'stop';
|
|
41482
41492
|
}
|
|
41483
41493
|
|
|
41484
41494
|
function runCommand(command, job, cb) {
|
|
@@ -41808,6 +41818,9 @@ ${svg}
|
|
|
41808
41818
|
} else if (name == 'split') {
|
|
41809
41819
|
outputLayers = applyCommandToEachLayer(cmd.splitLayer, targetLayers, opts.expression, opts);
|
|
41810
41820
|
|
|
41821
|
+
} else if (name == 'stop') {
|
|
41822
|
+
cmd.stop(job);
|
|
41823
|
+
|
|
41811
41824
|
} else if (name == 'split-on-grid') {
|
|
41812
41825
|
outputLayers = applyCommandToEachLayer(cmd.splitLayerOnGrid, targetLayers, arcs, opts);
|
|
41813
41826
|
|
|
@@ -42573,7 +42586,6 @@ ${svg}
|
|
|
42573
42586
|
// so they can be run by tests and by the GUI.
|
|
42574
42587
|
// TODO: rewrite tests to import functions directly from modules,
|
|
42575
42588
|
// export only functions called by the GUI.
|
|
42576
|
-
|
|
42577
42589
|
var internal = {};
|
|
42578
42590
|
|
|
42579
42591
|
internal.svg = Object.assign({}, SvgStringify, SvgPathUtils, GeojsonToSvg, SvgLabels, SvgSymbols);
|