Package org.opentripplanner.util

Source Code of org.opentripplanner.util.PolylineEncoder$CoordinateList

/* 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 <http://www.gnu.org/licenses/>. */

package org.opentripplanner.util;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;

import org.opentripplanner.util.model.EncodedPolylineBean;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;

public class PolylineEncoder {

    public static EncodedPolylineBean createEncodings(double[] lat, double[] lon) {
        return createEncodings(new PointAdapterList(lat, lon));
    }

    public static EncodedPolylineBean createEncodings(double[] lat, double[] lon, int level) {
        return createEncodings(new PointAdapterList(lat, lon), level);
    }

    public static EncodedPolylineBean createEncodings(double[] lat, double[] lon, int offset,
            int length, int level) {
        return createEncodings(new PointAdapterList(lat, lon, offset, length), level);
    }

    public static EncodedPolylineBean createEncodings(Iterable<Coordinate> points) {
        return createEncodings(points, -1);
    }

    public static EncodedPolylineBean createEncodings(Geometry geometry) {
        if (geometry instanceof LineString) {

            LineString string = (LineString) geometry;
            Coordinate[] coordinates = string.getCoordinates();
            return createEncodings(new CoordinateList(coordinates));
        } else if (geometry instanceof MultiLineString) {
            MultiLineString mls = (MultiLineString) geometry;
            return createEncodings(new CoordinateList(mls.getCoordinates()));
        } else {
            throw new IllegalArgumentException(geometry.toString());
        }
    }

    /**
     * If level < 0, then {@link EncodedPolylineBean#getLevels()} will be null.
     *
     * @param points
     * @param level
     * @return
     */
    public static EncodedPolylineBean createEncodings(Iterable<Coordinate> points, int level) {

        StringBuilder encodedPoints = new StringBuilder();
        StringBuilder encodedLevels = new StringBuilder();

        int plat = 0;
        int plng = 0;
        int count = 0;

        for (Coordinate point : points) {

            int late5 = floor1e5(point.y);
            int lnge5 = floor1e5(point.x);

            int dlat = late5 - plat;
            int dlng = lnge5 - plng;

            plat = late5;
            plng = lnge5;

            encodedPoints.append(encodeSignedNumber(dlat)).append(encodeSignedNumber(dlng));
            if (level >= 0)
                encodedLevels.append(encodeNumber(level));
            count++;
        }

        String pointsString = encodedPoints.toString();
        String levelsString = level >= 0 ? encodedLevels.toString() : null;
        return new EncodedPolylineBean(pointsString, levelsString, count);
    }

    public static List<Coordinate> decode(EncodedPolylineBean polyline) {

        String pointString = polyline.getPoints();

        double lat = 0;
        double lon = 0;

        int strIndex = 0;
        List<Coordinate> points = new ArrayList<Coordinate>();

        while (strIndex < pointString.length()) {

            int[] rLat = decodeSignedNumberWithIndex(pointString, strIndex);
            lat = lat + rLat[0] * 1e-5;
            strIndex = rLat[1];

            int[] rLon = decodeSignedNumberWithIndex(pointString, strIndex);
            lon = lon + rLon[0] * 1e-5;
            strIndex = rLon[1];

            points.add(new Coordinate(lat, lon));
        }

        return points;
    }

    /*****************************************************************************
     * Private Methods
     ****************************************************************************/

    private static final int floor1e5(double coordinate) {
        return (int) Math.floor(coordinate * 1e5);
    }

    public static String encodeSignedNumber(int num) {
        int sgn_num = num << 1;
        if (num < 0) {
            sgn_num = ~(sgn_num);
        }
        return (encodeNumber(sgn_num));
    }

    public static int decodeSignedNumber(String value) {
        int[] r = decodeSignedNumberWithIndex(value, 0);
        return r[0];
    }

    public static int[] decodeSignedNumberWithIndex(String value, int index) {
        int[] r = decodeNumberWithIndex(value, index);
        int sgn_num = r[0];
        if ((sgn_num & 0x01) > 0) {
            sgn_num = ~(sgn_num);
        }
        r[0] = sgn_num >> 1;
        return r;
    }

    public static String encodeNumber(int num) {

        StringBuffer encodeString = new StringBuffer();

        while (num >= 0x20) {
            int nextValue = (0x20 | (num & 0x1f)) + 63;
            encodeString.append((char) (nextValue));
            num >>= 5;
        }

        num += 63;
        encodeString.append((char) (num));

        return encodeString.toString();
    }

    public static int decodeNumber(String value) {
        int[] r = decodeNumberWithIndex(value, 0);
        return r[0];
    }

    public static int[] decodeNumberWithIndex(String value, int index) {

        if (value.length() == 0)
            throw new IllegalArgumentException("string is empty");

        int num = 0;
        int v = 0;
        int shift = 0;

        do {
            v = value.charAt(index++) - 63;
            num |= (v & 0x1f) << shift;
            shift += 5;
        } while (v >= 0x20);

        return new int[] { num, index };
    }

    private static class PointAdapterList extends AbstractList<Coordinate> {

        private double[] _lat;
        private double[] _lon;
        private int _offset;
        private int _length;

        public PointAdapterList(double[] lat, double[] lon) {
            this(lat, lon, 0, lat.length);
        }

        public PointAdapterList(double[] lat, double[] lon, int offset, int length) {
            _lat = lat;
            _lon = lon;
            _offset = offset;
            _length = length;
        }

        @Override
        public Coordinate get(int index) {
            return new Coordinate(_lon[_offset + index], _lat[_offset + index]);
        }

        @Override
        public int size() {
            return _length;
        }
    }

    private static class CoordinateList extends AbstractList<Coordinate> {

        private Coordinate[] _coordinates;

        public CoordinateList(Coordinate[] coordinates) {
            _coordinates = coordinates;
        }

        @Override
        public Coordinate get(int index) {
            return _coordinates[index];
        }

        @Override
        public int size() {
            return _coordinates.length;
        }
    }
}
TOP

Related Classes of org.opentripplanner.util.PolylineEncoder$CoordinateList

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.