mapshaper 0.5.78 → 0.5.79
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/mapshaper.js +75 -58
- package/package.json +1 -1
- package/www/mapshaper.js +75 -58
package/CHANGELOG.md
CHANGED
package/mapshaper.js
CHANGED
|
@@ -1330,9 +1330,10 @@
|
|
|
1330
1330
|
}
|
|
1331
1331
|
|
|
1332
1332
|
function logArgs(args) {
|
|
1333
|
-
if (LOGGING
|
|
1334
|
-
|
|
1335
|
-
|
|
1333
|
+
if (!LOGGING || getStateVar('QUIET') || !utils.isArrayLike(args)) return;
|
|
1334
|
+
var msg = formatLogArgs(args);
|
|
1335
|
+
if (STDOUT) console.log(msg);
|
|
1336
|
+
else console.error(msg);
|
|
1336
1337
|
}
|
|
1337
1338
|
|
|
1338
1339
|
var Logging = /*#__PURE__*/Object.freeze({
|
|
@@ -20340,6 +20341,16 @@ ${svg}
|
|
|
20340
20341
|
})
|
|
20341
20342
|
.option('name', nameOpt);
|
|
20342
20343
|
|
|
20344
|
+
// parser.command('shapes')
|
|
20345
|
+
// .describe('convert points to shapes')
|
|
20346
|
+
// .option('type', {
|
|
20347
|
+
// })
|
|
20348
|
+
// .option('size', {
|
|
20349
|
+
// })
|
|
20350
|
+
// .option('rotation', {
|
|
20351
|
+
// })
|
|
20352
|
+
|
|
20353
|
+
|
|
20343
20354
|
parser.command('subdivide')
|
|
20344
20355
|
.describe('recursively split a layer using a JS expression')
|
|
20345
20356
|
.validate(validateExpressionOpt)
|
|
@@ -21208,7 +21219,7 @@ ${svg}
|
|
|
21208
21219
|
var header = parseHeader(shpFile.readToBinArray(0, 100));
|
|
21209
21220
|
var shpSize = shpFile.size();
|
|
21210
21221
|
var RecordClass = new ShpRecordClass(header.type);
|
|
21211
|
-
var shpOffset, recordCount
|
|
21222
|
+
var shpOffset, recordCount;
|
|
21212
21223
|
var shxBin, shxFile;
|
|
21213
21224
|
|
|
21214
21225
|
if (shxSrc) {
|
|
@@ -21235,61 +21246,36 @@ ${svg}
|
|
|
21235
21246
|
|
|
21236
21247
|
// Iterator interface for reading shape records
|
|
21237
21248
|
this.nextShape = function() {
|
|
21238
|
-
var shape = readNextShape();
|
|
21239
|
-
if (
|
|
21240
|
-
|
|
21241
|
-
|
|
21242
|
-
// ne_10m_admin_0_boundary_lines_land.shp
|
|
21243
|
-
// ne_110m_admin_0_scale_rank.shp
|
|
21244
|
-
verbose("Skipped over " + skippedBytes + " non-data bytes in the .shp file.");
|
|
21245
|
-
}
|
|
21249
|
+
var shape = readNextShape(recordCount);
|
|
21250
|
+
if (shape) {
|
|
21251
|
+
recordCount++;
|
|
21252
|
+
} else {
|
|
21246
21253
|
shpFile.close();
|
|
21247
21254
|
reset();
|
|
21248
21255
|
}
|
|
21249
21256
|
return shape;
|
|
21250
21257
|
};
|
|
21251
21258
|
|
|
21252
|
-
|
|
21253
|
-
|
|
21259
|
+
// Returns a shape record or null if no more shapes can be read
|
|
21260
|
+
//
|
|
21261
|
+
function readNextShape(i) {
|
|
21262
|
+
var expectedId = i + 1; // Shapefile ids are 1-based
|
|
21254
21263
|
var shape, offset;
|
|
21255
|
-
if (done()) return null;
|
|
21256
21264
|
if (shxBin) {
|
|
21257
|
-
|
|
21265
|
+
if (shxFile.size() <= 100 + i * 8) return null; // done
|
|
21266
|
+
shxBin.position(100 + i * 8);
|
|
21258
21267
|
offset = shxBin.readUint32() * 2;
|
|
21259
|
-
|
|
21260
|
-
skippedBytes += offset - shpOffset;
|
|
21261
|
-
}
|
|
21268
|
+
shape = readIndexedShape(shpFile, offset, expectedId);
|
|
21262
21269
|
} else {
|
|
21270
|
+
// Reading without a .shx file (returns null at end-of-file)
|
|
21263
21271
|
offset = shpOffset;
|
|
21264
|
-
|
|
21265
|
-
shape = readShapeAtOffset(offset);
|
|
21266
|
-
if (!shape) {
|
|
21267
|
-
// Some in-the-wild .shp files contain junk bytes between records. This
|
|
21268
|
-
// is a problem if the .shx index file is not present.
|
|
21269
|
-
// Here, we try to scan past the junk to find the next record.
|
|
21270
|
-
shape = huntForNextShape(offset, expectedId);
|
|
21271
|
-
}
|
|
21272
|
-
if (shape) {
|
|
21273
|
-
if (shape.id < expectedId) {
|
|
21274
|
-
message("Found a Shapefile record with the same id as a previous record (" + shape.id + ") -- skipping.");
|
|
21275
|
-
return readNextShape();
|
|
21276
|
-
} else if (shape.id > expectedId) {
|
|
21277
|
-
stop("Shapefile contains an out-of-sequence record. Possible data corruption -- bailing.");
|
|
21278
|
-
}
|
|
21279
|
-
recordCount++;
|
|
21272
|
+
shape = readNonIndexedShape(shpFile, offset, expectedId);
|
|
21280
21273
|
}
|
|
21281
21274
|
return shape || null;
|
|
21282
21275
|
}
|
|
21283
21276
|
|
|
21284
|
-
function done() {
|
|
21285
|
-
if (shxFile && shxFile.size() <= 100 + recordCount * 8) return true;
|
|
21286
|
-
if (shpOffset + 12 > shpSize) return true;
|
|
21287
|
-
return false;
|
|
21288
|
-
}
|
|
21289
|
-
|
|
21290
21277
|
function reset() {
|
|
21291
21278
|
shpOffset = 100;
|
|
21292
|
-
skippedBytes = 0;
|
|
21293
21279
|
recordCount = 0;
|
|
21294
21280
|
}
|
|
21295
21281
|
|
|
@@ -21319,7 +21305,8 @@ ${svg}
|
|
|
21319
21305
|
return header;
|
|
21320
21306
|
}
|
|
21321
21307
|
|
|
21322
|
-
|
|
21308
|
+
|
|
21309
|
+
function readShapeAtOffset(shpFile, offset) {
|
|
21323
21310
|
var shape = null,
|
|
21324
21311
|
recordSize, recordType, recordId, goodSize, goodType, bin;
|
|
21325
21312
|
|
|
@@ -21334,32 +21321,62 @@ ${svg}
|
|
|
21334
21321
|
if (goodSize && goodType) {
|
|
21335
21322
|
bin = shpFile.readToBinArray(offset, recordSize);
|
|
21336
21323
|
shape = new RecordClass(bin, recordSize);
|
|
21337
|
-
shpOffset = offset + shape.byteLength; // advance read position
|
|
21338
21324
|
}
|
|
21339
21325
|
}
|
|
21340
21326
|
return shape;
|
|
21341
21327
|
}
|
|
21342
21328
|
|
|
21343
|
-
|
|
21344
|
-
|
|
21345
|
-
|
|
21346
|
-
|
|
21329
|
+
function readIndexedShape(shpFile, offset, expectedId) {
|
|
21330
|
+
var shape = readShapeAtOffset(shpFile, offset);
|
|
21331
|
+
if (!shape) {
|
|
21332
|
+
stop('Index of Shapefile record', expectedId, 'in the .shx file is invalid.');
|
|
21333
|
+
}
|
|
21334
|
+
if (shape.id != expectedId) {
|
|
21335
|
+
// stop("Found a Shapefile record with an out-of-sequence id (" + shape.id + ") -- bailing.");
|
|
21336
|
+
message(`Warning: A feature has a different record number in .shx (${expectedId}) and .shp (${shape.id}).`);
|
|
21337
|
+
}
|
|
21338
|
+
// TODO: consider printing verbose message if a .shp file contains garbage bytes
|
|
21339
|
+
// example files:
|
|
21340
|
+
// ne_10m_admin_0_boundary_lines_land.shp
|
|
21341
|
+
// ne_110m_admin_0_scale_rank.shp
|
|
21342
|
+
return shape;
|
|
21343
|
+
}
|
|
21344
|
+
|
|
21345
|
+
// The Shapefile specification does not require records to be densely packed or
|
|
21346
|
+
// in consecutive sequence in the .shp file. This is a problem when the .shx
|
|
21347
|
+
// index file is not present.
|
|
21348
|
+
//
|
|
21349
|
+
// Here, we try to scan past invalid content to find the next record.
|
|
21350
|
+
// Records are required to be in sequential order.
|
|
21351
|
+
//
|
|
21352
|
+
function readNonIndexedShape(shpFile, start, expectedId) {
|
|
21353
|
+
var offset = start,
|
|
21354
|
+
fileSize = shpFile.size(),
|
|
21347
21355
|
shape = null,
|
|
21348
|
-
bin, recordId, recordType,
|
|
21349
|
-
while (offset + 12 <=
|
|
21356
|
+
bin, recordId, recordType, isValidType;
|
|
21357
|
+
while (offset + 12 <= fileSize) {
|
|
21350
21358
|
bin = shpFile.readToBinArray(offset, 12);
|
|
21351
21359
|
recordId = bin.bigEndian().readUint32();
|
|
21352
21360
|
recordType = bin.littleEndian().skipBytes(4).readUint32();
|
|
21353
|
-
|
|
21354
|
-
|
|
21355
|
-
|
|
21356
|
-
|
|
21361
|
+
isValidType = recordType == header.type || recordType === 0;
|
|
21362
|
+
if (!isValidType || recordId != expectedId && recordType === 0) {
|
|
21363
|
+
offset += 4; // keep scanning -- try next integer position
|
|
21364
|
+
continue;
|
|
21357
21365
|
}
|
|
21358
|
-
|
|
21366
|
+
shape = readShapeAtOffset(shpFile, offset);
|
|
21367
|
+
if (!shape) break; // probably ran into end of file
|
|
21368
|
+
shpOffset = offset + shape.byteLength; // update
|
|
21369
|
+
if (recordId == expectedId) break; // found an apparently valid shape
|
|
21370
|
+
if (recordId < expectedId) {
|
|
21371
|
+
message("Found a Shapefile record with the same id as a previous record (" + shape.id + ") -- skipping.");
|
|
21372
|
+
offset += shape.byteLength;
|
|
21373
|
+
} else {
|
|
21374
|
+
stop("Shapefile contains an out-of-sequence record. Possible data corruption -- bailing.");
|
|
21375
|
+
}
|
|
21376
|
+
}
|
|
21377
|
+
if (shape && offset > start) {
|
|
21378
|
+
verbose("Skipped over " + (offset - start) + " non-data bytes in the .shp file.");
|
|
21359
21379
|
}
|
|
21360
|
-
count = shape ? offset - start : shpSize - start;
|
|
21361
|
-
// debug('Skipped', count, 'bytes', shape ? 'before record ' + id : 'at the end of the file');
|
|
21362
|
-
skippedBytes += count;
|
|
21363
21380
|
return shape;
|
|
21364
21381
|
}
|
|
21365
21382
|
}
|
package/package.json
CHANGED
package/www/mapshaper.js
CHANGED
|
@@ -1330,9 +1330,10 @@
|
|
|
1330
1330
|
}
|
|
1331
1331
|
|
|
1332
1332
|
function logArgs(args) {
|
|
1333
|
-
if (LOGGING
|
|
1334
|
-
|
|
1335
|
-
|
|
1333
|
+
if (!LOGGING || getStateVar('QUIET') || !utils.isArrayLike(args)) return;
|
|
1334
|
+
var msg = formatLogArgs(args);
|
|
1335
|
+
if (STDOUT) console.log(msg);
|
|
1336
|
+
else console.error(msg);
|
|
1336
1337
|
}
|
|
1337
1338
|
|
|
1338
1339
|
var Logging = /*#__PURE__*/Object.freeze({
|
|
@@ -20340,6 +20341,16 @@ ${svg}
|
|
|
20340
20341
|
})
|
|
20341
20342
|
.option('name', nameOpt);
|
|
20342
20343
|
|
|
20344
|
+
// parser.command('shapes')
|
|
20345
|
+
// .describe('convert points to shapes')
|
|
20346
|
+
// .option('type', {
|
|
20347
|
+
// })
|
|
20348
|
+
// .option('size', {
|
|
20349
|
+
// })
|
|
20350
|
+
// .option('rotation', {
|
|
20351
|
+
// })
|
|
20352
|
+
|
|
20353
|
+
|
|
20343
20354
|
parser.command('subdivide')
|
|
20344
20355
|
.describe('recursively split a layer using a JS expression')
|
|
20345
20356
|
.validate(validateExpressionOpt)
|
|
@@ -21208,7 +21219,7 @@ ${svg}
|
|
|
21208
21219
|
var header = parseHeader(shpFile.readToBinArray(0, 100));
|
|
21209
21220
|
var shpSize = shpFile.size();
|
|
21210
21221
|
var RecordClass = new ShpRecordClass(header.type);
|
|
21211
|
-
var shpOffset, recordCount
|
|
21222
|
+
var shpOffset, recordCount;
|
|
21212
21223
|
var shxBin, shxFile;
|
|
21213
21224
|
|
|
21214
21225
|
if (shxSrc) {
|
|
@@ -21235,61 +21246,36 @@ ${svg}
|
|
|
21235
21246
|
|
|
21236
21247
|
// Iterator interface for reading shape records
|
|
21237
21248
|
this.nextShape = function() {
|
|
21238
|
-
var shape = readNextShape();
|
|
21239
|
-
if (
|
|
21240
|
-
|
|
21241
|
-
|
|
21242
|
-
// ne_10m_admin_0_boundary_lines_land.shp
|
|
21243
|
-
// ne_110m_admin_0_scale_rank.shp
|
|
21244
|
-
verbose("Skipped over " + skippedBytes + " non-data bytes in the .shp file.");
|
|
21245
|
-
}
|
|
21249
|
+
var shape = readNextShape(recordCount);
|
|
21250
|
+
if (shape) {
|
|
21251
|
+
recordCount++;
|
|
21252
|
+
} else {
|
|
21246
21253
|
shpFile.close();
|
|
21247
21254
|
reset();
|
|
21248
21255
|
}
|
|
21249
21256
|
return shape;
|
|
21250
21257
|
};
|
|
21251
21258
|
|
|
21252
|
-
|
|
21253
|
-
|
|
21259
|
+
// Returns a shape record or null if no more shapes can be read
|
|
21260
|
+
//
|
|
21261
|
+
function readNextShape(i) {
|
|
21262
|
+
var expectedId = i + 1; // Shapefile ids are 1-based
|
|
21254
21263
|
var shape, offset;
|
|
21255
|
-
if (done()) return null;
|
|
21256
21264
|
if (shxBin) {
|
|
21257
|
-
|
|
21265
|
+
if (shxFile.size() <= 100 + i * 8) return null; // done
|
|
21266
|
+
shxBin.position(100 + i * 8);
|
|
21258
21267
|
offset = shxBin.readUint32() * 2;
|
|
21259
|
-
|
|
21260
|
-
skippedBytes += offset - shpOffset;
|
|
21261
|
-
}
|
|
21268
|
+
shape = readIndexedShape(shpFile, offset, expectedId);
|
|
21262
21269
|
} else {
|
|
21270
|
+
// Reading without a .shx file (returns null at end-of-file)
|
|
21263
21271
|
offset = shpOffset;
|
|
21264
|
-
|
|
21265
|
-
shape = readShapeAtOffset(offset);
|
|
21266
|
-
if (!shape) {
|
|
21267
|
-
// Some in-the-wild .shp files contain junk bytes between records. This
|
|
21268
|
-
// is a problem if the .shx index file is not present.
|
|
21269
|
-
// Here, we try to scan past the junk to find the next record.
|
|
21270
|
-
shape = huntForNextShape(offset, expectedId);
|
|
21271
|
-
}
|
|
21272
|
-
if (shape) {
|
|
21273
|
-
if (shape.id < expectedId) {
|
|
21274
|
-
message("Found a Shapefile record with the same id as a previous record (" + shape.id + ") -- skipping.");
|
|
21275
|
-
return readNextShape();
|
|
21276
|
-
} else if (shape.id > expectedId) {
|
|
21277
|
-
stop("Shapefile contains an out-of-sequence record. Possible data corruption -- bailing.");
|
|
21278
|
-
}
|
|
21279
|
-
recordCount++;
|
|
21272
|
+
shape = readNonIndexedShape(shpFile, offset, expectedId);
|
|
21280
21273
|
}
|
|
21281
21274
|
return shape || null;
|
|
21282
21275
|
}
|
|
21283
21276
|
|
|
21284
|
-
function done() {
|
|
21285
|
-
if (shxFile && shxFile.size() <= 100 + recordCount * 8) return true;
|
|
21286
|
-
if (shpOffset + 12 > shpSize) return true;
|
|
21287
|
-
return false;
|
|
21288
|
-
}
|
|
21289
|
-
|
|
21290
21277
|
function reset() {
|
|
21291
21278
|
shpOffset = 100;
|
|
21292
|
-
skippedBytes = 0;
|
|
21293
21279
|
recordCount = 0;
|
|
21294
21280
|
}
|
|
21295
21281
|
|
|
@@ -21319,7 +21305,8 @@ ${svg}
|
|
|
21319
21305
|
return header;
|
|
21320
21306
|
}
|
|
21321
21307
|
|
|
21322
|
-
|
|
21308
|
+
|
|
21309
|
+
function readShapeAtOffset(shpFile, offset) {
|
|
21323
21310
|
var shape = null,
|
|
21324
21311
|
recordSize, recordType, recordId, goodSize, goodType, bin;
|
|
21325
21312
|
|
|
@@ -21334,32 +21321,62 @@ ${svg}
|
|
|
21334
21321
|
if (goodSize && goodType) {
|
|
21335
21322
|
bin = shpFile.readToBinArray(offset, recordSize);
|
|
21336
21323
|
shape = new RecordClass(bin, recordSize);
|
|
21337
|
-
shpOffset = offset + shape.byteLength; // advance read position
|
|
21338
21324
|
}
|
|
21339
21325
|
}
|
|
21340
21326
|
return shape;
|
|
21341
21327
|
}
|
|
21342
21328
|
|
|
21343
|
-
|
|
21344
|
-
|
|
21345
|
-
|
|
21346
|
-
|
|
21329
|
+
function readIndexedShape(shpFile, offset, expectedId) {
|
|
21330
|
+
var shape = readShapeAtOffset(shpFile, offset);
|
|
21331
|
+
if (!shape) {
|
|
21332
|
+
stop('Index of Shapefile record', expectedId, 'in the .shx file is invalid.');
|
|
21333
|
+
}
|
|
21334
|
+
if (shape.id != expectedId) {
|
|
21335
|
+
// stop("Found a Shapefile record with an out-of-sequence id (" + shape.id + ") -- bailing.");
|
|
21336
|
+
message(`Warning: A feature has a different record number in .shx (${expectedId}) and .shp (${shape.id}).`);
|
|
21337
|
+
}
|
|
21338
|
+
// TODO: consider printing verbose message if a .shp file contains garbage bytes
|
|
21339
|
+
// example files:
|
|
21340
|
+
// ne_10m_admin_0_boundary_lines_land.shp
|
|
21341
|
+
// ne_110m_admin_0_scale_rank.shp
|
|
21342
|
+
return shape;
|
|
21343
|
+
}
|
|
21344
|
+
|
|
21345
|
+
// The Shapefile specification does not require records to be densely packed or
|
|
21346
|
+
// in consecutive sequence in the .shp file. This is a problem when the .shx
|
|
21347
|
+
// index file is not present.
|
|
21348
|
+
//
|
|
21349
|
+
// Here, we try to scan past invalid content to find the next record.
|
|
21350
|
+
// Records are required to be in sequential order.
|
|
21351
|
+
//
|
|
21352
|
+
function readNonIndexedShape(shpFile, start, expectedId) {
|
|
21353
|
+
var offset = start,
|
|
21354
|
+
fileSize = shpFile.size(),
|
|
21347
21355
|
shape = null,
|
|
21348
|
-
bin, recordId, recordType,
|
|
21349
|
-
while (offset + 12 <=
|
|
21356
|
+
bin, recordId, recordType, isValidType;
|
|
21357
|
+
while (offset + 12 <= fileSize) {
|
|
21350
21358
|
bin = shpFile.readToBinArray(offset, 12);
|
|
21351
21359
|
recordId = bin.bigEndian().readUint32();
|
|
21352
21360
|
recordType = bin.littleEndian().skipBytes(4).readUint32();
|
|
21353
|
-
|
|
21354
|
-
|
|
21355
|
-
|
|
21356
|
-
|
|
21361
|
+
isValidType = recordType == header.type || recordType === 0;
|
|
21362
|
+
if (!isValidType || recordId != expectedId && recordType === 0) {
|
|
21363
|
+
offset += 4; // keep scanning -- try next integer position
|
|
21364
|
+
continue;
|
|
21357
21365
|
}
|
|
21358
|
-
|
|
21366
|
+
shape = readShapeAtOffset(shpFile, offset);
|
|
21367
|
+
if (!shape) break; // probably ran into end of file
|
|
21368
|
+
shpOffset = offset + shape.byteLength; // update
|
|
21369
|
+
if (recordId == expectedId) break; // found an apparently valid shape
|
|
21370
|
+
if (recordId < expectedId) {
|
|
21371
|
+
message("Found a Shapefile record with the same id as a previous record (" + shape.id + ") -- skipping.");
|
|
21372
|
+
offset += shape.byteLength;
|
|
21373
|
+
} else {
|
|
21374
|
+
stop("Shapefile contains an out-of-sequence record. Possible data corruption -- bailing.");
|
|
21375
|
+
}
|
|
21376
|
+
}
|
|
21377
|
+
if (shape && offset > start) {
|
|
21378
|
+
verbose("Skipped over " + (offset - start) + " non-data bytes in the .shp file.");
|
|
21359
21379
|
}
|
|
21360
|
-
count = shape ? offset - start : shpSize - start;
|
|
21361
|
-
// debug('Skipped', count, 'bytes', shape ? 'before record ' + id : 'at the end of the file');
|
|
21362
|
-
skippedBytes += count;
|
|
21363
21380
|
return shape;
|
|
21364
21381
|
}
|
|
21365
21382
|
}
|