Skip to content

Commit e27f7be

Browse files
committed
Parsing for different degree units
1 parent f61d898 commit e27f7be

File tree

4 files changed

+82
-21
lines changed

4 files changed

+82
-21
lines changed

bundles/paikkatietoikkuna/coordinatetransformation/components/FilePreview.jsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import styled from 'styled-components';
33
import { Message, Card, WarningIcon } from 'oskari-ui';
44
import { ErrorBoundary } from 'oskari-ui/util';
5+
import { parseValue } from '../handler/FileParser';
56

67
const MAX_COLUMNS = 4;
78

@@ -24,7 +25,7 @@ const RawPreviewNode = styled.pre`
2425
`;
2526

2627
const ParseHeaderRow = ({ fileContents }) => {
27-
if (!fileContents.headers) {
28+
if (!fileContents.headers?.length || !fileContents.headerLines?.length) {
2829
return null;
2930
}
3031
const headerLineCount = fileContents.headerLines.length;
@@ -45,8 +46,8 @@ const ParseHeaderRow = ({ fileContents }) => {
4546
</thead>)
4647
}
4748

48-
const PreviewCell = ({ data }) => {
49-
const numberValue = parseFloat(data);
49+
const PreviewCell = ({ data, dataFormat }) => {
50+
const numberValue = parseValue(data, dataFormat);
5051
if (isNaN(numberValue)) {
5152
// show raw value
5253
return (<PreviewCellStyle className={'invalid'}>{data} <WarningIcon/></PreviewCellStyle>);
@@ -55,8 +56,8 @@ const PreviewCell = ({ data }) => {
5556
return (<PreviewCellStyle>{numberValue}</PreviewCellStyle>);
5657
};
5758

58-
const ParseDataRow = ({ fileContents }) => {
59-
if (!fileContents.data) {
59+
const ParseDataRow = ({ fileContents, dataFormat }) => {
60+
if (!fileContents.data || !fileContents.data.length) {
6061
return null;
6162
}
6263
// only show max 2 rows and 4 columns of data
@@ -71,9 +72,9 @@ const ParseDataRow = ({ fileContents }) => {
7172
previewData = previewData.map(data => data.slice(0, MAX_COLUMNS));
7273
colCount = MAX_COLUMNS;
7374
}
74-
const previewRows = previewData.map(data => (
75-
<tr>
76-
{ data.map(cell => (<PreviewCell data={ cell } />)) }
75+
const previewRows = previewData.map((data, i) => (
76+
<tr key={ 'data_' + i }>
77+
{ data.map(cell => (<PreviewCell key={i + '_' + cell} data={ cell } dataFormat={ dataFormat } />)) }
7778
</tr>
7879
));
7980
let extraMessages = [];
@@ -87,7 +88,7 @@ const ParseDataRow = ({ fileContents }) => {
8788
extraMessages.push(<React.Fragment>{colCountOriginal - colCount} <Message messageKey='fileSettings.columns' /></React.Fragment>);
8889
}
8990
if (extraMessages.length) {
90-
previewRows.push(<tr>
91+
previewRows.push(<tr key='metadata'>
9192
<HasMoreCell colSpan={ colCount }>
9293
+ {extraMessages}
9394
</HasMoreCell>
@@ -102,7 +103,7 @@ const RawPreviewRow = ({ fileContents }) => {
102103
return (<RawPreviewNode>{ previewLines.join('\r\n') + '\r\n...' }</RawPreviewNode>);
103104
};
104105

105-
export const FilePreview = ({ fileContents }) => {
106+
export const FilePreview = ({ fileContents, dataFormat }) => {
106107
if (!fileContents) {
107108
return null;
108109
}
@@ -113,7 +114,7 @@ export const FilePreview = ({ fileContents }) => {
113114
<table>
114115
<ParseHeaderRow fileContents={fileContents} />
115116
<tbody>
116-
<ParseDataRow fileContents={fileContents} />
117+
<ParseDataRow fileContents={fileContents} dataFormat={dataFormat} />
117118
</tbody>
118119
</table>
119120
<RawPreviewRow fileContents={fileContents} />

bundles/paikkatietoikkuna/coordinatetransformation/components/FileSettings.jsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,13 @@ const FILE_INPUT_PROPS = {
1616
};
1717

1818
const OPTIONS = {
19-
importSelect: ['decimalSeparator', 'coordinateSeparator'],
20-
importCheckbox: ['prefixId', 'axisFlip'],
19+
importSelect: ['coordinateSeparator', 'decimalSeparator'],
20+
importCheckbox: ['prefixId' /*, 'axisFlip' */],
2121
exportSelect: ['decimalCount', 'decimalSeparator', 'coordinateSeparator', 'lineSeparator'],
2222
exportCheckbox: ['prefixId', 'axisFlip', 'writeHeader', 'writeLineEndings', 'writeCardinals'],
2323
options: {...SEPARATORS, decimalCount: DECIMAL, unit: DEGREE }
2424
};
2525

26-
const IMPORT = ['headerLineCount', 'prefixId', 'axisFlip'];
27-
2826
const Content = styled.div`
2927
display: flex;
3028
flex-direction: column;
@@ -63,10 +61,10 @@ export const ImportFile = ({ import: values, inputSrs, files, fileContents, cont
6361
<Content>
6462
<FileInput mandatory onFiles={controller.setFiles} files={files} { ...FILE_INPUT_PROPS } />
6563
<LabeledInput number min={0} label='fileSettings.options.headerLineCount' value={values.headerLineCount} onChange={value => onChange('headerLineCount', value)} controller={controller}/>
66-
{ showDegreeUnit(inputSrs) && <SelectOption id='unit' controller={controller} onChange={onChange} value={values.unit}/> }
6764
{ OPTIONS.importSelect.map(id => <SelectOption key={id} id={id} controller={controller} onChange={onChange} value={values[id]}/>)}
65+
{ showDegreeUnit(inputSrs) && <SelectOption id='unit' controller={controller} onChange={onChange} value={values.unit}/> }
6866
{ OPTIONS.importCheckbox.map(id => <CheckboxOption key={id} id={id} controller={controller} onChange={onChange} checked={values[id]}/>)}
69-
<FilePreview fileContents={fileContents} />
67+
<FilePreview fileContents={fileContents} dataFormat={values.unit} />
7068
</Content>
7169
);
7270
};

bundles/paikkatietoikkuna/coordinatetransformation/handler/FileParser.js

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { SEPARATORS } from '../constants';
1+
import { DEGREE, SEPARATORS } from '../constants';
22

33
export const parseFile = (file) => {
44
return new Promise((resolve, reject) => {
@@ -49,6 +49,63 @@ export const parseFileContents = (lines = [], delimiter = ';', headerLineCount =
4949
};
5050
};
5151

52+
const HOUR_TO_MIN = 60;
53+
const HOUR_TO_SEC = 3600;
54+
// 2 * pi =~ 6.283185307179586476925286766559
55+
const PI2 = Math.PI * 2;
56+
const DEC_TO_GRAD = 10 / 9;
57+
const DEC_TO_RAD = PI2 / 360;
58+
59+
// https://github.com/nls-oskari/kartta.paikkatietoikkuna.fi/blob/master/service-coordtransform/src/main/java/fi/nls/paikkatietoikkuna/coordtransform/CoordTransService.java#L25-L26
60+
export const parseValue = (value, format = 'default') => {
61+
if (typeof value === 'undefined') {
62+
return NaN;
63+
}
64+
const asNumber = parseFloat(value);
65+
const unitItem = DEGREE.find(unit => unit.value === format);
66+
if (!unitItem) {
67+
return parseFloat(value);
68+
}
69+
if (format === 'gradian') {
70+
return asNumber / DEC_TO_GRAD;
71+
} else if (format === 'radian') {
72+
return asNumber / DEC_TO_RAD;
73+
} else if (!format?.startsWith('DD')) {
74+
return asNumber;
75+
}
76+
// parsing the degree format
77+
const degreeValue = value.replaceAll(' ', '');
78+
const degreeFormat = format.replaceAll(' ', '');
79+
if (degreeFormat === 'DD') {
80+
return asNumber;
81+
} else if (degreeFormat === 'DDMM') {
82+
// value should be a string of length 4+
83+
if (degreeValue.length < 4) {
84+
return NaN;
85+
}
86+
const dd = parseFloat(degreeValue.substring(0, 2));
87+
const mm = parseFloat(degreeValue.substring(2));
88+
if (isNaN(dd) || isNaN(mm)) {
89+
return NaN;
90+
}
91+
return dd + mm / HOUR_TO_MIN;
92+
} else if (degreeFormat === 'DDMMSS') {
93+
// value should be a string of length 5+
94+
if (degreeValue.length < 5) {
95+
return NaN;
96+
}
97+
const dd = parseFloat(degreeValue.substring(0, 2));
98+
const mm = parseFloat(degreeValue.substring(2, 4));
99+
const ss = parseFloat(degreeValue.substring(4));
100+
if (isNaN(dd) || isNaN(mm) || isNaN(ss)) {
101+
return NaN;
102+
}
103+
return dd + (mm / HOUR_TO_MIN) + (ss / HOUR_TO_SEC);
104+
}
105+
106+
return asNumber;
107+
};
108+
52109
const interpretFileContents = (lines = []) => {
53110
const delimiter = detectDelimiter(lines[0]);
54111
const headerLineCount = countHeaders(lines, delimiter);

bundles/paikkatietoikkuna/coordinatetransformation/handler/ViewHandler.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { showConfirmPopup } from '../view/ConfirmPopup';
55
import { showMapSelectPopup, showMapPreviewPopup } from '../view/MapPopup';
66
import { SOURCE, MAP, WATCH_JOB, WATCH_URL, TRANSFORM, FILE_DEFAULTS, SEPARATORS } from '../constants';
77
import { stateToPTIArray, loadFile, validateTransform, validateFileSettings, parseCoordinateValue, is3DSystem } from '../helper';
8-
import { parseFile, parseFileContents } from './FileParser';
8+
import { parseFile, parseFileContents, parseValue } from './FileParser';
99

1010
const getInitialState = () => ({
1111
loading: false,
@@ -357,7 +357,8 @@ class UIHandler extends StateHandler {
357357
}
358358

359359
importFileContentsToInputTable () {
360-
const { fileContents } = this.getState();
360+
const { fileContents, import: importSettings } = this.getState();
361+
const { unit } = importSettings;
361362
/* {
362363
delimiter,
363364
// TODO: we don't need this when we don't send the file to backend
@@ -374,7 +375,11 @@ class UIHandler extends StateHandler {
374375
alert('NOPE');
375376
return;
376377
}
377-
const coordinates = fileContents.data.map(([x, y, z]) => ({ x, y, z }));
378+
const coordinates = fileContents.data.map(([x, y, z]) => ({
379+
x: parseValue(x, unit),
380+
y: parseValue(y, unit),
381+
z: parseValue(z, unit)
382+
}));
378383
this.updateState({ coordinates });
379384
}
380385

0 commit comments

Comments
 (0)