comparison client/src/application/lib/geo.js @ 666:4c36b0e39d78

feat: prepareProfile converts geoJSON to diagram data. PrepareProfile assumes data given in geoJSON format. It extracts heigth and width information for the diagram and transposes every coordinate given relative to the first coordinate in the first set.
author Thomas Junk <thomas.junk@intevation.de>
date Tue, 18 Sep 2018 13:43:24 +0200
parents
children 3605af94d1ee
comparison
equal deleted inserted replaced
663:db749c02127c 666:4c36b0e39d78
1 /**
2 *
3 * Distance calculations
4 * JS transposition of cross.go functions
5 *
6 */
7
8 const EARTHRADIUS = 6378137.0;
9
10 /**
11 * Converts to radiant
12 * @param {degree} d
13 */
14 const deg2rad = d => {
15 return (d * Math.PI) / 180.0;
16 };
17
18 /**
19 * Calculates the difference between two points in m
20 *
21 * Points are given with {lat: $lat, lon: $lon}
22 *
23 * @param {object} P1
24 * @param {object} P2
25 */
26 const distanceBetween = (P1, P2) => {
27 const dLat = deg2rad(P2.lat - P1.lat);
28 let dLng = Math.abs(deg2rad(P2.lon - P1.lon));
29 if (dLng > Math.PI) {
30 dLng = 2 * Math.PI - dLng;
31 }
32 const x = dLng * Math.cos(deg2rad((P1.lat + P2.lat) / 2.0));
33 return Math.sqrt(dLat * dLat + x * x) * EARTHRADIUS;
34 };
35
36 /**
37 * Takes a triple of [lat, long, alt] and generates
38 * an object with according attributes
39 * {
40 * lat: $lat,
41 * lon: $lon,
42 * alt: $alt
43 * }
44 *
45 * @param {array} coords
46 */
47 const generatePoint = coords => {
48 return {
49 lon: coords[0],
50 lat: coords[1],
51 alt: coords[2]
52 };
53 };
54
55 /**
56 * Has geoJSON as its input and transforms
57 * given coordinates
58 *
59 * a) extracting the minimum altitude
60 * b) extracting the maximum altitude
61 * c) calculating the total length of the given profile
62 * d) transposes the datapoints given to the first point of the first section
63 *
64 * @param {object} feature
65 */
66 const transform = feature => {
67 const sections = feature.geometry.coordinates;
68 let firstPoint = generatePoint(sections[0][0]);
69 let coordinates = [];
70 let totalLength = 0;
71 let minAlt = firstPoint.alt;
72 let maxAlt = firstPoint.alt;
73 for (let section of sections) {
74 let sectionCoordinates = [];
75 let previousPoint = generatePoint(section[0]);
76 for (let coords of section) {
77 const currentPoint = generatePoint(coords);
78 let x = distanceBetween(firstPoint, currentPoint);
79 let y = coords[2];
80 sectionCoordinates.push({
81 x: x,
82 y: y
83 });
84 totalLength += distanceBetween(currentPoint, previousPoint);
85 previousPoint = currentPoint;
86 if (y < minAlt) minAlt = y;
87 if (y > maxAlt) maxAlt = y;
88 }
89 coordinates.push(sectionCoordinates);
90 }
91 return { coordinates, totalLength, minAlt, maxAlt };
92 };
93
94 /**
95 * Prepare profile takes geoJSON data in form of
96 * a MultiLineString, e.g.
97 *
98 * {
99 * type: "Feature",
100 * geometry: {
101 * type: "MultiLineString",
102 * coordinates: [
103 * [
104 * [16.53593398, 48.14694085, -146.52392755]
105 * ...
106 * ]]
107 *
108 * and transforms it to a structure representing the number of sections
109 * where data is present with according lengths and the points
110 *
111 * {
112 * { points:
113 * [
114 * [ { x: 0.005798201616417183, y: -146.52419461 },
115 * { x: 0, y: -146.52394016 }
116 * ...
117 * ]
118 * ]
119 * totalLength: 160.06814078495722,
120 * minAlt: -146.73122231,
121 * maxAlt: -145.65155866
122 * }
123 *
124 * @param {object} geoJSON
125 */
126 const prepareProfile = geoJSON => {
127 const { coordinates, totalLength, minAlt, maxAlt } = transform(geoJSON);
128 return {
129 points: coordinates,
130 totalLength: totalLength,
131 minAlt: minAlt,
132 maxAlt: maxAlt
133 };
134 };
135
136 export { prepareProfile };