Files
PointCloudWeb/PointCloudWeb.Web/public/Potree/libs/shapefile/shapefile.js
2021-08-04 21:30:59 +02:00

482 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// https://github.com/mbostock/shapefile Version 0.6.2. Copyright 2017 Mike Bostock.
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.shapefile = global.shapefile || {})));
}(this, (function (exports) { 'use strict';
var array_cancel = function() {
this._array = null;
return Promise.resolve();
};
var array_read = function() {
var array = this._array;
this._array = null;
return Promise.resolve(array ? {done: false, value: array} : {done: true, value: undefined});
};
function array(array) {
return new ArraySource(array instanceof Uint8Array ? array : new Uint8Array(array));
}
function ArraySource(array) {
this._array = array;
}
ArraySource.prototype.read = array_read;
ArraySource.prototype.cancel = array_cancel;
var fetchPath = function(url) {
return fetch(url).then(function(response) {
return response.body && response.body.getReader
? response.body.getReader()
: response.arrayBuffer().then(array);
});
};
var requestPath = function(url) {
return new Promise(function(resolve, reject) {
var request = new XMLHttpRequest;
request.responseType = "arraybuffer";
request.onload = function() { resolve(array(request.response)); };
request.onerror = reject;
request.ontimeout = reject;
request.open("GET", url, true);
request.send();
});
};
function path(path) {
return (typeof fetch === "function" ? fetchPath : requestPath)(path);
}
function stream(source) {
return typeof source.read === "function" ? source : source.getReader();
}
var empty = new Uint8Array(0);
var slice_cancel = function() {
return this._source.cancel();
};
function concat(a, b) {
if (!a.length) return b;
if (!b.length) return a;
var c = new Uint8Array(a.length + b.length);
c.set(a);
c.set(b, a.length);
return c;
}
var slice_read = function() {
var that = this, array = that._array.subarray(that._index);
return that._source.read().then(function(result) {
that._array = empty;
that._index = 0;
return result.done ? (array.length > 0
? {done: false, value: array}
: {done: true, value: undefined})
: {done: false, value: concat(array, result.value)};
});
};
var slice_slice = function(length) {
if ((length |= 0) < 0) throw new Error("invalid length");
var that = this, index = this._array.length - this._index;
// If the request fits within the remaining buffer, resolve it immediately.
if (this._index + length <= this._array.length) {
return Promise.resolve(this._array.subarray(this._index, this._index += length));
}
// Otherwise, read chunks repeatedly until the request is fulfilled.
var array = new Uint8Array(length);
array.set(this._array.subarray(this._index));
return (function read() {
return that._source.read().then(function(result) {
// When done, its possible the request wasnt fully fullfilled!
// If so, the pre-allocated array is too big and needs slicing.
if (result.done) {
that._array = empty;
that._index = 0;
return index > 0 ? array.subarray(0, index) : null;
}
// If this chunk fulfills the request, return the resulting array.
if (index + result.value.length >= length) {
that._array = result.value;
that._index = length - index;
array.set(result.value.subarray(0, length - index), index);
return array;
}
// Otherwise copy this chunk into the array, then read the next chunk.
array.set(result.value, index);
index += result.value.length;
return read();
});
})();
};
function slice(source) {
return typeof source.slice === "function" ? source :
new SliceSource(typeof source.read === "function" ? source
: source.getReader());
}
function SliceSource(source) {
this._source = source;
this._array = empty;
this._index = 0;
}
SliceSource.prototype.read = slice_read;
SliceSource.prototype.slice = slice_slice;
SliceSource.prototype.cancel = slice_cancel;
var dbf_cancel = function() {
return this._source.cancel();
};
var readBoolean = function(value) {
return /^[nf]$/i.test(value) ? false
: /^[yt]$/i.test(value) ? true
: null;
};
var readDate = function(value) {
return new Date(+value.substring(0, 4), value.substring(4, 6) - 1, +value.substring(6, 8));
};
var readNumber = function(value) {
return !(value = value.trim()) || isNaN(value = +value) ? null : value;
};
var readString = function(value) {
return value.trim() || null;
};
var types = {
B: readNumber,
C: readString,
D: readDate,
F: readNumber,
L: readBoolean,
M: readNumber,
N: readNumber
};
var dbf_read = function() {
var that = this, i = 1;
return that._source.slice(that._recordLength).then(function(value) {
return value && (value[0] !== 0x1a) ? {done: false, value: that._fields.reduce(function(p, f) {
p[f.name] = types[f.type](that._decode(value.subarray(i, i += f.length)));
return p;
}, {})} : {done: true, value: undefined};
});
};
var view = function(array) {
return new DataView(array.buffer, array.byteOffset, array.byteLength);
};
var dbf = function(source, decoder) {
source = slice(source);
return source.slice(32).then(function(array) {
var head = view(array);
return source.slice(head.getUint16(8, true) - 32).then(function(array) {
return new Dbf(source, decoder, head, view(array));
});
});
};
function Dbf(source, decoder, head, body) {
this._source = source;
this._decode = decoder.decode.bind(decoder);
this._recordLength = head.getUint16(10, true);
this._fields = [];
for (var n = 0; body.getUint8(n) !== 0x0d; n += 32) {
for (var j = 0; j < 11; ++j) if (body.getUint8(n + j) === 0) break;
this._fields.push({
name: this._decode(new Uint8Array(body.buffer, body.byteOffset + n, j)),
type: String.fromCharCode(body.getUint8(n + 11)),
length: body.getUint8(n + 16)
});
}
}
var prototype = Dbf.prototype;
prototype.read = dbf_read;
prototype.cancel = dbf_cancel;
function cancel() {
return this._source.cancel();
}
var readMultiPoint = function(record) {
var i = 40, j, n = record.getInt32(36, true), coordinates = new Array(n);
for (j = 0; j < n; ++j, i += 16) coordinates[j] = [record.getFloat64(i, true), record.getFloat64(i + 8, true)];
return {type: "MultiPoint", coordinates: coordinates};
};
var readNull = function() {
return null;
};
var readPoint = function(record) {
return {type: "Point", coordinates: [record.getFloat64(4, true), record.getFloat64(12, true)]};
};
var readPolygon = function(record) {
var i = 44, j, n = record.getInt32(36, true), m = record.getInt32(40, true), parts = new Array(n), points = new Array(m), polygons = [], holes = [];
for (j = 0; j < n; ++j, i += 4) parts[j] = record.getInt32(i, true);
for (j = 0; j < m; ++j, i += 16) points[j] = [record.getFloat64(i, true), record.getFloat64(i + 8, true)];
parts.forEach(function(i, j) {
var ring = points.slice(i, parts[j + 1]);
if (ringClockwise(ring)) polygons.push([ring]);
else holes.push(ring);
});
holes.forEach(function(hole) {
polygons.some(function(polygon) {
if (ringContainsSome(polygon[0], hole)) {
polygon.push(hole);
return true;
}
}) || polygons.push([hole]);
});
return polygons.length === 1
? {type: "Polygon", coordinates: polygons[0]}
: {type: "MultiPolygon", coordinates: polygons};
};
function ringClockwise(ring) {
if ((n = ring.length) < 4) return false;
var i = 0, n, area = ring[n - 1][1] * ring[0][0] - ring[n - 1][0] * ring[0][1];
while (++i < n) area += ring[i - 1][1] * ring[i][0] - ring[i - 1][0] * ring[i][1];
return area >= 0;
}
function ringContainsSome(ring, hole) {
var i = -1, n = hole.length, c;
while (++i < n) {
if (c = ringContains(ring, hole[i])) {
return c > 0;
}
}
return false;
}
function ringContains(ring, point) {
var x = point[0], y = point[1], contains = -1;
for (var i = 0, n = ring.length, j = n - 1; i < n; j = i++) {
var pi = ring[i], xi = pi[0], yi = pi[1],
pj = ring[j], xj = pj[0], yj = pj[1];
if (segmentContains(pi, pj, point)) {
return 0;
}
if (((yi > y) !== (yj > y)) && ((x < (xj - xi) * (y - yi) / (yj - yi) + xi))) {
contains = -contains;
}
}
return contains;
}
function segmentContains(p0, p1, p2) {
var x20 = p2[0] - p0[0], y20 = p2[1] - p0[1];
if (x20 === 0 && y20 === 0) return true;
var x10 = p1[0] - p0[0], y10 = p1[1] - p0[1];
if (x10 === 0 && y10 === 0) return false;
var t = (x20 * x10 + y20 * y10) / (x10 * x10 + y10 * y10);
return t < 0 || t > 1 ? false : t === 0 || t === 1 ? true : t * x10 === x20 && t * y10 === y20;
}
var readPolyLine = function(record) {
var i = 44, j, n = record.getInt32(36, true), m = record.getInt32(40, true), parts = new Array(n), points = new Array(m);
for (j = 0; j < n; ++j, i += 4) parts[j] = record.getInt32(i, true);
for (j = 0; j < m; ++j, i += 16) points[j] = [record.getFloat64(i, true), record.getFloat64(i + 8, true)];
return n === 1
? {type: "LineString", coordinates: points}
: {type: "MultiLineString", coordinates: parts.map(function(i, j) { return points.slice(i, parts[j + 1]); })};
};
var readPolyLineZ = function(record) {
var i = 44, j, n = record.getInt32(36, true), m = record.getInt32(40, true), parts = new Array(n), points = new Array(m);
for (j = 0; j < n; ++j, i += 4) parts[j] = record.getInt32(i, true);
for (j = 0; j < m; ++j, i += 16) points[j] = [record.getFloat64(i, true), record.getFloat64(i + 8, true)];
// Advance two doubles (z min, z max)
i += 16;
for (j = 0; j < m; ++j, i += 8) points[j].push(record.getFloat64(i, true));
return n === 1
? {type: "LineStringZ", coordinates: points}
: {type: "MultiLineStringZ", coordinates: parts.map(function(i, j) { return points.slice(i, parts[j + 1]); })};
};
var shp_read = function() {
var that = this;
return that._source.slice(8).then(function(array) {
if (array == null) return {done: true, value: undefined};
var header = view(array);
return that._source.slice(header.getInt32(4, false) * 2).then(function(array) {
var record = view(array);
return {done: false, value: record.getInt32(0, true) ? that._type(record) : readNull()};
});
});
};
var types$1 = {
0: readNull,
1: readPoint,
3: readPolyLine,
5: readPolygon,
8: readMultiPoint,
11: readPoint,
13: readPolyLineZ,
15: readPolygon,
18: readMultiPoint
};
var shp = function(source) {
source = slice(source);
return source.slice(100).then(function(array) {
return new Shp(source, view(array));
});
};
function Shp(source, header) {
var type = header.getInt32(32, true);
if (!(type in types$1)) throw new Error("unsupported shape type: " + type);
this._source = source;
this._type = types$1[type];
this.bbox = [header.getFloat64(36, true), header.getFloat64(44, true), header.getFloat64(52, true), header.getFloat64(60, true)];
}
var prototype$2 = Shp.prototype;
prototype$2.read = shp_read;
prototype$2.cancel = cancel;
function noop() {}
var shapefile_cancel = function() {
return Promise.all([
this._dbf && this._dbf.cancel(),
this._shp.cancel()
]).then(noop);
};
var shapefile_read = function() {
var that = this;
return Promise.all([
that._dbf ? that._dbf.read() : {value: {}},
that._shp.read()
]).then(function(results) {
var dbf = results[0], shp = results[1];
return shp.done ? shp : {
done: false,
value: {
type: "Feature",
properties: dbf.value,
geometry: shp.value
}
};
});
};
var shapefile = function(shpSource, dbfSource, decoder) {
return Promise.all([
shp(shpSource),
dbfSource && dbf(dbfSource, decoder)
]).then(function(sources) {
return new Shapefile(sources[0], sources[1]);
});
};
function Shapefile(shp$$1, dbf$$1) {
this._shp = shp$$1;
this._dbf = dbf$$1;
this.bbox = shp$$1.bbox;
}
var prototype$1 = Shapefile.prototype;
prototype$1.read = shapefile_read;
prototype$1.cancel = shapefile_cancel;
function open(shp$$1, dbf$$1, options) {
if (typeof dbf$$1 === "string") {
if (!/\.dbf$/.test(dbf$$1)) dbf$$1 += ".dbf";
dbf$$1 = path(dbf$$1, options);
} else if (dbf$$1 instanceof ArrayBuffer || dbf$$1 instanceof Uint8Array) {
dbf$$1 = array(dbf$$1);
} else if (dbf$$1 != null) {
dbf$$1 = stream(dbf$$1);
}
if (typeof shp$$1 === "string") {
if (!/\.shp$/.test(shp$$1)) shp$$1 += ".shp";
if (dbf$$1 === undefined) dbf$$1 = path(shp$$1.substring(0, shp$$1.length - 4) + ".dbf", options).catch(function() {});
shp$$1 = path(shp$$1, options);
} else if (shp$$1 instanceof ArrayBuffer || shp$$1 instanceof Uint8Array) {
shp$$1 = array(shp$$1);
} else {
shp$$1 = stream(shp$$1);
}
return Promise.all([shp$$1, dbf$$1]).then(function(sources) {
var shp$$1 = sources[0], dbf$$1 = sources[1], encoding = "windows-1252";
if (options && options.encoding != null) encoding = options.encoding;
return shapefile(shp$$1, dbf$$1, dbf$$1 && new TextDecoder(encoding));
});
}
function openShp(source, options) {
if (typeof source === "string") {
if (!/\.shp$/.test(source)) source += ".shp";
source = path(source, options);
} else if (source instanceof ArrayBuffer || source instanceof Uint8Array) {
source = array(source);
} else {
source = stream(source);
}
return Promise.resolve(source).then(shp);
}
function openDbf(source, options) {
var encoding = "windows-1252";
if (options && options.encoding != null) encoding = options.encoding;
encoding = new TextDecoder(encoding);
if (typeof source === "string") {
if (!/\.dbf$/.test(source)) source += ".dbf";
source = path(source, options);
} else if (source instanceof ArrayBuffer || source instanceof Uint8Array) {
source = array(source);
} else {
source = stream(source);
}
return Promise.resolve(source).then(function(source) {
return dbf(source, encoding);
});
}
function read(shp$$1, dbf$$1, options) {
return open(shp$$1, dbf$$1, options).then(function(source) {
var features = [], collection = {type: "FeatureCollection", features: features, bbox: source.bbox};
return source.read().then(function read(result) {
if (result.done) return collection;
features.push(result.value);
return source.read().then(read);
});
});
}
exports.open = open;
exports.openShp = openShp;
exports.openDbf = openDbf;
exports.read = read;
Object.defineProperty(exports, '__esModule', { value: true });
})));