UNPKG

isoxml

Version:

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

137 lines (136 loc) 7.08 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { registerEntityClass } from '../../classRegistry'; import { Grid, GridGridTypeEnum } from '../../baseEntities/Grid'; import { TAGS } from '../../baseEntities/constants'; import { createGridParamsGenerator } from './DefaultGridParamsGenerator'; import { cellCenterBasedGridGenerator } from './CellCenterBasedGridGenerator'; const GRID_CELL_SIZE = 10; // meters export class ExtendedGrid extends Grid { constructor(attributes, isoxmlManager) { super(attributes, isoxmlManager); this.tag = TAGS.Grid; } static fromXML(xml, isoxmlManager, internalId) { return __awaiter(this, void 0, void 0, function* () { const entity = yield Grid.fromXML(xml, isoxmlManager, internalId, ExtendedGrid); const filename = entity.attributes.Filename; entity.binaryData = yield isoxmlManager.getParsedFile(`${filename}.bin`, true); if (!entity.binaryData) { isoxmlManager.addWarning(`[${internalId}] Missing grid file ${filename}.bin`); } return entity; }); } /** Creates Grid of Type 2 */ static fromGeoJSON(geoJSON, geoJSONPropertyNames, isoxmlManager, treatmentZoneCode) { const gridParamsGenerator = isoxmlManager.options.gridParamsGenerator || createGridParamsGenerator(GRID_CELL_SIZE, GRID_CELL_SIZE); const gridParams = gridParamsGenerator(geoJSON); const gridGenerator = isoxmlManager.options.gridGenerator || cellCenterBasedGridGenerator; const { minX, minY, numCols, numRows, cellWidth, cellHeight } = gridParams; const buffer = gridGenerator(geoJSON, geoJSONPropertyNames, gridParams); const filename = isoxmlManager.generateUniqueFilename(TAGS.Grid); isoxmlManager.addFileToSave(new Uint8Array(buffer), `${filename}.bin`); const entity = new ExtendedGrid(Object.assign({ GridMinimumNorthPosition: minY, GridMinimumEastPosition: minX, GridCellNorthSize: cellHeight, GridCellEastSize: cellWidth, GridMaximumColumn: numCols, GridMaximumRow: numRows, Filename: filename, Filelength: numCols * numRows * 4 * geoJSONPropertyNames.length, GridType: GridGridTypeEnum.GridType2 }, typeof treatmentZoneCode === 'number' && { TreatmentZoneCode: treatmentZoneCode }), isoxmlManager); entity.binaryData = new Uint8Array(buffer); return entity; } toXML() { this.isoxmlManager.addFileToSave(this.binaryData, `${this.attributes.Filename}.bin`); return super.toXML(); } /** Supports only Grid of Type 2 */ toGeoJSON(propertyNames) { if (this.attributes.GridType === GridGridTypeEnum.GridType1) { throw new Error('GeoJSON for Grids of Type 1 are not supported'); } const rows = this.attributes.GridMaximumRow; const cols = this.attributes.GridMaximumColumn; const w = this.attributes.GridCellEastSize; const h = this.attributes.GridCellNorthSize; const minX = this.attributes.GridMinimumEastPosition; const minY = this.attributes.GridMinimumNorthPosition; const numValues = propertyNames.length; const extectedBufferSize = rows * cols * 4 * numValues; if (extectedBufferSize !== this.binaryData.length) { throw new Error('Can not generate GeoJSON: invalid size of binary data.'); } const cells = new Int32Array(this.binaryData.buffer); const features = new Array(rows * cols); let index = 0; for (let y = 0; y < rows; y++) { for (let x = 0; x < cols; x++) { let allAreZeros = true; const properties = {}; for (const attrName of propertyNames) { const value = cells[index++]; properties[attrName] = value; allAreZeros && (allAreZeros = value === 0); } if (allAreZeros) { features[y * cols + x] = null; continue; } features[y * cols + x] = { type: 'Feature', properties, geometry: { type: 'Polygon', coordinates: [[ [minX + x * w, minY + y * h], [minX + x * w + w, minY + y * h], [minX + x * w + w, minY + y * h + h], [minX + x * w, minY + y * h + h], [minX + x * w, minY + y * h] ]] } }; } } return { type: 'FeatureCollection', features: features.filter(e => e) }; } // the result will be cached getAllReferencedTZNCodes() { if (!this.allReferencedTZNCodes) { if (this.attributes.GridType === GridGridTypeEnum.GridType1) { const codes = new Set(); for (let i = 0; i < this.binaryData.length; i++) { codes.add(this.binaryData[i]); } this.allReferencedTZNCodes = [...codes]; } else { this.allReferencedTZNCodes = [this.attributes.TreatmentZoneCode]; } } return this.allReferencedTZNCodes; } /** Verifies that the binary file of this Grid has correct size. * Adds a warning to "isoxmlManager" if the size is incorrect. * @param isoxmlManager - the ISOXMLManager instance to add warnings to * @param pdvCount - the number of ProcessDataVariable in the grid (used for Type 2 grids) * */ verifyGridSize(isoxmlManager, pdvCount) { const nRows = this.attributes.GridMaximumRow; const nCols = this.attributes.GridMaximumColumn; const bytesPerCell = this.attributes.GridType === GridGridTypeEnum.GridType1 ? 1 : 4 * pdvCount; const expectedSize = nRows * nCols * bytesPerCell; if (expectedSize !== this.binaryData.length) { isoxmlManager.addWarning(`[${this.attributes.Filename}] Invalid size of grid file ${this.attributes.Filename}.bin: ` + `expected ${expectedSize} bytes, but real size is ${this.binaryData.length}`); } } } registerEntityClass('main', TAGS.Grid, ExtendedGrid);