isoxml
Version:
JavaScript library to parse and generate ISOXML (ISO11783-10) files
137 lines (136 loc) • 7.08 kB
JavaScript
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);