mapshaper 0.5.118 → 0.6.3
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/bin/mapshaper +1 -1
- package/mapshaper.js +1979 -290
- package/package.json +22 -14
- package/www/mapshaper-gui.js +66 -55
- package/www/mapshaper.js +1979 -290
- package/www/modules.js +688 -1836
- package/www/page.css +3 -7
- package/CHANGELOG.md +0 -1395
- package/www/assets/iosevka-light.woff +0 -0
- package/www/assets/iosevka-regular.woff +0 -0
- package/www/assets/iosevka-regular.woff2 +0 -0
- package/www/assets/iosevka-slab-light.woff +0 -0
- package/www/assets/iosevka-slab-light.woff2 +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mapshaper",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"description": "A tool for editing vector datasets for mapping and GIS.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"shapefile",
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"cartography",
|
|
10
10
|
"simplification",
|
|
11
11
|
"topology",
|
|
12
|
+
"csv",
|
|
12
13
|
"gis"
|
|
13
14
|
],
|
|
14
15
|
"author": "Matthew Bloch <masiyou@gmail.com>",
|
|
@@ -19,16 +20,15 @@
|
|
|
19
20
|
"url": "https://github.com/mbloch/mapshaper"
|
|
20
21
|
},
|
|
21
22
|
"engines": {
|
|
22
|
-
"node": ">=
|
|
23
|
+
"node": ">=12.0.0"
|
|
23
24
|
},
|
|
24
25
|
"scripts": {
|
|
25
|
-
"test": "mocha
|
|
26
|
+
"test": "mocha test",
|
|
26
27
|
"build": "rollup --config",
|
|
27
|
-
|
|
28
|
+
"lint": "eslint --ext mjs src/",
|
|
29
|
+
"prepublishOnly": "npm lint; npm test; ./pre-publish",
|
|
28
30
|
"postpublish": "./release_web_ui; ./release_github_version",
|
|
29
|
-
"
|
|
30
|
-
"browserify": "browserify -r sync-request -r mproj -r buffer -r iconv-lite -r fs -r flatbush -r rw -r path -r d3-scale-chromatic -r d3-color -r d3-interpolate -r kdbush -r @tmcw/togeojson -o www/modules.js",
|
|
31
|
-
"watch": "rollup --config --watch",
|
|
31
|
+
"browserify": "browserify -r sync-request -r mproj -r buffer -r iconv-lite -r fs -r flatbush -r rw -r path -r kdbush -r @tmcw/togeojson -o www/modules.js",
|
|
32
32
|
"dev": "rollup --config --watch"
|
|
33
33
|
},
|
|
34
34
|
"main": "./mapshaper.js",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"/bin/**",
|
|
37
37
|
"/www/**",
|
|
38
38
|
"!/www/basemap.js",
|
|
39
|
-
"!/www/nacis
|
|
39
|
+
"!/www/nacis/**",
|
|
40
40
|
"/mapshaper.js",
|
|
41
41
|
"!.DS_Store"
|
|
42
42
|
],
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"delaunator": "^5.0.0",
|
|
51
51
|
"flatbush": "^3.2.1",
|
|
52
52
|
"geokdbush": "^1.1.0",
|
|
53
|
-
"iconv-lite": "0.
|
|
53
|
+
"iconv-lite": "^0.6.3",
|
|
54
54
|
"kdbush": "^3.0.0",
|
|
55
55
|
"mproj": "0.0.35",
|
|
56
56
|
"opn": "^5.3.0",
|
|
@@ -59,16 +59,24 @@
|
|
|
59
59
|
"tinyqueue": "^2.0.3"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@rollup/plugin-node-resolve": "^13.0
|
|
62
|
+
"@rollup/plugin-node-resolve": "^13.3.0",
|
|
63
63
|
"browserify": "^17.0.0",
|
|
64
64
|
"csv-spectrum": "^1.0.0",
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"rollup": "^2.60.0",
|
|
65
|
+
"eslint": "^8.16.0",
|
|
66
|
+
"mocha": "^10.0.0",
|
|
67
|
+
"rollup": "^2.73.0",
|
|
69
68
|
"shell-quote": "^1.6.1",
|
|
70
69
|
"underscore": "^1.13.1"
|
|
71
70
|
},
|
|
71
|
+
"mocha": {
|
|
72
|
+
"reporter": "dot",
|
|
73
|
+
"node-option": [
|
|
74
|
+
"experimental-specifier-resolution=node"
|
|
75
|
+
],
|
|
76
|
+
"check-leaks": true,
|
|
77
|
+
"parallel": true,
|
|
78
|
+
"jobs": 4
|
|
79
|
+
},
|
|
72
80
|
"bin": {
|
|
73
81
|
"mapshaper": "./bin/mapshaper",
|
|
74
82
|
"mapshaper-gui": "./bin/mapshaper-gui",
|
package/www/mapshaper-gui.js
CHANGED
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
get findValueByPct () { return findValueByPct; },
|
|
79
79
|
get findValueByRank () { return findValueByRank; },
|
|
80
80
|
get findMedian () { return findMedian; },
|
|
81
|
+
get findQuantile () { return findQuantile; },
|
|
81
82
|
get mean () { return mean; },
|
|
82
83
|
get format () { return format; },
|
|
83
84
|
get formatter () { return formatter; },
|
|
@@ -1682,7 +1683,6 @@
|
|
|
1682
1683
|
}
|
|
1683
1684
|
|
|
1684
1685
|
function Slider(ref, opts) {
|
|
1685
|
-
var _el = El(ref);
|
|
1686
1686
|
var _self = this;
|
|
1687
1687
|
var defaults = {
|
|
1688
1688
|
space: 7
|
|
@@ -1713,7 +1713,7 @@
|
|
|
1713
1713
|
_handle = El(ref);
|
|
1714
1714
|
draggable(_handle)
|
|
1715
1715
|
.on('drag', function(e) {
|
|
1716
|
-
setHandlePos(startX + e.dx
|
|
1716
|
+
setHandlePos(startX + e.dx);
|
|
1717
1717
|
})
|
|
1718
1718
|
.on('dragstart', function(e) {
|
|
1719
1719
|
startX = position();
|
|
@@ -1739,7 +1739,7 @@
|
|
|
1739
1739
|
return _pct;
|
|
1740
1740
|
};
|
|
1741
1741
|
|
|
1742
|
-
function setHandlePos(x
|
|
1742
|
+
function setHandlePos(x) {
|
|
1743
1743
|
x = utils$1.clamp(x, 0, size());
|
|
1744
1744
|
var pct = x / size();
|
|
1745
1745
|
if (pct != _pct) {
|
|
@@ -2261,7 +2261,7 @@
|
|
|
2261
2261
|
menu.hide();
|
|
2262
2262
|
setTimeout(function() {
|
|
2263
2263
|
var opts = getSimplifyOptions();
|
|
2264
|
-
mapshaper.simplify(dataset, opts);
|
|
2264
|
+
mapshaper.cmd.simplify(dataset, opts);
|
|
2265
2265
|
gui.session.simplificationApplied(getSimplifyOptionsAsString());
|
|
2266
2266
|
updateZ(gui.map.getActiveLayer()); // question: does this update all display layers?
|
|
2267
2267
|
model.updated({
|
|
@@ -3122,7 +3122,7 @@
|
|
|
3122
3122
|
|
|
3123
3123
|
function cleanLayerName(raw) {
|
|
3124
3124
|
return raw.replace(/[\n\t/\\]/g, '')
|
|
3125
|
-
.replace(/^[
|
|
3125
|
+
.replace(/^[.\s]+/, '').replace(/[.\s]+$/, '');
|
|
3126
3126
|
}
|
|
3127
3127
|
|
|
3128
3128
|
function updateLayerStackOrder(layers) {
|
|
@@ -3856,8 +3856,6 @@
|
|
|
3856
3856
|
}
|
|
3857
3857
|
}
|
|
3858
3858
|
|
|
3859
|
-
var snapVerticesToPoint = internal.snapVerticesToPoint;
|
|
3860
|
-
var cloneShape = internal.cloneShape;
|
|
3861
3859
|
var copyRecord = internal.copyRecord;
|
|
3862
3860
|
|
|
3863
3861
|
function Undo(gui) {
|
|
@@ -4412,7 +4410,8 @@
|
|
|
4412
4410
|
return self;
|
|
4413
4411
|
}
|
|
4414
4412
|
|
|
4415
|
-
|
|
4413
|
+
// Fall back to browserify's Buffer polyfill
|
|
4414
|
+
var B = typeof Buffer != 'undefined' ? Buffer : require('buffer').Buffer;
|
|
4416
4415
|
|
|
4417
4416
|
// This module provides a way for multiple jobs to run together asynchronously
|
|
4418
4417
|
// while keeping job-level context variables (like "defs") separate.
|
|
@@ -4740,7 +4739,7 @@
|
|
|
4740
4739
|
'/': '/'
|
|
4741
4740
|
};
|
|
4742
4741
|
function htmlEscape(s) {
|
|
4743
|
-
return String(s).replace(/[&<>"'
|
|
4742
|
+
return String(s).replace(/[&<>"'/]/g, function(s) {
|
|
4744
4743
|
return entityMap[s];
|
|
4745
4744
|
});
|
|
4746
4745
|
}
|
|
@@ -5314,18 +5313,24 @@
|
|
|
5314
5313
|
return arr[k];
|
|
5315
5314
|
}
|
|
5316
5315
|
|
|
5317
|
-
//
|
|
5318
|
-
//
|
|
5319
5316
|
function findMedian(arr) {
|
|
5320
|
-
|
|
5321
|
-
rank = Math.floor(n / 2) + 1,
|
|
5322
|
-
median = findValueByRank(arr, rank);
|
|
5323
|
-
if ((n & 1) == 0) {
|
|
5324
|
-
median = (median + findValueByRank(arr, rank - 1)) / 2;
|
|
5325
|
-
}
|
|
5326
|
-
return median;
|
|
5317
|
+
return findQuantile(arr, 0.5);
|
|
5327
5318
|
}
|
|
5328
5319
|
|
|
5320
|
+
function findQuantile(arr, k) {
|
|
5321
|
+
var n = arr.length,
|
|
5322
|
+
i1 = Math.floor((n - 1) * k),
|
|
5323
|
+
i2 = Math.ceil((n - 1) * k);
|
|
5324
|
+
if (i1 < 0 || i2 >= n) return NaN;
|
|
5325
|
+
var v1 = findValueByRank(arr, i1 + 1);
|
|
5326
|
+
if (i1 == i2) return v1;
|
|
5327
|
+
var v2 = findValueByRank(arr, i2 + 1);
|
|
5328
|
+
// use linear interpolation
|
|
5329
|
+
var w1 = i2 / (n - 1) - k;
|
|
5330
|
+
var w2 = k - i1 / (n - 1);
|
|
5331
|
+
var v = (v1 * w1 + v2 * w2) * (n - 1);
|
|
5332
|
+
return v;
|
|
5333
|
+
}
|
|
5329
5334
|
|
|
5330
5335
|
function mean(arr) {
|
|
5331
5336
|
var count = 0,
|
|
@@ -5383,8 +5388,8 @@
|
|
|
5383
5388
|
var type = matches[4];
|
|
5384
5389
|
var isString = type == 's',
|
|
5385
5390
|
isHex = type == 'x' || type == 'X',
|
|
5386
|
-
isInt = type == 'd' || type == 'i',
|
|
5387
|
-
isFloat = type == 'f',
|
|
5391
|
+
// isInt = type == 'd' || type == 'i',
|
|
5392
|
+
// isFloat = type == 'f',
|
|
5388
5393
|
isNumber = !isString;
|
|
5389
5394
|
|
|
5390
5395
|
var sign = "",
|
|
@@ -5443,7 +5448,7 @@
|
|
|
5443
5448
|
|
|
5444
5449
|
// Get a function for interpolating formatted values into a string.
|
|
5445
5450
|
function formatter(fmt) {
|
|
5446
|
-
var codeRxp = /%([
|
|
5451
|
+
var codeRxp = /%([',+0]*)([1-9]?)((?:\.[1-9])?)([sdifxX%])/g;
|
|
5447
5452
|
var literals = [],
|
|
5448
5453
|
formatCodes = [],
|
|
5449
5454
|
startIdx = 0,
|
|
@@ -5487,10 +5492,10 @@
|
|
|
5487
5492
|
|
|
5488
5493
|
function createBuffer(arg, arg2) {
|
|
5489
5494
|
if (isInteger(arg)) {
|
|
5490
|
-
return
|
|
5495
|
+
return B.allocUnsafe ? B.allocUnsafe(arg) : new B(arg);
|
|
5491
5496
|
} else {
|
|
5492
5497
|
// check allocUnsafe to make sure Buffer.from() will accept strings (it didn't before Node v5.10)
|
|
5493
|
-
return
|
|
5498
|
+
return B.from && B.allocUnsafe ? B.from(arg, arg2) : new B(arg, arg2);
|
|
5494
5499
|
}
|
|
5495
5500
|
}
|
|
5496
5501
|
|
|
@@ -5843,27 +5848,21 @@
|
|
|
5843
5848
|
|
|
5844
5849
|
function pointTest(x, y) {
|
|
5845
5850
|
var bullseyeDist = 2, // hit all points w/in 2 px
|
|
5846
|
-
tinyDist = 0.5,
|
|
5847
|
-
toPx = ext.getTransform().mx,
|
|
5848
|
-
hits = [],
|
|
5849
5851
|
hitThreshold = 25,
|
|
5850
|
-
|
|
5852
|
+
toPx = ext.getTransform().mx,
|
|
5853
|
+
hits = [];
|
|
5851
5854
|
|
|
5855
|
+
// inlining forEachPoint() does not not appreciably speed this up
|
|
5852
5856
|
internal.forEachPoint(displayLayer.layer.shapes, function(p, id) {
|
|
5853
5857
|
var dist = geom.distance2D(x, y, p[0], p[1]) * toPx;
|
|
5854
5858
|
if (dist > hitThreshold) return;
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
hits = [id];
|
|
5859
|
-
hitThreshold = Math.max(bullseyeDist, dist + tinyDist);
|
|
5860
|
-
newThreshold = dist < bullseyeDist ? -1 : dist - tinyDist;
|
|
5861
|
-
} else {
|
|
5862
|
-
// add to hits if inside bullseye or is same dist as previous hit
|
|
5863
|
-
hits.push(id);
|
|
5859
|
+
if (dist < hitThreshold && hitThreshold > bullseyeDist) {
|
|
5860
|
+
hits = [];
|
|
5861
|
+
hitThreshold = Math.max(bullseyeDist, dist);
|
|
5864
5862
|
}
|
|
5863
|
+
hits.push(id);
|
|
5865
5864
|
});
|
|
5866
|
-
// TODO: add info on what part of a shape gets hit
|
|
5865
|
+
// TODO: add info on what part of a shape gets hit?
|
|
5867
5866
|
return {
|
|
5868
5867
|
ids: utils$1.uniq(hits) // multipoint features can register multiple hits
|
|
5869
5868
|
};
|
|
@@ -8272,20 +8271,25 @@
|
|
|
8272
8271
|
_frame;
|
|
8273
8272
|
|
|
8274
8273
|
_position.on('resize', function(e) {
|
|
8275
|
-
if (
|
|
8274
|
+
if (ready()) {
|
|
8276
8275
|
onChange({resize: true});
|
|
8277
8276
|
}
|
|
8278
8277
|
});
|
|
8279
8278
|
|
|
8279
|
+
function ready() { return !!_contentBounds; }
|
|
8280
|
+
|
|
8280
8281
|
this.reset = function() {
|
|
8282
|
+
if (!ready()) return;
|
|
8281
8283
|
recenter(_contentBounds.centerX(), _contentBounds.centerY(), 1, {reset: true});
|
|
8282
8284
|
};
|
|
8283
8285
|
|
|
8284
8286
|
this.home = function() {
|
|
8287
|
+
if (!ready()) return;
|
|
8285
8288
|
recenter(_contentBounds.centerX(), _contentBounds.centerY(), 1);
|
|
8286
8289
|
};
|
|
8287
8290
|
|
|
8288
8291
|
this.pan = function(xpix, ypix) {
|
|
8292
|
+
if (!ready()) return;
|
|
8289
8293
|
var t = this.getTransform();
|
|
8290
8294
|
recenter(_cx - xpix / t.mx, _cy - ypix / t.my);
|
|
8291
8295
|
};
|
|
@@ -8293,6 +8297,7 @@
|
|
|
8293
8297
|
// Zoom to @w (width of the map viewport in coordinates)
|
|
8294
8298
|
// @xpct, @ypct: optional focus, [0-1]...
|
|
8295
8299
|
this.zoomToExtent = function(w, xpct, ypct) {
|
|
8300
|
+
if (!ready()) return;
|
|
8296
8301
|
if (arguments.length < 3) {
|
|
8297
8302
|
xpct = 0.5;
|
|
8298
8303
|
ypct = 0.5;
|
|
@@ -8312,6 +8317,7 @@
|
|
|
8312
8317
|
};
|
|
8313
8318
|
|
|
8314
8319
|
this.zoomByPct = function(pct, xpct, ypct) {
|
|
8320
|
+
if (!ready()) return;
|
|
8315
8321
|
this.zoomToExtent(this.getBounds().width() / pct, xpct, ypct);
|
|
8316
8322
|
};
|
|
8317
8323
|
|
|
@@ -8753,7 +8759,7 @@
|
|
|
8753
8759
|
bx = t.bx,
|
|
8754
8760
|
by = t.by;
|
|
8755
8761
|
if (size === 0) return;
|
|
8756
|
-
if (size <=
|
|
8762
|
+
if (size <= 6 && !styler) {
|
|
8757
8763
|
// optimized drawing of many small same-colored dots
|
|
8758
8764
|
_self.drawSquareDotsFaster(shapes, color, size, t);
|
|
8759
8765
|
return;
|
|
@@ -8810,14 +8816,12 @@
|
|
|
8810
8816
|
// pixels: Uint32Array of pixel colors
|
|
8811
8817
|
// w, h: Size of canvas
|
|
8812
8818
|
function drawSquareFaster(x, y, rgba, size, pixels, w, h) {
|
|
8813
|
-
var xmin = (x - size * 0.5) | 0;
|
|
8814
|
-
var ymin = (y - size * 0.5) | 0;
|
|
8815
|
-
var xmax = xmin + size - 1;
|
|
8816
|
-
var ymax = ymin + size - 1;
|
|
8817
|
-
var
|
|
8818
|
-
|
|
8819
|
-
if (c < 0 || c >= w) continue;
|
|
8820
|
-
for (r = ymin; r <= ymax && r >= 0 && r < h; r++) {
|
|
8819
|
+
var xmin = x < 0 ? 0 : (x - size * 0.5) | 0;
|
|
8820
|
+
var ymin = y < 0 ? 0 : (y - size * 0.5) | 0;
|
|
8821
|
+
var xmax = x >= w-1 ? w-1 : xmin + size - 1;
|
|
8822
|
+
var ymax = y >= h-1 ? h-1 : ymin + size - 1;
|
|
8823
|
+
for (var r = ymin; r <= ymax; r++) {
|
|
8824
|
+
for (var c = xmin; c <= xmax; c++) {
|
|
8821
8825
|
pixels[r * w + c] = rgba;
|
|
8822
8826
|
}
|
|
8823
8827
|
}
|
|
@@ -8904,24 +8908,25 @@
|
|
|
8904
8908
|
return s;
|
|
8905
8909
|
}
|
|
8906
8910
|
|
|
8907
|
-
|
|
8908
8911
|
function getDotScale(ext) {
|
|
8909
8912
|
var smallSide = Math.min(ext.width(), ext.height());
|
|
8913
|
+
var mapScale = ext.scale();
|
|
8910
8914
|
// reduce size on smaller screens
|
|
8911
8915
|
var j = smallSide < 200 && 0.5 || smallSide < 400 && 0.75 || 1;
|
|
8916
|
+
// grow dots as map zooms in
|
|
8912
8917
|
var k = 1;
|
|
8913
|
-
var mapScale = ext.scale();
|
|
8914
8918
|
if (mapScale < 0.5) {
|
|
8915
8919
|
k = Math.pow(mapScale + 0.5, 0.35);
|
|
8916
|
-
}
|
|
8917
|
-
if (mapScale > 1) {
|
|
8920
|
+
} else if (mapScale > 1) {
|
|
8918
8921
|
// scale faster at first, so small dots in large datasets
|
|
8919
8922
|
// become easily visible and clickable after zooming in a bit
|
|
8920
8923
|
k *= Math.pow(Math.min(mapScale, 10), 0.3);
|
|
8921
8924
|
k *= Math.pow(mapScale, 0.1);
|
|
8922
8925
|
}
|
|
8923
|
-
|
|
8924
|
-
|
|
8926
|
+
// grow pixels more slowly on retina displays (to reduce number of pixels to
|
|
8927
|
+
// draw for large point datasets when slightly zoomed in)
|
|
8928
|
+
var l = Math.pow(GUI.getPixelRatio(), 0.8);
|
|
8929
|
+
return j * k * l;
|
|
8925
8930
|
}
|
|
8926
8931
|
|
|
8927
8932
|
function getScaledTransform(ext) {
|
|
@@ -9494,7 +9499,7 @@
|
|
|
9494
9499
|
|
|
9495
9500
|
// Only generate low-detail arcs for larger datasets
|
|
9496
9501
|
if (size > 5e5) {
|
|
9497
|
-
if (
|
|
9502
|
+
if (unfilteredArcs.getVertexData().zz) {
|
|
9498
9503
|
// Use precalculated simplification data for vertex filtering, if available
|
|
9499
9504
|
filteredArcs = initFilteredArcs(unfilteredArcs);
|
|
9500
9505
|
filteredSegLen = internal.getAvgSegment(filteredArcs);
|
|
@@ -9860,7 +9865,13 @@
|
|
|
9860
9865
|
var warning;
|
|
9861
9866
|
|
|
9862
9867
|
if (!dataCRS || !displayCRS || !crsIsUsable(displayCRS) || !crsIsUsable(dataCRS)) {
|
|
9863
|
-
warning = '
|
|
9868
|
+
warning = 'This data is incompatible with the basemaps.';
|
|
9869
|
+
if (!internal.layerHasGeometry(activeLyr.layer)) {
|
|
9870
|
+
warning += ' Reason: layer is missing geographic data';
|
|
9871
|
+
} else if (!dataCRS) {
|
|
9872
|
+
warning += ' Reason: unknown projection.';
|
|
9873
|
+
}
|
|
9874
|
+
|
|
9864
9875
|
basemapWarning.html(warning).show();
|
|
9865
9876
|
basemapNote.hide();
|
|
9866
9877
|
} else {
|