Mercurial > dive4elements > river
view artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadData.java @ 8128:65a938e4d92f
Fix compilation of last commit
I think it was intended this way.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 25 Aug 2014 17:28:18 +0200 |
parents | 8c5eb9edc3f3 |
children | bbad52b073a4 |
line wrap: on
line source
/* Copyright (C) 2014 by Bundesanstalt für Gewässerkunde * Software engineering by Intevation GmbH * * This file is Free Software under the GNU AGPL (>=v3) * and comes with ABSOLUTELY NO WARRANTY! Check out the * documentation coming with Dive4Elements River for details. */ package org.dive4elements.river.artifacts.model.minfo; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.TreeMap; import java.util.TreeSet; import org.dive4elements.river.utils.EpsilonComparator; public class SedimentLoadData implements Serializable { public static final int GF_UNKNOWN = -1; public static final int GF_COARSE = 0; public static final int GF_FINE_MIDDLE = 1; public static final int GF_SAND = 2; public static final int GF_SUSP_SAND = 3; public static final int GF_SUSP_SAND_BED = 4; public static final int GF_SUSP_SEDIMENT = 5; public static final int GF_TOTAL = 6; public static final int GF_BED_LOAD = 7; public static final int GF_SUSPENDED_LOAD = 8; public static final int GF_MAX = 8; public static final int [] MEASUREMENT_STATION_GF = { /* GF_COARSE */ Station.BED_LOAD, /* GF_FINE_MIDDLE */ Station.BED_LOAD, /* GF_SAND */ Station.BED_LOAD, /* GF_SUSP_SAND */ Station.BED_LOAD, /* GF_SUSP_SAND_BED */ Station.BED_LOAD, /* GF_SUSP_SEDIMENT */ Station.SUSPENDED, /* GF_TOTAL */ Station.BED_LOAD|Station.SUSPENDED, /* GF_BED_LOAD */ Station.BED_LOAD, /* GF_SUSPENDED_LOAD */ Station.BED_LOAD }; public static final int measurementStationType(int grainFraction) { return grainFraction < 0 || grainFraction >= MEASUREMENT_STATION_GF.length ? Station.UNKNOWN : MEASUREMENT_STATION_GF[grainFraction]; } public static final int grainFractionIndex(String name) { if ("coarse".equals(name)) return GF_COARSE; if ("fine_middle".equals(name)) return GF_FINE_MIDDLE; if ("sand".equals(name)) return GF_SAND; if ("susp_sand".equals(name)) return GF_SUSP_SAND; if ("susp_sand_bed".equals(name)) return GF_SUSP_SAND_BED; if ("suspended_sediment".equals(name)) return GF_SUSP_SEDIMENT; if ("total".equals(name)) return GF_TOTAL; if ("bed_load".equals(name)) return GF_BED_LOAD; if ("suspended_load".equals(name)) return GF_SUSPENDED_LOAD; return GF_UNKNOWN; } public interface Visitor { void visit(Station station); } public static class Value implements Serializable { public interface Filter { boolean accept(Value value); } public interface Visitor { void visit(Value value); } private double value; private Load load; public Value() { } public Value(Load load, double value) { this.load = load; this.value = value; } public double getValue() { return value; } public Load getLoad() { return load; } } // class Value public static class Load implements Serializable { private int id; private int kind; private String description; private Date startTime; private Date stopTime; public Load() { } public Load( int id, int kind, String description, Date startTime, Date stopTime ) { this.id = id; this.kind = kind; this.description = description; this.startTime = startTime; this.stopTime = stopTime; } public int getId() { return id; } public int getKind() { return kind; } public String getDescription() { return description; } public Date getStartTime() { return startTime; } public Date getStopTime() { return stopTime; } public boolean isEpoch() { return startTime != null && stopTime != null; } } // class SedimentLoad public static class Station implements Serializable { public static final int UNKNOWN = 0; public static final int BED_LOAD = 1; public static final int SUSPENDED = 2; private double station; private int type; private List<List<Value>> grainFractions; private Station next; private Station prev; public Station() { this(BED_LOAD, 0.0); } public Station(int type, double station) { grainFractions = new ArrayList<List<Value>>(GF_MAX+1); for (int i = 0; i < GF_MAX+1; ++i) { grainFractions.add(null); } this.type = type; this.station = station; } public void allLoads(Collection<Load> loads) { for (List<Value> values: grainFractions) { if (values != null) { for (Value value: values) { loads.add(value.getLoad()); } } } } public double getStation() { return station; } public int getType() { return type; } public boolean isType(int type) { return (this.type & type) != 0; } public void setNext(Station next) { this.next = next; } public Station getNext() { return next; } public void setPrev(Station prev) { this.prev = next; } public Station getPrev() { return prev; } public Station getNext(boolean isKMUp) { return isKMUp ? getNext() : getPrev(); } public Station getPrev(boolean isKMUp) { return isKMUp ? getPrev() : getNext(); } public void merge(Station other) { this.type |= other.type; for (int i = 0, N = grainFractions.size(); i < N; ++i) { grainFractions.set(i, mergeValues(grainFractions.get(i), other.grainFractions.get(i))); } } private static final Comparator<Value> ID_CMP = new Comparator<Value>() { @Override public int compare(Value a, Value b) { return a.getLoad().getId() - b.getLoad().getId(); } }; private static List<Value> mergeValues(List<Value> a, List<Value> b) { if (a == null) return b; if (b == null) return a; a.addAll(b); // re-establish id order. Collections.sort(a, ID_CMP); return a; } public Station nextByType(int type, boolean isKMUp) { for (Station curr = this; curr != null; curr = curr.getNext(isKMUp)) { if (curr.isType(type)) { return curr; } } return null; } public Station prevByType(int type, boolean isKMUp) { for (Station curr = this; curr != null; curr = curr.getPrev(isKMUp)) { if (curr.isType(type)) { return curr; } } return null; } public void addValue(int grainFraction, Value value) { List<Value> values = grainFractions.get(grainFraction); if (values == null) { values = new ArrayList<Value>(); grainFractions.set(grainFraction, values); } values.add(value); } public boolean hasGrainFraction(String grainFraction) { return hasGrainFraction(grainFractionIndex(grainFraction)); } public boolean hasGrainFraction(int grainFraction) { List<Value> values = grainFractions.get(grainFraction); return values != null && !values.isEmpty(); } public void filterGrainFraction( int grainFraction, Value.Filter filter, Value.Visitor visitor ) { List<Value> values = grainFractions.get(grainFraction); if (values != null && !values.isEmpty()) { for (Value value: values) { if (filter.accept(value)) { visitor.visit(value); } } } } public List<Value> filterGrainFraction(int grainFraction, Value.Filter filter) { final List<Value> result = new ArrayList<Value>(); filterGrainFraction(grainFraction, filter, new Value.Visitor() { @Override public void visit(Value value) { result.add(value); } }); return result; } public double findValueByLoadId(int id) { for (List<Value> values: grainFractions) { double value = findValueByLoadId(values, id); if (!Double.isNaN(value)) { return value; } } return Double.NaN; } private static final double findValueByLoadId( List<Value> values, int id ) { if (values == null) { return Double.NaN; } // List is ordered by station id -> binary search. int lo = 0, hi = values.size()-1; while (lo <= hi) { int mid = (lo + hi)/2; Value v = values.get(mid); int xid = v.getLoad().getId(); if (xid > id) hi = mid-1; else if (xid < id) lo = mid+1; else return v.getValue(); } return Double.NaN; } } // class Station private Station [] stations; public SedimentLoadData() { } public SedimentLoadData(Collection<Station> stations) { setStations(stations); } public Station[] getStations() { return stations; } public void setStations(Collection<Station> stations) { TreeMap<Double, Station> same = new TreeMap<Double, Station>(EpsilonComparator.CMP); for (Station station: stations) { Double key = station.getStation(); Station st = same.get(key); if (st == null) { same.put(key, station); } else { st.merge(station); } } this.stations = new Station[same.size()]; int i = 0; for (Station station: same.values()) { this.stations[i++] = station; } wireNeighbors(); } private void wireNeighbors() { for (int i = 1; i < stations.length; ++i) { stations[i-1].setNext(stations[i]); stations[i].setPrev(stations[i-1]); } } private void recursiveFindStations( double a, double b, int lo, int hi, Visitor visitor ) { if (lo > hi) { return; } int mid = (lo+hi)/2; Station st = stations[mid]; double station = st.getStation(); if (station < a) { recursiveFindStations(a, b, mid+1, hi, visitor); } else if (station > b) { recursiveFindStations(a, b, lo, mid-1, visitor); } else { recursiveFindStations(a, b, lo, mid-1, visitor); visitor.visit(st); recursiveFindStations(a, b, mid+1, hi, visitor); } } public static final Comparator<Load> LOAD_ID_CMP = new Comparator<Load>() { @Override public int compare(Load a, Load b) { return a.getId() - b.getId(); } }; public Collection<Load> findLoads(double a, double b) { final TreeSet loads = new TreeSet<Load>(LOAD_ID_CMP); findStations(a, b, new Visitor() { @Override public void visit(Station station) { station.allLoads(loads); } }); return loads; } public void findStations(double a, double b, Visitor visitor) { if (a > b) { double t = a; a = b; b = t; } recursiveFindStations(a, b, 0, stations.length-1, visitor); } public List<Station> findStations(double a, double b) { final List<Station> result = new ArrayList<Station>(); findStations(a, b, new Visitor() { @Override public void visit(Station station) { result.add(station); } }); return result; } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :