Mercurial > gemma
view client/src/application/lib/geo.js @ 974:7a89313f0ead
Fetch the octree directly from the builder. No need to deserialize it from the blob.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Thu, 18 Oct 2018 15:11:49 +0200 |
parents | dedf252b3e01 |
children | ca628dce90dd |
line wrap: on
line source
/** * * Distance calculations * JS transposition of cross.go functions * */ const EARTHRADIUS = 6378137.0; /** * Converts to radiant * @param {degree} d */ const deg2rad = d => { return (d * Math.PI) / 180.0; }; /** * Calculates the difference between two points in m * * Points are given with {lat: $lat, lon: $lon} * * @param {object} P1 * @param {object} P2 */ const distanceBetween = (P1, P2) => { const dLat = deg2rad(P2.lat - P1.lat); let dLng = Math.abs(deg2rad(P2.lon - P1.lon)); if (dLng > Math.PI) { dLng = 2 * Math.PI - dLng; } const x = dLng * Math.cos(deg2rad((P1.lat + P2.lat) / 2.0)); return Math.sqrt(dLat * dLat + x * x) * EARTHRADIUS; }; /** * Takes a triple of [lat, long, alt] and generates * an object with according attributes * { * lat: $lat, * lon: $lon, * alt: $alt * } * * @param {array} coords */ const Point = coords => { return { lon: coords[0], lat: coords[1], alt: coords[2] }; }; /** * Has geoJSON as its input and transforms * given coordinates into points representing * distance from startpoint / altitude information * * a) extracting the minimum altitude * b) extracting the maximum altitude * c) calculating the total length of the given profile * d) transposes the datapoints relative to a given start point * * The calculation of total equals the sum of partial distances between points * * The x-value of a point is equal to the total distance up to this point * * The distance between the last point of the last segment and the end point is added * to the total * * @param {object} geoJSON, startPoint, endPoint */ const transform = ({ geoJSON, startPoint, endPoint }) => { const lineSegments = geoJSON.geometry.coordinates; let segmentPoints = []; let lengthPolyLine = 0; let referencePoint = Point(startPoint); let minAlt = Math.abs(lineSegments[0][0][2]); let maxAlt = Math.abs(lineSegments[0][0][2]); let currentPoint = null; for (let segment of lineSegments) { let points = []; for (let coordinateTriplet of segment) { currentPoint = Point(coordinateTriplet); lengthPolyLine += distanceBetween(referencePoint, currentPoint); let y = Math.abs(currentPoint.alt); points.push({ x: lengthPolyLine, y: y }); if (y < minAlt) minAlt = y; if (y > maxAlt) maxAlt = y; referencePoint = currentPoint; } segmentPoints.push(points); } lengthPolyLine += distanceBetween(currentPoint, Point(endPoint)); return { segmentPoints, lengthPolyLine, minAlt, maxAlt }; }; /** * Prepare profile takes geoJSON data in form of * a MultiLineString, e.g. * * { * type: "Feature", * geometry: { * type: "MultiLineString", * coordinates: [ * [ * [16.53593398, 48.14694085, -146.52392755] * ... * ]] * * and transforms it to a structure representing the number of sections * where data is present with according lengths and the points * * { * { points: * [ * [ { x: 0.005798201616417183, y: -146.52419461 }, * { x: 0, y: -146.52394016 } * ... * ] * ] * lengthPolyLine: 160.06814078495722, * minAlt: -146.73122231, * maxAlt: -145.65155866 * } * * @param {object} geoJSON */ const prepareProfile = ({ geoJSON, startPoint, endPoint }) => { const { segmentPoints, lengthPolyLine, minAlt, maxAlt } = transform({ geoJSON, startPoint, endPoint }); return { points: segmentPoints, lengthPolyLine: lengthPolyLine, minAlt: minAlt, maxAlt: maxAlt }; }; export { prepareProfile };