isoxml-angular
Version:
JavaScript library to parse and generate ISOXML (ISO11783-10) files
107 lines (106 loc) • 4.74 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.cellCenterBasedGridGenerator = exports.FeatureFinder = void 0;
const turf_1 = require("@turf/turf");
const rbush_1 = __importDefault(require("rbush"));
// This is an optimized version of https://github.com/Turfjs/turf/tree/master/packages/turf-boolean-point-in-polygon
class FeatureFinder {
constructor(featureCollection) {
this.features = featureCollection.features.map(f => {
const geom = Object.assign({}, f.geometry);
if (geom.type === 'Polygon') {
geom.type = 'MultiPolygon';
geom.coordinates = [geom.coordinates];
}
geom.coordinates = geom.coordinates.map((component) => component.map((ring) => ring[0][0] === ring[ring.length - 1][0] && ring[0][1] === ring[ring.length - 1][1]
? ring.slice(0, ring.length - 1)
: ring));
const binaryCoordinates = geom.coordinates.map((component) => component.map((ring) => {
const binaryRing = new Float32Array(2 * ring.length);
for (let idx = 0; idx < ring.length; idx++) {
binaryRing[2 * idx + 0] = ring[idx][0];
binaryRing[2 * idx + 1] = ring[idx][1];
}
return binaryRing;
}));
return {
type: 'Feature',
properties: f.properties,
bbox: (0, turf_1.bbox)(f),
geometry: geom,
binaryCoordinates
};
});
this.rtree = new rbush_1.default();
this.rtree.load(this.features.map((f) => {
const [bboxMinX, bboxMinY, bboxMaxX, bboxMaxY] = f.bbox;
return { minX: bboxMinX, minY: bboxMinY, maxX: bboxMaxX, maxY: bboxMaxY, feature: f };
}));
}
findFeature(pt) {
var _a;
const searchResults = this.rtree.search({ minX: pt[0], minY: pt[1], maxX: pt[0], maxY: pt[1] });
return (_a = searchResults.find(searchItem => {
const polys = searchItem.feature.binaryCoordinates;
let insidePoly = false;
for (let i = 0; i < polys.length && !insidePoly; i++) {
// check if it is in the outer ring first
if (this.inRingTyped(pt, polys[i][0])) {
let inHole = false;
let k = 1;
// check for the point in any of the holes
while (k < polys[i].length && !inHole) {
if (this.inRingTyped(pt, polys[i][k])) {
inHole = true;
}
k++;
}
if (!inHole) {
insidePoly = true;
}
}
}
return insidePoly;
})) === null || _a === void 0 ? void 0 : _a.feature;
}
inRingTyped(pt, ring) {
let isInside = false;
for (let i = 0, j = ring.length / 2 - 1; i < ring.length / 2; j = i++) {
const xi = ring[2 * i + 0];
const yi = ring[2 * i + 1];
const xj = ring[2 * j + 0];
const yj = ring[2 * j + 1];
const intersect = yi > pt[1] !== yj > pt[1] && pt[0] < ((xj - xi) * (pt[1] - yi)) / (yj - yi) + xi;
if (intersect) {
isInside = !isInside;
}
}
return isInside;
}
}
exports.FeatureFinder = FeatureFinder;
// Simplified algorithm: just check the center of cell
function cellCenterBasedGridGenerator(geometry, gridParams) {
// const initDate = +new Date()
const { minX, minY, numCols, numRows, cellWidth, cellHeight } = gridParams;
const filelength = numCols * numRows * 4;
const buffer = new ArrayBuffer(filelength);
const int32array = new Int32Array(buffer);
const featureFinder = new FeatureFinder(geometry);
// console.log('finder initialization', +new Date() - initDate)
for (let y = 0; y < numRows; y++) {
for (let x = 0; x < numCols; x++) {
const lng = minX + (x + 0.5) * cellWidth;
const lat = minY + (y + 0.5) * cellHeight;
const feature = featureFinder.findFeature([lng, lat]);
const value = feature ? feature.properties.DOSE : 0;
int32array[y * numCols + x] = Math.round(value);
}
}
// console.log('cells generation', +new Date() - initDate)
return buffer;
}
exports.cellCenterBasedGridGenerator = cellCenterBasedGridGenerator;