mapshaper 0.6.29 → 0.6.31
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/mapshaper.js +25 -8
- package/package.json +2 -2
- package/www/index.html +9 -8
- package/www/mapshaper-gui.js +22 -8
- package/www/mapshaper.js +25 -8
- package/www/modules.js +4 -1
- package/www/page.css +30 -5
package/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
3
|
+
var VERSION = "0.6.31";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -4846,13 +4846,14 @@
|
|
|
4846
4846
|
|
|
4847
4847
|
// @info: info property of source dataset (instead of crs object, so wkt string
|
|
4848
4848
|
// can be preserved if present)
|
|
4849
|
-
function setDatasetCrsInfo(dataset,
|
|
4849
|
+
function setDatasetCrsInfo(dataset, crsInfo) {
|
|
4850
|
+
crsInfo = crsInfo || {}; // also accepts null/unknown crs info
|
|
4850
4851
|
dataset.info = dataset.info || {};
|
|
4851
4852
|
// Assumes that proj4 object is never mutated.
|
|
4852
4853
|
// TODO: assign a copy of crs (if present)
|
|
4853
|
-
dataset.info.crs =
|
|
4854
|
-
dataset.info.prj =
|
|
4855
|
-
dataset.info.crs_string =
|
|
4854
|
+
dataset.info.crs = crsInfo.crs;
|
|
4855
|
+
dataset.info.prj = crsInfo.prj;
|
|
4856
|
+
dataset.info.crs_string = crsInfo.crs_string;
|
|
4856
4857
|
return dataset;
|
|
4857
4858
|
}
|
|
4858
4859
|
|
|
@@ -23814,6 +23815,10 @@ ${svg}
|
|
|
23814
23815
|
type: 'strings',
|
|
23815
23816
|
describe: 'fields to retain (comma-sep.), e.g. \'fips,name\''
|
|
23816
23817
|
})
|
|
23818
|
+
.option('invert', {
|
|
23819
|
+
type: 'flag',
|
|
23820
|
+
describe: 'retain only fields that would have been deleted'
|
|
23821
|
+
})
|
|
23817
23822
|
.option('target', targetOpt);
|
|
23818
23823
|
|
|
23819
23824
|
parser.command('filter-geom')
|
|
@@ -36481,7 +36486,7 @@ ${svg}
|
|
|
36481
36486
|
return removed;
|
|
36482
36487
|
}
|
|
36483
36488
|
|
|
36484
|
-
cmd.filterFields = function(lyr, names) {
|
|
36489
|
+
cmd.filterFields = function(lyr, names, opts) {
|
|
36485
36490
|
var table = lyr.data;
|
|
36486
36491
|
names = names || [];
|
|
36487
36492
|
requireDataFields(table, names);
|
|
@@ -36490,6 +36495,9 @@ ${svg}
|
|
|
36490
36495
|
// utils.difference(table.getFields(), names).forEach(table.deleteField, table);
|
|
36491
36496
|
// the below method sets field order of CSV output, and is generally faster
|
|
36492
36497
|
var map = mapFieldNames(names);
|
|
36498
|
+
if (opts.invert) {
|
|
36499
|
+
map = invertFieldMap(map, table.getFields());
|
|
36500
|
+
}
|
|
36493
36501
|
lyr.data.update(getRecordMapper(map));
|
|
36494
36502
|
};
|
|
36495
36503
|
|
|
@@ -36500,6 +36508,15 @@ ${svg}
|
|
|
36500
36508
|
lyr.data.update(getRecordMapper(map));
|
|
36501
36509
|
};
|
|
36502
36510
|
|
|
36511
|
+
function invertFieldMap(map, fields) {
|
|
36512
|
+
return fields.reduce(function(memo, name) {
|
|
36513
|
+
if (!(name in map)) {
|
|
36514
|
+
memo[name] = name;
|
|
36515
|
+
}
|
|
36516
|
+
return memo;
|
|
36517
|
+
}, {});
|
|
36518
|
+
}
|
|
36519
|
+
|
|
36503
36520
|
function mapFieldNames(names) {
|
|
36504
36521
|
return (names || []).reduce(function(memo, str) {
|
|
36505
36522
|
var parts = str.split('='),
|
|
@@ -37123,7 +37140,7 @@ ${svg}
|
|
|
37123
37140
|
crsInfo = getDatasetCrsInfo(source.dataset);
|
|
37124
37141
|
} else if (opts.bbox) {
|
|
37125
37142
|
bounds = new Bounds(opts.bbox);
|
|
37126
|
-
crsInfo = getCrsInfo('wgs84');
|
|
37143
|
+
crsInfo = probablyDecimalDegreeBounds(bounds) ? getCrsInfo('wgs84') : {};
|
|
37127
37144
|
}
|
|
37128
37145
|
bounds = bounds && applyRectangleOptions(bounds, crsInfo.crs, opts);
|
|
37129
37146
|
if (!bounds || !bounds.hasBounds()) {
|
|
@@ -43237,7 +43254,7 @@ ${svg}
|
|
|
43237
43254
|
outputLayers = applyCommandToEachLayer(cmd.filterFeatures, targetLayers, arcs, opts);
|
|
43238
43255
|
|
|
43239
43256
|
} else if (name == 'filter-fields') {
|
|
43240
|
-
applyCommandToEachLayer(cmd.filterFields, targetLayers, opts.fields);
|
|
43257
|
+
applyCommandToEachLayer(cmd.filterFields, targetLayers, opts.fields, opts);
|
|
43241
43258
|
|
|
43242
43259
|
} else if (name == 'filter-geom') {
|
|
43243
43260
|
applyCommandToEachLayer(cmd.filterGeom, targetLayers, arcs, opts);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mapshaper",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.31",
|
|
4
4
|
"description": "A tool for editing vector datasets for mapping and GIS.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"shapefile",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"iconv-lite": "^0.6.3",
|
|
57
57
|
"idb-keyval": "^6.2.0",
|
|
58
58
|
"kdbush": "^3.0.0",
|
|
59
|
-
"mproj": "0.0.
|
|
59
|
+
"mproj": "0.0.37",
|
|
60
60
|
"msgpackr": "^1.8.5",
|
|
61
61
|
"opn": "^5.3.0",
|
|
62
62
|
"rw": "~1.3.3",
|
package/www/index.html
CHANGED
|
@@ -100,7 +100,8 @@
|
|
|
100
100
|
<img class="pin-btn pinned" src="images/eye2.png">
|
|
101
101
|
</div>
|
|
102
102
|
<div class="layer-list"></div>
|
|
103
|
-
<h4>Sources</h4>
|
|
103
|
+
<!-- <h4>Sources</h4> -->
|
|
104
|
+
<h4>Source files</h4>
|
|
104
105
|
<div class="file-list"></div>
|
|
105
106
|
<div>
|
|
106
107
|
<div id="add-file-btn" class="dialog-btn btn">Add a file</div>
|
|
@@ -192,8 +193,8 @@ the largest ring of multi-ring features.
|
|
|
192
193
|
</div></div></div></div>
|
|
193
194
|
<div class="planar-opt-wrapper"><label for="planar-opt"><input type="checkbox" class="checkbox planar-opt"/>use planar geometry</label>
|
|
194
195
|
<div class="tip-button">?<div class="tip-anchor">
|
|
195
|
-
<div class="tip">
|
|
196
|
-
on a plane, rather than longitude, latitude
|
|
196
|
+
<div class="tip">Treat x, y values as Cartesian coordinates
|
|
197
|
+
on a plane, rather than as longitude, latitude
|
|
197
198
|
coordinates on a sphere.
|
|
198
199
|
</div></div></div></div>
|
|
199
200
|
</div>
|
|
@@ -256,7 +257,7 @@ a smoother appearance.</div></div></div></div>
|
|
|
256
257
|
|
|
257
258
|
<div id="import-options" class="main-area popup-dialog">
|
|
258
259
|
<div class="info-box">
|
|
259
|
-
|
|
260
|
+
<h3 class="list-header">Files</h3>
|
|
260
261
|
|
|
261
262
|
<div class="dropped-file-list"></div>
|
|
262
263
|
|
|
@@ -272,20 +273,20 @@ a smoother appearance.</div></div></div></div>
|
|
|
272
273
|
self-intersections, to help identify
|
|
273
274
|
topological errors in a dataset.</div></div></div></div>
|
|
274
275
|
|
|
275
|
-
<div><label for="snap-points-opt"><input type="checkbox" class="checkbox" id="snap-points-opt" />snap vertices</label>
|
|
276
|
+
<!-- <div><label for="snap-points-opt"><input type="checkbox" class="checkbox" id="snap-points-opt" />snap vertices</label>
|
|
276
277
|
<div class="tip-button">?<div class="tip-anchor">
|
|
277
278
|
<div class="tip">Fix topology errors by snapping
|
|
278
279
|
together points with nearly identical
|
|
279
280
|
coordinates. This option does not
|
|
280
|
-
apply to TopoJSON files.</div></div></div></div>
|
|
281
|
+
apply to TopoJSON files.</div></div></div></div> -->
|
|
281
282
|
<div style="height:5px"></div>
|
|
282
283
|
|
|
283
284
|
</div>
|
|
284
285
|
|
|
285
286
|
<div><input type="text" class="advanced-options" placeholder="import options" /><div class="tip-button">?<div class="tip-anchor">
|
|
286
287
|
<div class="tip">Enter options from the command line
|
|
287
|
-
interface. Examples: "no-topology
|
|
288
|
-
|
|
288
|
+
interface. Examples: <span id="import-option-examples">no-topology
|
|
289
|
+
encoding=big5</span></div></div></div></div>
|
|
289
290
|
|
|
290
291
|
</div>
|
|
291
292
|
|
package/www/mapshaper-gui.js
CHANGED
|
@@ -1959,7 +1959,21 @@
|
|
|
1959
1959
|
function showQueuedFiles() {
|
|
1960
1960
|
var list = gui.container.findChild('.dropped-file-list').empty();
|
|
1961
1961
|
queuedFiles.forEach(function(f) {
|
|
1962
|
-
|
|
1962
|
+
var html = '<span>' + f.name + '</span><img class="close-btn" draggable="false" src="images/close.png">';
|
|
1963
|
+
var entry = El('<div>').html(html);
|
|
1964
|
+
entry.appendTo(list);
|
|
1965
|
+
// init delete button
|
|
1966
|
+
GUI.onClick(entry.findChild('img.close-btn'), function(e) {
|
|
1967
|
+
e.stopPropagation();
|
|
1968
|
+
queuedFiles = queuedFiles.filter(function(item) {
|
|
1969
|
+
return item != f;
|
|
1970
|
+
});
|
|
1971
|
+
if (queuedFiles.length > 0) {
|
|
1972
|
+
showQueuedFiles();
|
|
1973
|
+
} else {
|
|
1974
|
+
gui.clearMode();
|
|
1975
|
+
}
|
|
1976
|
+
});
|
|
1963
1977
|
});
|
|
1964
1978
|
}
|
|
1965
1979
|
|
|
@@ -2026,23 +2040,23 @@
|
|
|
2026
2040
|
}
|
|
2027
2041
|
if (group[internal.PACKAGE_EXT]) {
|
|
2028
2042
|
await importSessionData(group[internal.PACKAGE_EXT].content, gui);
|
|
2029
|
-
} else {
|
|
2030
|
-
|
|
2043
|
+
} else if (importDataset(group, importOpts)) {
|
|
2044
|
+
importCount++;
|
|
2045
|
+
gui.session.fileImported(group.filename, optStr);
|
|
2031
2046
|
}
|
|
2032
|
-
importCount++;
|
|
2033
|
-
gui.session.fileImported(group.filename, optStr);
|
|
2034
2047
|
}
|
|
2035
2048
|
}
|
|
2036
2049
|
|
|
2037
2050
|
function importDataset(group, importOpts) {
|
|
2038
2051
|
var dataset = internal.importContent(group, importOpts);
|
|
2039
|
-
if (datasetIsEmpty(dataset)) return;
|
|
2052
|
+
if (datasetIsEmpty(dataset)) return false;
|
|
2040
2053
|
if (group.layername) {
|
|
2041
2054
|
dataset.layers.forEach(lyr => lyr.name = group.layername);
|
|
2042
2055
|
}
|
|
2043
2056
|
// save import options for use by repair control, etc.
|
|
2044
2057
|
dataset.info.import_options = importOpts;
|
|
2045
2058
|
model.addDataset(dataset);
|
|
2059
|
+
return true;
|
|
2046
2060
|
}
|
|
2047
2061
|
|
|
2048
2062
|
function addEmptyLayer() {
|
|
@@ -2083,7 +2097,7 @@
|
|
|
2083
2097
|
var freeform = El('#import-options .advanced-options').node().value;
|
|
2084
2098
|
importOpts = GUI.parseFreeformOptions(freeform, 'i');
|
|
2085
2099
|
importOpts.no_repair = !El("#repair-intersections-opt").node().checked;
|
|
2086
|
-
importOpts.snap = !!El("#snap-points-opt").node().checked;
|
|
2100
|
+
// importOpts.snap = !!El("#snap-points-opt").node().checked;
|
|
2087
2101
|
}
|
|
2088
2102
|
return importOpts;
|
|
2089
2103
|
}
|
|
@@ -2183,8 +2197,8 @@
|
|
|
2183
2197
|
name: filename,
|
|
2184
2198
|
content: index[filename]
|
|
2185
2199
|
});
|
|
2186
|
-
return memo;
|
|
2187
2200
|
}
|
|
2201
|
+
return memo;
|
|
2188
2202
|
}, []);
|
|
2189
2203
|
}
|
|
2190
2204
|
|
package/www/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
3
|
+
var VERSION = "0.6.31";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -4846,13 +4846,14 @@
|
|
|
4846
4846
|
|
|
4847
4847
|
// @info: info property of source dataset (instead of crs object, so wkt string
|
|
4848
4848
|
// can be preserved if present)
|
|
4849
|
-
function setDatasetCrsInfo(dataset,
|
|
4849
|
+
function setDatasetCrsInfo(dataset, crsInfo) {
|
|
4850
|
+
crsInfo = crsInfo || {}; // also accepts null/unknown crs info
|
|
4850
4851
|
dataset.info = dataset.info || {};
|
|
4851
4852
|
// Assumes that proj4 object is never mutated.
|
|
4852
4853
|
// TODO: assign a copy of crs (if present)
|
|
4853
|
-
dataset.info.crs =
|
|
4854
|
-
dataset.info.prj =
|
|
4855
|
-
dataset.info.crs_string =
|
|
4854
|
+
dataset.info.crs = crsInfo.crs;
|
|
4855
|
+
dataset.info.prj = crsInfo.prj;
|
|
4856
|
+
dataset.info.crs_string = crsInfo.crs_string;
|
|
4856
4857
|
return dataset;
|
|
4857
4858
|
}
|
|
4858
4859
|
|
|
@@ -23814,6 +23815,10 @@ ${svg}
|
|
|
23814
23815
|
type: 'strings',
|
|
23815
23816
|
describe: 'fields to retain (comma-sep.), e.g. \'fips,name\''
|
|
23816
23817
|
})
|
|
23818
|
+
.option('invert', {
|
|
23819
|
+
type: 'flag',
|
|
23820
|
+
describe: 'retain only fields that would have been deleted'
|
|
23821
|
+
})
|
|
23817
23822
|
.option('target', targetOpt);
|
|
23818
23823
|
|
|
23819
23824
|
parser.command('filter-geom')
|
|
@@ -36481,7 +36486,7 @@ ${svg}
|
|
|
36481
36486
|
return removed;
|
|
36482
36487
|
}
|
|
36483
36488
|
|
|
36484
|
-
cmd.filterFields = function(lyr, names) {
|
|
36489
|
+
cmd.filterFields = function(lyr, names, opts) {
|
|
36485
36490
|
var table = lyr.data;
|
|
36486
36491
|
names = names || [];
|
|
36487
36492
|
requireDataFields(table, names);
|
|
@@ -36490,6 +36495,9 @@ ${svg}
|
|
|
36490
36495
|
// utils.difference(table.getFields(), names).forEach(table.deleteField, table);
|
|
36491
36496
|
// the below method sets field order of CSV output, and is generally faster
|
|
36492
36497
|
var map = mapFieldNames(names);
|
|
36498
|
+
if (opts.invert) {
|
|
36499
|
+
map = invertFieldMap(map, table.getFields());
|
|
36500
|
+
}
|
|
36493
36501
|
lyr.data.update(getRecordMapper(map));
|
|
36494
36502
|
};
|
|
36495
36503
|
|
|
@@ -36500,6 +36508,15 @@ ${svg}
|
|
|
36500
36508
|
lyr.data.update(getRecordMapper(map));
|
|
36501
36509
|
};
|
|
36502
36510
|
|
|
36511
|
+
function invertFieldMap(map, fields) {
|
|
36512
|
+
return fields.reduce(function(memo, name) {
|
|
36513
|
+
if (!(name in map)) {
|
|
36514
|
+
memo[name] = name;
|
|
36515
|
+
}
|
|
36516
|
+
return memo;
|
|
36517
|
+
}, {});
|
|
36518
|
+
}
|
|
36519
|
+
|
|
36503
36520
|
function mapFieldNames(names) {
|
|
36504
36521
|
return (names || []).reduce(function(memo, str) {
|
|
36505
36522
|
var parts = str.split('='),
|
|
@@ -37123,7 +37140,7 @@ ${svg}
|
|
|
37123
37140
|
crsInfo = getDatasetCrsInfo(source.dataset);
|
|
37124
37141
|
} else if (opts.bbox) {
|
|
37125
37142
|
bounds = new Bounds(opts.bbox);
|
|
37126
|
-
crsInfo = getCrsInfo('wgs84');
|
|
37143
|
+
crsInfo = probablyDecimalDegreeBounds(bounds) ? getCrsInfo('wgs84') : {};
|
|
37127
37144
|
}
|
|
37128
37145
|
bounds = bounds && applyRectangleOptions(bounds, crsInfo.crs, opts);
|
|
37129
37146
|
if (!bounds || !bounds.hasBounds()) {
|
|
@@ -43237,7 +43254,7 @@ ${svg}
|
|
|
43237
43254
|
outputLayers = applyCommandToEachLayer(cmd.filterFeatures, targetLayers, arcs, opts);
|
|
43238
43255
|
|
|
43239
43256
|
} else if (name == 'filter-fields') {
|
|
43240
|
-
applyCommandToEachLayer(cmd.filterFields, targetLayers, opts.fields);
|
|
43257
|
+
applyCommandToEachLayer(cmd.filterFields, targetLayers, opts.fields, opts);
|
|
43241
43258
|
|
|
43242
43259
|
} else if (name == 'filter-geom') {
|
|
43243
43260
|
applyCommandToEachLayer(cmd.filterGeom, targetLayers, arcs, opts);
|
package/www/modules.js
CHANGED
|
@@ -12530,7 +12530,10 @@ function wkt_unpack(str) {
|
|
|
12530
12530
|
str = convert_wkt_quotes(str);
|
|
12531
12531
|
|
|
12532
12532
|
// Convert WKT entities to JSON arrays
|
|
12533
|
-
str = str.replace(/([A-Z0-9]+)\[/g, '["$1",');
|
|
12533
|
+
// str = str.replace(/([A-Z0-9]+)\[/g, '["$1",');
|
|
12534
|
+
// Changed to ignore some names that look like entities, like "GCS_TWD97[2020]"
|
|
12535
|
+
// allow only [ or , character before the next quote (i.e. block close quotes)
|
|
12536
|
+
str = str.replace(/([A-Z0-9]+)\[(?![^"]*[^\[,"]")/g, '["$1",');
|
|
12534
12537
|
|
|
12535
12538
|
// Enclose axis keywords in quotes to create valid JSON strings
|
|
12536
12539
|
str = str.replace(/, *([a-zA-Z]+) *(?=[,\]])/g, ',"$1"');
|
package/www/page.css
CHANGED
|
@@ -472,6 +472,25 @@ body.dragover #import-options-drop-area .drop-area {
|
|
|
472
472
|
overflow-y: auto;
|
|
473
473
|
}
|
|
474
474
|
|
|
475
|
+
.dropped-file-list img.close-btn {
|
|
476
|
+
position: absolute;
|
|
477
|
+
cursor: pointer;
|
|
478
|
+
width: 14px;
|
|
479
|
+
height: 14px;
|
|
480
|
+
padding: 0;
|
|
481
|
+
top: 3px;
|
|
482
|
+
right: 0px;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.dropped-file-list > div {
|
|
486
|
+
position: relative;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
.dropped-file-list span {
|
|
490
|
+
margin-right: 16px;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
|
|
475
494
|
#import-options .dropped-file-list p {
|
|
476
495
|
line-height: 1;
|
|
477
496
|
margin-bottom: 5px;
|
|
@@ -498,7 +517,7 @@ body.dragover #import-options-drop-area .drop-area {
|
|
|
498
517
|
text-align: left;
|
|
499
518
|
margin-top: 12px;
|
|
500
519
|
margin-right: 20px;
|
|
501
|
-
padding: 12px
|
|
520
|
+
padding: 12px 16px 12px 18px;
|
|
502
521
|
vertical-align: top;
|
|
503
522
|
display: inline-block;
|
|
504
523
|
/* border: 1px solid #aaa; */
|
|
@@ -512,6 +531,10 @@ body.dragover #import-options-drop-area .drop-area {
|
|
|
512
531
|
font-weight: normal;
|
|
513
532
|
}
|
|
514
533
|
|
|
534
|
+
.info-box h3.list-header {
|
|
535
|
+
margin-bottom: 0.1em;
|
|
536
|
+
}
|
|
537
|
+
|
|
515
538
|
.info-box h4 {
|
|
516
539
|
font-size: 1.085em;
|
|
517
540
|
font-weight: normal;
|
|
@@ -541,8 +564,8 @@ body.dragover #import-options-drop-area .drop-area {
|
|
|
541
564
|
}
|
|
542
565
|
|
|
543
566
|
.info-box .tip-button {
|
|
544
|
-
margin
|
|
545
|
-
|
|
567
|
+
margin: 3px 2px 0 10px;
|
|
568
|
+
|
|
546
569
|
}
|
|
547
570
|
|
|
548
571
|
.info-box input[type="checkbox"] {
|
|
@@ -762,8 +785,10 @@ body.simplify .layer-control-btn {
|
|
|
762
785
|
padding: 0px 14px 2px 14px;
|
|
763
786
|
}
|
|
764
787
|
|
|
788
|
+
|
|
765
789
|
.pin-all img,
|
|
766
|
-
.layer-item img
|
|
790
|
+
.layer-item img
|
|
791
|
+
{
|
|
767
792
|
position: absolute;
|
|
768
793
|
width: 16px;
|
|
769
794
|
height: 16px;
|
|
@@ -784,7 +809,7 @@ img.close-btn {
|
|
|
784
809
|
height: 18px;
|
|
785
810
|
width: 18px;
|
|
786
811
|
margin-top: 1px;
|
|
787
|
-
margin-right: -
|
|
812
|
+
margin-right: -3px;
|
|
788
813
|
cursor: pointer;
|
|
789
814
|
border-radius: 4px;
|
|
790
815
|
}
|