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

global.maplink.domain.MaplinkPoints Maven / Gradle / Ivy

The newest version!
package global.maplink.domain;

import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.lang.Math.floor;
import static java.lang.Math.max;
import static java.util.stream.IntStream.range;

@RequiredArgsConstructor
@EqualsAndHashCode
@ToString
public class MaplinkPoints implements Iterable {

    public static final MaplinkPoints EMPTY = new MaplinkPoints(new MaplinkPoint[0]);

    private static final double DEFAULT_POLYLINE_PRECISION = 1e5;

    private final MaplinkPoint[] data;

    public int size() {
        return data.length;
    }

    public MaplinkPoint first() {
        if (data.length == 0) {
            return null;
        }
        return data[0];
    }

    public MaplinkPoint get(int pos) {
        if (pos >= data.length) {
            return null;
        }
        return data[pos];
    }

    public MaplinkPoint last() {
        if (data.length == 0) {
            return null;
        }
        return data[data.length - 1];
    }

    public String toPolyline() {
        StringBuilder sb = new StringBuilder(max(20, data.length * 3));
        int prevLat = 0;
        int prevLon = 0;
        for (MaplinkPoint point : data) {
            int num = (int) floor(point.getLatitude() * DEFAULT_POLYLINE_PRECISION);
            encodePolylineNumber(sb, num - prevLat);
            prevLat = num;
            num = (int) floor(point.getLongitude() * DEFAULT_POLYLINE_PRECISION);
            encodePolylineNumber(sb, num - prevLon);
            prevLon = num;
        }
        return sb.toString();
    }

    private static void encodePolylineNumber(StringBuilder sb, int num) {
        num = num << 1;
        if (num < 0) {
            num = ~num;
        }
        while (num >= 0x20) {
            int nextValue = (0x20 | (num & 0x1f)) + 63;
            sb.append((char) (nextValue));
            num >>= 5;
        }
        num += 63;
        sb.append((char) (num));
    }

    public List toGeohash() {
        return toList(MaplinkPoint::toGeohash);
    }

    public List toGeohash(int size) {
        return toList(point -> point.toGeohash(size));
    }

    public  List toList(Function transform) {
        return stream()
                .map(transform)
                .collect(Collectors.toList());
    }

    public List toList() {
        return Arrays.asList(data);
    }

    public Stream stream() {
        return Arrays.stream(data);
    }

    @Override
    public Iterator iterator() {
        return stream().iterator();
    }

    @Override
    public Spliterator spliterator() {
        return Arrays.spliterator(data);
    }

    public static MaplinkPoints from(double... points) {
        if (points.length == 0) {
            return EMPTY;
        }
        if (points.length % 2 != 0) {
            throw new IllegalArgumentException("MaplinkPoints.from requires coordinates in pairs");
        }
        return new MaplinkPoints(
                range(0, points.length / 2)
                        .map(i -> i * 2)
                        .mapToObj(v -> new MaplinkPoint(points[v], points[v + 1]))
                        .toArray(MaplinkPoint[]::new)
        );
    }

    public static MaplinkPoints from(double[][] points) {
        return new MaplinkPoints(
                Arrays.stream(points)
                        .map(MaplinkPoint::from)
                        .toArray(MaplinkPoint[]::new)
        );
    }

    public static MaplinkPoints fromGeohash(List geohash) {
        return new MaplinkPoints(
                geohash.stream()
                        .map(MaplinkPoint::fromGeohash)
                        .toArray(MaplinkPoint[]::new)
        );
    }

    public static MaplinkPoints fromPolyline(String encoded) {
        List points = new LinkedList<>();
        int index = 0;
        int len = encoded.length();
        int[] coordinates = new int[]{0, 0};

        while (index < len) {
            int b;
            int[] delta = new int[]{0, 0};
            for (int i = 0; i < 2; i++) {
                int shift = 0;
                int result = 0;
                do {
                    b = encoded.charAt(index++) - 63;
                    result |= (b & 0x1f) << shift;
                    shift += 5;
                } while (b >= 0x20);
                delta[i] = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
                coordinates[i] += delta[i];
            }

            points.add(new MaplinkPoint(
                    (double) coordinates[0] / DEFAULT_POLYLINE_PRECISION,
                    (double) coordinates[1] / DEFAULT_POLYLINE_PRECISION
            ));
        }
        return new MaplinkPoints(points.stream().toArray(MaplinkPoint[]::new));
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy