Skip to content

Instantly share code, notes, and snippets.

@michael-simons
Last active April 13, 2025 15:36
Show Gist options
  • Select an option

  • Save michael-simons/8d47454c9586db88fb3a1cc7b8ce1cf9 to your computer and use it in GitHub Desktop.

Select an option

Save michael-simons/8d47454c9586db88fb3a1cc7b8ce1cf9 to your computer and use it in GitHub Desktop.

Revisions

  1. michael-simons revised this gist Apr 13, 2025. 1 changed file with 39 additions and 36 deletions.
    75 changes: 39 additions & 36 deletions Polyline.java
    Original file line number Diff line number Diff line change
    @@ -5,35 +5,6 @@

    public final class Polyline {

    record Point(int x, int y) {

    private Point offset(Point other) {
    return new Point(x - other.x(), y - other.y());
    }

    private String encode() {
    return encode0(x) + encode0(y);
    }

    private String encode0(int v) {
    var num = v << 1;
    if (v < 0) {
    num = ~num;
    }

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

    num += 63;
    result.append((char) (num));
    return result.toString();
    }
    }

    private final List<Point> points = new ArrayList<>();

    private final int scale;
    @@ -48,19 +19,22 @@ private String encode0(int v) {
    }

    void add(double x, double y) {
    this.points.add(new Point((int) Math.floor(x * scale), (int) Math.floor(y * scale)));
    this.points.add(new Point((int) Math.floor(x * this.scale), (int) Math.floor(y * this.scale)));
    }

    @Override
    public String toString() {
    if (points.isEmpty()) {
    if (this.points.isEmpty()) {
    return "";
    }
    var initial = points.getFirst().encode();
    if (points.size() == 1) {
    var initial = this.points.getFirst().encode();
    if (this.points.size() == 1) {
    return initial;
    }
    var remainder = points.stream().gather(Gatherers.windowSliding(2)).map(pair -> pair.getLast().offset(pair.getFirst()).encode()).collect(Collectors.joining());
    var remainder = this.points.stream()
    .gather(Gatherers.windowSliding(2))
    .map(pair -> pair.getLast().offset(pair.getFirst()).encode())
    .collect(Collectors.joining());
    return initial + remainder;
    }

    @@ -70,6 +44,35 @@ public static void main(String... a) {
    polyline.add(38.5, -120.2);
    polyline.add(40.7, -120.95);
    polyline.add(43.252, -126.453);
    System.out.println(polyline);
    System.err.println(polyline);
    }

    record Point(int x, int y) {

    private Point offset(Point other) {
    return new Point(this.x - other.x(), this.y - other.y());
    }

    private String encode() {
    return encode0(this.x) + encode0(this.y);
    }

    private String encode0(int v) {
    var num = v << 1;
    if (v < 0) {
    num = ~num;
    }

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

    num += 63;
    result.append((char) (num));
    return result.toString();
    }
    }
    }
    }
  2. michael-simons revised this gist Apr 13, 2025. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Polyline.java
    Original file line number Diff line number Diff line change
    @@ -38,7 +38,7 @@ private String encode0(int v) {

    private final int scale;

    // Valhalla uses a scale of 6, Google is stupid and uses 5.
    // Valhalla uses a scale of 6, Google is stupid and uses 5.
    Polyline() {
    this(6);
    }
  3. michael-simons created this gist Apr 13, 2025.
    75 changes: 75 additions & 0 deletions Polyline.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,75 @@
    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Collectors;
    import java.util.stream.Gatherers;

    public final class Polyline {

    record Point(int x, int y) {

    private Point offset(Point other) {
    return new Point(x - other.x(), y - other.y());
    }

    private String encode() {
    return encode0(x) + encode0(y);
    }

    private String encode0(int v) {
    var num = v << 1;
    if (v < 0) {
    num = ~num;
    }

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

    num += 63;
    result.append((char) (num));
    return result.toString();
    }
    }

    private final List<Point> points = new ArrayList<>();

    private final int scale;

    // Valhalla uses a scale of 6, Google is stupid and uses 5.
    Polyline() {
    this(6);
    }

    Polyline(int scale) {
    this.scale = (int) Math.pow(10, scale);
    }

    void add(double x, double y) {
    this.points.add(new Point((int) Math.floor(x * scale), (int) Math.floor(y * scale)));
    }

    @Override
    public String toString() {
    if (points.isEmpty()) {
    return "";
    }
    var initial = points.getFirst().encode();
    if (points.size() == 1) {
    return initial;
    }
    var remainder = points.stream().gather(Gatherers.windowSliding(2)).map(pair -> pair.getLast().offset(pair.getFirst()).encode()).collect(Collectors.joining());
    return initial + remainder;
    }

    public static void main(String... a) {

    var polyline = new Polyline(5);
    polyline.add(38.5, -120.2);
    polyline.add(40.7, -120.95);
    polyline.add(43.252, -126.453);
    System.out.println(polyline);
    }
    }