fieldnotes/src/util/export.ts

143 lines
3.8 KiB
TypeScript

import RNFS from 'react-native-fs';
import Share from 'react-native-share';
import { ActionSheet } from 'native-base';
import { XYZtoLLA, LLAtoXYZ, WGS84Ellipsoid, project, Projections, EPSG_WGS84 } from './projection';
import { ErrSelectionCanceled } from './errors';
import { ControlSession } from '../store/reducers/control-sessions';
import { ControlledPoint } from '../store';
import { slice } from 'lodash';
const ExportDirectoryPath = `${RNFS.ExternalDirectoryPath}/fieldnotes/export`;
const CellSeparator = ';';
const LineSeparator = '\n';
const projectionsButtons = Projections.map(p => {
return { text: p.title, projection: p.code }
});
export function selectProjection(): any {
return new Promise((resolve, reject) => {
ActionSheet.show(
{
options: projectionsButtons.map(b => b.text),
title: "Sélectionner la projection"
},
buttonIndex => {
if (buttonIndex === undefined) {
return reject(ErrSelectionCanceled);
}
const p = projectionsButtons[buttonIndex];
return resolve(p);
}
)
});
}
export function exportEntititiesToCSV(siteUUID: string, entities: any) {
return createExportDirectory()
.then(() => selectProjection())
.then(({ projection }) => {
const csv = entitiesToCSV(entities, projection);
const filePath = `${ExportDirectoryPath}/site_${siteUUID}_${Date.now()}.csv`;
return RNFS.writeFile(filePath, csv, 'utf8')
.then((res) => {
return filePath;
})
;
})
;
}
export function exportControlSessionToCSV(session: ControlSession) {
return createExportDirectory()
.then(() => {
const csv = controlSessionToCSV(session);
const filePath = `${ExportDirectoryPath}/session_${session.uuid}_${Date.now()}.csv`;
return RNFS.writeFile(filePath, csv, 'utf8')
.then((res) => {
return filePath;
})
;
})
;
}
export function shareCSV(filepath: string) {
return Share.open({
url: `file://${filepath}`,
type: 'text/csv',
showAppsToView: true,
failOnCancel: false,
});
}
export function entitiesToCSV(entities: any, projection: any) {
// Transform ECEF WGS84 coordinates to geodetic/cartesian coordinates
const transformCoordinates = ({x, y, z}: any) => {
const lla = XYZtoLLA(x, y, z, WGS84Ellipsoid);
const p = project(EPSG_WGS84, projection, lla.latitude, lla.longitude);
return [ p.x, p.y, lla.altitude ];
};
let index = 0;
return entities.reduce((rows: any[], e: any) => {
rows.push(...e.positions.map((p: any) => {
return [
index++,
...transformCoordinates(p),
...metadataToArray(e.metadata)
];
}));
// If the entity is of type "rect", push first row
// to close geometry
if (e.metadata.type == "rect") {
const copy = rows[0].slice(0);
copy[0] = index++;
rows.push(copy);
}
return rows.map(row => row.join(CellSeparator));
}, []).join(LineSeparator);
}
function controlSessionToCSV(session: ControlSession): string {
let index = 0;
return session.controlPoints.reduce((rows: any[], cp: ControlledPoint) => {
rows.push([
index++,
session.siteUUID,
session.date ? session.date : '',
cp.expectedX,
cp.expectedY,
cp.expectedZ,
cp.x,
cp.xPrecision,
cp.y,
cp.yPrecision,
cp.z,
cp.zPrecision,
].join(CellSeparator));
return rows;
}, []).join(LineSeparator);
}
const exportedMetadatas = [
'category',
'code',
'controlSession',
'creationDate',
'type'
];
function metadataToArray(metadata: any) {
return exportedMetadatas.sort().map(key => {
return metadata[key] ? metadata[key]: '';
});
}
function createExportDirectory() {
return RNFS.mkdir(ExportDirectoryPath)
}