UNPKG

isoxml-angular

Version:

JavaScript library to parse and generate ISOXML (ISO11783-10) files

107 lines (106 loc) 4.74 kB
"use strict"; 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;