Mercurial > dive4elements > river
diff flys-backend/src/main/java/de/intevation/flys/model/River.java @ 3820:8a75cf0841b1 pre2.7-2012-03-16
merged flys-backend/pre2.7-2012-03-16
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:59 +0200 |
parents | 385170ff7b34 |
children | 42db09d101f3 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-backend/src/main/java/de/intevation/flys/model/River.java Fri Sep 28 12:14:59 2012 +0200 @@ -0,0 +1,292 @@ +package de.intevation.flys.model; + +import java.io.Serializable; + +import java.math.BigDecimal; +import java.math.MathContext; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.GeneratedValue; +import javax.persistence.Column; +import javax.persistence.SequenceGenerator; +import javax.persistence.OneToMany; +import javax.persistence.OneToOne; +import javax.persistence.JoinColumn; +import javax.persistence.GenerationType; + +import java.util.List; +import java.util.Comparator; +import java.util.Map; +import java.util.TreeMap; + +import org.hibernate.Session; +import org.hibernate.Query; + +import de.intevation.flys.backend.SessionHolder; + + +@Entity +@Table(name = "rivers") +public class River +implements Serializable +{ + public static final MathContext PRECISION = new MathContext(6); + + public static final double EPSILON = 1e-5; + + public static final Comparator KM_CMP = new Comparator<Double>() { + @Override + public int compare(Double a, Double b) { + double diff = a - b; + if (diff < -EPSILON) return -1; + if (diff > EPSILON) return +1; + return 0; + } + }; + + private Integer id; + + private String name; + + private boolean kmUp; + + private List<Gauge> gauges; + + private Unit wstUnit; + + @Id + @SequenceGenerator( + name = "SEQUENCE_RIVERS_ID_SEQ", + sequenceName = "RIVERS_ID_SEQ", + allocationSize = 1) + @GeneratedValue( + strategy = GenerationType.SEQUENCE, + generator = "SEQUENCE_RIVERS_ID_SEQ") + @Column(name = "id") + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + @Column(name = "name") + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Column(name = "km_up") + public boolean getKmUp() { + return kmUp; + } + + public void setKmUp(boolean kmUp) { + this.kmUp = kmUp; + } + + public River() { + } + + public River(String name, Unit wstUnit) { + this.name = name; + this.wstUnit = wstUnit; + } + + @OneToMany + @JoinColumn(name="river_id") + public List<Gauge> getGauges() { + return gauges; + } + + public void setGauges(List<Gauge> gauges) { + this.gauges = gauges; + } + + + @OneToOne + @JoinColumn(name = "wst_unit_id" ) + public Unit getWstUnit() { + return wstUnit; + } + + public void setWstUnit(Unit wstUnit) { + this.wstUnit = wstUnit; + } + + + + public String toString() { + return name != null ? name : ""; + } + + + /** + * This method returns the gauges that intersect with <i>a</i> and + * <i>b</i>, + * + * @param a A start point. + * @param b An end point. + * + * @return the intersecting gauges. + */ + public List<Gauge> determineGauges(double a, double b) { + Session session = SessionHolder.HOLDER.get(); + + if (a > b) { double t = a; a = b; b = t; } + + Query query = session.createQuery( + "from Gauge where river=:river " + + "and not (range.a > :b or range.b < :a) order by a"); + query.setParameter("river", this); + query.setParameter("a", new BigDecimal(a, PRECISION)); + query.setParameter("b", new BigDecimal(b, PRECISION)); + + return query.list(); + } + + public Gauge maxOverlap(double a, double b) { + List<Gauge> gauges = determineGauges(a, b); + if (gauges == null) { + return null; + } + + if (a > b) { double t = a; a = b; b = t; } + + double max = -Double.MAX_VALUE; + + Gauge result = null; + + for (Gauge gauge: gauges) { + Range r = gauge.getRange(); + double c = r.getA().doubleValue(); + double d = r.getB().doubleValue(); + + double start = c >= a ? c : a; + double stop = d <= b ? d : b; + + double length = stop - start; + + if (length > max) { + max = length; + result = gauge; + } + } + + return result; + } + + public Gauge determineGaugeByName(String name) { + Session session = SessionHolder.HOLDER.get(); + Query query = session.createQuery( + "from Gauge where river=:river and name=:name"); + query.setParameter("river", this); + query.setParameter("name", name); + List<Gauge> gauges = query.list(); + return gauges.isEmpty() ? null : gauges.get(0); + } + + public Gauge determineGaugeByPosition(double p) { + Session session = SessionHolder.HOLDER.get(); + Query query = session.createQuery( + "from Gauge g where river=:river " + + "and :p between g.range.a and g.range.b"); + query.setParameter("river", this); + query.setParameter("p", new BigDecimal(p, PRECISION)); + List<Gauge> gauges = query.list(); + return gauges.isEmpty() ? null : gauges.get(0); + } + + public Gauge determineGaugeByStation(double a, double b) { + + if (a > b) { double t = a; a = b; b = t; } + + Session session = SessionHolder.HOLDER.get(); + + Query query = session.createQuery( + "from Gauge where river.id=:river " + + "and station between :a and :b"); + query.setParameter("river", getId()); + query.setParameter("a", new BigDecimal(a)); + query.setParameter("b", new BigDecimal(b)); + + List<Gauge> gauges = query.list(); + return gauges.isEmpty() ? null : gauges.get(0); + } + + + /** + * This method returns the first gauge that is intersected by <i>a</i> and + * <i>b</i>, + * + * @param a A start point. + * @param b An end point. + * + * @return the first intersecting gauge. + */ + public Gauge determineGauge(double a, double b) { + List<Gauge> gauges = determineGauges(a, b); + + int idx = a < b ? 0 : gauges.size() - 1; + + return gauges.isEmpty() ? null : gauges.get(idx); + } + + /** + * Returns the min and max distance of this river. The first position in the + * resulting array contains the min distance, the second position the max + * distance. + * + * @return the min and max distance of this river. + */ + public double[] determineMinMaxDistance() { + List<Gauge> gauges = getGauges(); + + if (gauges == null || gauges.isEmpty()) { + return null; + } + + double minmax[] = new double[] { Double.MAX_VALUE, Double.MIN_VALUE }; + + for (Gauge g: gauges) { + Range r = g.getRange(); + + if (r == null) { + continue; + } + + double a = r.getA().doubleValue(); + minmax[0] = minmax[0] < a ? minmax[0] : a; + + BigDecimal bigB = r.getB(); + if (bigB != null) { + double b = bigB.doubleValue(); + minmax[1] = minmax[1] > b ? minmax[1] : b; + } + } + + return minmax; + } + + public Map<Double, Double> queryGaugeDatumsKMs() { + List<Gauge> gauges = getGauges(); + Map result = new TreeMap<Double, Double>(KM_CMP); + + for (Gauge gauge: gauges) { + BigDecimal km = gauge.getStation(); + BigDecimal datum = gauge.getDatum(); + if (km != null && datum != null) { + result.put(km.doubleValue(), datum.doubleValue()); + } + } + + return result; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :