All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentripplanner.common.geometry.CompactElevationProfile Maven / Gradle / Ivy

package org.opentripplanner.common.geometry;

import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.CoordinateSequence;

import java.io.Serializable;

/**
 * Compact elevation profile. To optimize storage, we use the following tricks:
 * 
    *
  • Store intermediate point in fixed floating points with fixed precision, using delta coding * from the previous point, and variable length coding (most of the delta coordinates will thus fits * in 1 or 2 bytes).
  • *
* * Performance hit should be low as we do not need the elevation profile itself during a path * search. * * @author laurent */ public final class CompactElevationProfile implements Serializable { private static final long serialVersionUID = 1L; public static final double DEFAULT_DISTANCE_BETWEEN_SAMPLES_METERS = 10; /** * Multipler for fixed-float representation. In meters, the precision is 1 cm (elevation and arc * length). */ private static final double FIXED_FLOAT_MULT = 1.0e2; /** * The distance between samples in meters. Defaults to 10m, the approximate resolution of 1/3 * arc-second NED data. */ private static double distanceBetweenSamplesM = DEFAULT_DISTANCE_BETWEEN_SAMPLES_METERS; /** * Compact an elevation profile onto a var-len int packed form (Dlugosz coding). This method * supposes that only the y-values are to be compacted and the x-values can be reconstructed * at regular intervals according to the distanceBetweenSamplesM field. The last x-value is given * by the length of the geometry. * * @param elevation The elevation profile to compact * @return The compacted format */ public static byte[] compactElevationProfileWithRegularSamples(CoordinateSequence elevation) { if (elevation == null) return null; int oiy = 0; int[] coords = new int[elevation.size()]; for (int i = 0; i < elevation.size(); i++) { /* * Note: We should do the rounding *before* the delta to prevent rounding errors from * accumulating on long line strings. */ Coordinate c = elevation.getCoordinate(i); int iy = (int) Math.round(c.y * FIXED_FLOAT_MULT); int diy = iy - oiy; coords[i] = diy; oiy = iy; } return DlugoszVarLenIntPacker.pack(coords); } /** * Uncompact an ElevationProfile from a var-len int packed form (Dlugosz coding). This method * supposes that only the y-values have been compacted and x-values will be reconstructed at * regular interval according to the distanceBetweenSamplesM field. The last x-value is given * by the length of the geometry. * * @param packedCoords Compacted coordinates * @param lengthM The length of the edge in meters. This is used as the x-value of the final * height sample * @return The elevation profile */ public static PackedCoordinateSequence uncompactElevationProfileWithRegularSamples(byte[] packedCoords, double lengthM) { if (packedCoords == null) return null; int[] coords = DlugoszVarLenIntPacker.unpack(packedCoords); int size = coords.length; Coordinate[] c = new Coordinate[size]; int oiy = 0; for (int i = 0; i < c.length; i++) { int iy = oiy + coords[i]; c[i] = new Coordinate( i == c.length - 1 ? lengthM : i * distanceBetweenSamplesM, iy / FIXED_FLOAT_MULT); oiy = iy; } return new PackedCoordinateSequence.Double(c, 2); } public static void setDistanceBetweenSamplesM(double distance) { distanceBetweenSamplesM = distance; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy