teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.utils; sascha@3013: gernotbelger@9415: import java.io.Serializable; sascha@3013: import java.util.ArrayList; sascha@3013: import java.util.Collections; sascha@3026: import java.util.Iterator; gernotbelger@9415: import java.util.List; sascha@3013: felix@4318: /** km to value, searchable. Tolerance is at 10cm. */ gernotbelger@9415: public class KMIndex implements Serializable, Iterable> { sascha@3013: gernotbelger@9415: private static final long serialVersionUID = 1L; sascha@3013: gernotbelger@9415: private static final double EPSILON = 1e-4; gernotbelger@9415: gernotbelger@9415: public static class Entry implements Serializable, Comparable> { gernotbelger@9415: private static final long serialVersionUID = 1L; gernotbelger@9415: gernotbelger@9415: private final double km; gernotbelger@9415: gernotbelger@9415: private A value; gernotbelger@9415: gernotbelger@9415: public Entry(final double km) { sascha@3013: this.km = km; sascha@3013: } sascha@3013: gernotbelger@9415: public Entry(final double km, final A value) { gernotbelger@9415: this.km = km; sascha@3013: this.value = value; sascha@3013: } sascha@3013: sascha@3013: public double getKm() { gernotbelger@9415: return this.km; sascha@3013: } sascha@3013: sascha@3013: public A getValue() { gernotbelger@9415: return this.value; sascha@3013: } sascha@3013: sascha@3013: @Override gernotbelger@9415: public int compareTo(final Entry other) { gernotbelger@9415: final double diff = this.km - other.km; gernotbelger@9415: if (diff < -EPSILON) gernotbelger@9415: return -1; gernotbelger@9415: if (diff > +EPSILON) gernotbelger@9415: return +1; sascha@3013: return 0; sascha@3013: } sascha@3013: gernotbelger@9415: public boolean epsilonEquals(final double otherKm) { gernotbelger@9415: return Math.abs(this.km - otherKm) < EPSILON; sascha@3013: } gernotbelger@9415: } sascha@3013: gernotbelger@9415: private List> entries; sascha@3013: sascha@3013: public KMIndex() { sascha@3013: this(10); sascha@3013: } sascha@3013: gernotbelger@9415: public KMIndex(final int capacity) { gernotbelger@9415: this.entries = new ArrayList<>(capacity); sascha@3013: } sascha@3013: gernotbelger@9415: public void add(final double km, final A value) { gernotbelger@9415: this.entries.add(new Entry<>(km, value)); sascha@3013: } sascha@3013: sascha@3013: public void sort() { gernotbelger@9415: Collections.sort(this.entries); sascha@3013: } sascha@3013: andre@8613: public int size() { gernotbelger@9415: return this.entries.size(); andre@8613: } andre@8613: gernotbelger@9415: public Entry get(final int idx) { gernotbelger@9415: return this.entries.get(idx); andre@8613: } andre@8613: felix@7215: /** Return the first entry at km. */ gernotbelger@9415: public Entry search(final double km) { gernotbelger@9415: for (final Entry entry : this.entries) { sascha@3013: if (entry.epsilonEquals(km)) { sascha@3013: return entry; sascha@3013: } sascha@3013: } sascha@3013: return null; sascha@3013: } sascha@3013: gernotbelger@9415: public Entry binarySearch(final double km) { gernotbelger@9415: final int index = Collections.binarySearch(this.entries, new Entry(km)); gernotbelger@9415: return index >= 0 ? this.entries.get(index) : null; sascha@3013: } sascha@3026: gernotbelger@9415: @Override sascha@3026: public Iterator> iterator() { gernotbelger@9415: return this.entries.iterator(); sascha@3026: } gernotbelger@9415: }