itowns
Version:
A JS/WebGL framework for 3D geospatial data visualization
72 lines (65 loc) • 3.63 kB
JavaScript
import * as THREE from 'three';
import { Extent } from '@itowns/geographic';
import GeoidGrid from "../Core/Geographic/GeoidGrid.js";
import { BYTES_PER_DOUBLE } from "./GTXParser.js";
export function getHeaderAttribute(header, attributeName) {
const attributeRow = header[header.indexOf(header.find(element => element.includes(attributeName)))].split(' ').filter(value => value !== '');
return parseFloat(attributeRow[attributeRow.length - 1]);
}
/**
* The `GDFParser` module provides a `[parse]{@link module:GDFParser.parse}` method. This method takes the content of a
* GDF file in, and returns a `{@link GeoidGrid}`. the `{@link GeoidGrid}` contains all the necessary attributes and
* methods to access the GDF data in iTowns.
*
* @module GDFParser
*/
export default {
/**
* Parses a GDF file content and returns a corresponding {@link GeoidGrid}.
*
* @param {string} gdf The content of the GDF file to parse.
* @param {Object} options An object gathering the optional parameters to pass to
* the parser.
* @param {Object} [options.in={}] Information on the GDF data.
* @param {string} [options.in.crs='EPSG:4326'] The Coordinates Reference System (CRS) of the GDF data.
* It must be a geographic CRS, and must be given as an EPSG
* code.
*
* @returns {Promise<GeoidGrid>} A promise resolving with a {@link GeoidGrid}, which contains all the necessary
* attributes and methods to access GDF file data.
*/
parse(gdf) {
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
in: {}
};
const rows = gdf.split('\n');
const firstMeasureLine = rows.indexOf(rows.find(row => row.includes('end_of_head'))) + 1;
const rawHeaderData = rows.slice(0, firstMeasureLine);
// ---------- GET METADATA FROM THE FILE : ----------
const metadata = {
minX: getHeaderAttribute(rawHeaderData, 'longlimit_west'),
maxX: getHeaderAttribute(rawHeaderData, 'longlimit_east'),
minY: getHeaderAttribute(rawHeaderData, 'latlimit_south'),
maxY: getHeaderAttribute(rawHeaderData, 'latlimit_north'),
stepX: getHeaderAttribute(rawHeaderData, 'gridstep'),
stepY: getHeaderAttribute(rawHeaderData, 'gridstep'),
nRows: getHeaderAttribute(rawHeaderData, 'latitude_parallels'),
nColumns: getHeaderAttribute(rawHeaderData, 'longitude_parallels')
};
// ---------- BUILD A DATA VIEWER FROM THE TEXT DATA : ----------
const data = new DataView(new ArrayBuffer(BYTES_PER_DOUBLE * metadata.nRows * metadata.nColumns));
let index = 0;
for (let row of rows.slice(firstMeasureLine, rows.length)) {
row = row.split(' ').filter(value => value !== '');
if (!row.length) {
continue;
}
data.setFloat64(index * BYTES_PER_DOUBLE, parseFloat(row[2]));
index++;
}
// ---------- CREATE A GeoidGrid FOR THE GIVEN FILE DATA : ----------
const dataExtent = new Extent(options.in.crs || 'EPSG:4326', metadata.minX, metadata.maxX, metadata.minY, metadata.maxY);
const dataStep = new THREE.Vector2(metadata.stepX, metadata.stepY);
return Promise.resolve(new GeoidGrid(dataExtent, dataStep, (verticalIndex, horizontalIndex) => data.getFloat64((metadata.nColumns * (metadata.nRows - verticalIndex - 1) + horizontalIndex) * BYTES_PER_DOUBLE)));
}
};