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

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

/* This program is free software: you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public License
 as published by the Free Software Foundation, either version 3 of
 the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see . */

package org.opentripplanner.common.geometry;

import java.io.Serializable;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.CoordinateSequence;

/**
 * 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; /** * 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; /** * Compact an elevation profile onto a var-len int packed form (Dlugosz coding). * * @param profile The elevation profile to compact * @return The compacted format */ public static byte[] compactElevationProfile(CoordinateSequence elevation) { if (elevation == null) return null; int oix = 0; int oiy = 0; int[] coords = new int[elevation.size() * 2]; 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 ix = (int) Math.round(c.x * FIXED_FLOAT_MULT); int iy = (int) Math.round(c.y * FIXED_FLOAT_MULT); int dix = ix - oix; int diy = iy - oiy; coords[i * 2] = dix; coords[i * 2 + 1] = diy; oix = ix; oiy = iy; } return DlugoszVarLenIntPacker.pack(coords); } /** * Uncompact an ElevationProfile from a var-len int packed form (Dlugosz coding). * * TODO relax the returned type to CoordinateSequence * * @param packedCoords Compacted coordinates * @return The elevation profile */ public static PackedCoordinateSequence uncompactElevationProfile(byte[] packedCoords) { if (packedCoords == null) return null; int[] coords = DlugoszVarLenIntPacker.unpack(packedCoords); int size = coords.length / 2; Coordinate[] c = new Coordinate[size]; int oix = 0; int oiy = 0; for (int i = 0; i < c.length; i++) { int ix = oix + coords[i * 2]; int iy = oiy + coords[i * 2 + 1]; c[i] = new Coordinate(ix / FIXED_FLOAT_MULT, iy / FIXED_FLOAT_MULT); oix = ix; oiy = iy; } return new PackedCoordinateSequence.Double(c, 2); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy