import {Feature, FeatureCollection, GeometryObject} from 'geojson'; import {jsonClone} from 'tsfun/struct'; import {FieldDocument, FieldGeometry} from 'idai-components-2'; import {FieldReadDatastore} from '../datastore/field/field-read-datastore'; import {M} from '../../components/messages/m'; import {Query} from '../datastore/model/query'; const geojsonRewind = typeof window !== 'undefined' ? window.require('geojson-rewind') : require('geojson-rewind'); const fs = typeof window !== 'undefined' ? window.require('fs') : require('fs'); /** * @author Thomas Kleinke */ export module GeoJsonExporter { export async function performExport(datastore: FieldReadDatastore, outputFilePath: string, operationId: string): Promise { const documents: Array = await getGeometryDocuments(datastore, operationId); const featureCollection: FeatureCollection = createFeatureCollection(documents); return writeFile(outputFilePath, featureCollection); } async function getGeometryDocuments(datastore: FieldReadDatastore, operationId: string): Promise> { const query: Query = createQuery(operationId); return (await datastore.find(query)).documents; } function createQuery(operationId: string): Query { const query: Query = { q: '', constraints: { 'geometry:exist': 'KNOWN' } }; if (operationId !== 'project') (query.constraints as any)['isRecordedIn:contain'] = operationId; return query; } function createFeatureCollection(documents: Array): FeatureCollection { const featureCollection: FeatureCollection = { type: 'FeatureCollection', features: documents.map(createFeature) }; geojsonRewind(featureCollection); return featureCollection; } function createFeature(document: FieldDocument): Feature { return { type: 'Feature', geometry: getGeometry(document), properties: getProperties(document) }; } function writeFile(outputFilePath: string, featureCollection: FeatureCollection): Promise { const json: string = JSON.stringify(featureCollection, null, 2); return new Promise((resolve, reject) => { fs.writeFile(outputFilePath, json, (err: any) => { if (err) { console.error(err); reject([M.EXPORT_GEOJSON_ERROR_WRITE]); } else { resolve(); } }); }); } function getGeometry(document: FieldDocument): GeometryObject { return { type: (document.resource.geometry as FieldGeometry).type, coordinates: getCoordinates(document.resource.geometry as FieldGeometry) }; } function getCoordinates(geometry: FieldGeometry): any { const coordinates: any = jsonClone(geometry.coordinates); if (geometry.type === 'Polygon') { closeRings(coordinates); } else if (geometry.type === 'MultiPolygon') { coordinates.forEach(closeRings); } return coordinates; } function closeRings(polygonCoordinates: number[][][]) { polygonCoordinates.forEach(ring => { if (ring[0][0] !== ring[ring.length - 1][0] || ring[0][1] !== ring[ring.length - 1][1]) { ring.push([ring[0][0], ring[0][1]]); } }); } function getProperties(document: FieldDocument): any { const properties: any = { identifier: document.resource.identifier, shortDescription: document.resource.shortDescription, category: document.resource.category }; if (!properties.shortDescription) delete properties.shortDescription; return properties; } }