comparison artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhcalculation/SoilKindKmValueFinder.java @ 8952:1a8f19f3b776

Connection to new database table bed_mobility implemented
author mschaefer
date Mon, 19 Mar 2018 09:12:17 +0100
parents d9dbf0b74bc2
children 45f1ad66560e
comparison
equal deleted inserted replaced
8951:322b0e6298ea 8952:1a8f19f3b776
8 * documentation coming with Dive4Elements River for details. 8 * documentation coming with Dive4Elements River for details.
9 */ 9 */
10 10
11 package org.dive4elements.river.artifacts.sinfo.tkhcalculation; 11 package org.dive4elements.river.artifacts.sinfo.tkhcalculation;
12 12
13 import java.util.ArrayList;
14 import java.util.List; 13 import java.util.List;
14 import java.util.Map.Entry;
15 import java.util.NavigableMap;
16 import java.util.TreeMap;
15 17
16 import org.apache.commons.lang.math.DoubleRange; 18 import org.apache.commons.lang.math.DoubleRange;
17 import org.apache.commons.math.ArgumentOutsideDomainException; 19 import org.apache.commons.math.ArgumentOutsideDomainException;
20 import org.dive4elements.river.backend.SessionHolder;
18 import org.dive4elements.river.model.River; 21 import org.dive4elements.river.model.River;
22 import org.hibernate.SQLQuery;
23 import org.hibernate.Session;
24 import org.hibernate.type.StandardBasicTypes;
19 25
20 import gnu.trove.TDoubleArrayList;
21 26
22 /** 27 /**
23 * @author Matthias Schäfer 28 * @author Matthias Schäfer
24 */ 29 */
25 final class SoilKindKmValueFinder { 30 final class SoilKindKmValueFinder {
26 // /** 31
27 // * Private log to use here. 32 /***** FIELDS *****/
28 // */ 33
29 // private static Logger log = Logger.getLogger(SoilKindKmValueFinder.class); 34 // private static Logger log = Logger.getLogger(SoilKindKmValueFinder.class);
30 35
31 private final TDoubleArrayList kms = new TDoubleArrayList(); 36 /**
37 * Query selecting the bed mobility attribute for a range of stations of a river
38 */
39 private static final String SQL_BED_MOBILITY = "SELECT bmv.station, bmv.moving"
40 + " FROM bed_mobility bm INNER JOIN bed_mobility_values bmv ON bm.id = bmv.bed_mobility_id"
41 + " WHERE (bm.river_id=:river_id) AND (bmv.station BETWEEN (:fromkm-0.0001) AND (:tokm+0.0001))"
42 + " ORDER BY bmv.station ASC";
32 43
33 private final List<SoilKind> values = new ArrayList<>(); 44 private final NavigableMap<Double, SoilKind> kmMobility;
45
46
47 /***** CONSTRUCTORS *****/
48
49 private SoilKindKmValueFinder() {
50 /* only instantiate me via static constructor */
51 this.kmMobility = null;
52 }
53
54 private SoilKindKmValueFinder(final List<Object[]> queryRows) {
55 this.kmMobility = new TreeMap<>();
56 for (int i = 0; i <= queryRows.size() - 1; i++) {
57 this.kmMobility.put(Double.valueOf((double) queryRows.get(i)[0]), (((int) queryRows.get(i)[1]) == 1) ? SoilKind.mobil : SoilKind.starr);
58 }
59 }
60
61 /***** METHODS *****/
34 62
35 /** 63 /**
36 * Loads the range of the river's kms with their soil kind. 64 * Loads the range of the river's kms with their soil kind.
37 * 65 *
38 * @return Whether the load has been successful 66 * @return Whether the load has been successful
39 */ 67 */
40 public static SoilKindKmValueFinder loadValues(final River river, final DoubleRange kmRange) { 68 public static SoilKindKmValueFinder loadValues(final River river, final DoubleRange kmRange) {
41 69 final Session session = SessionHolder.HOLDER.get();
42 final SoilKindKmValueFinder instance = new SoilKindKmValueFinder(); 70 final SQLQuery sqlQuery = session.createSQLQuery(SQL_BED_MOBILITY).addScalar("station", StandardBasicTypes.DOUBLE)
43 71 .addScalar("moving", StandardBasicTypes.INTEGER);
44 // FIXME Echte Daten aus der Datenbank abfragen 72 sqlQuery.setInteger("river_id", river.getId().intValue());
45 instance.addKmKind(0, SoilKind.starr); 73 sqlQuery.setDouble("fromkm", kmRange.getMinimumDouble());
46 instance.addKmKind(15.7, SoilKind.mobil); 74 sqlQuery.setDouble("tokm", kmRange.getMaximumDouble());
47 instance.addKmKind(15.8, SoilKind.mobil); 75 final List<Object[]> rows = sqlQuery.list();
48 instance.addKmKind(15.9, SoilKind.starr); 76 if (rows.size() >= 1)
49 instance.addKmKind(108.7, SoilKind.mobil); 77 return new SoilKindKmValueFinder(rows);
50 instance.addKmKind(108.8, SoilKind.mobil); 78 else
51 instance.addKmKind(108.9, SoilKind.starr); 79 return null;
52 instance.addKmKind(119.1, SoilKind.mobil);
53 instance.addKmKind(119.4, SoilKind.mobil);
54 instance.addKmKind(119.5, SoilKind.starr);
55 instance.addKmKind(128.3, SoilKind.mobil);
56 instance.addKmKind(128.9, SoilKind.mobil);
57 instance.addKmKind(129, SoilKind.starr);
58 instance.addKmKind(133.1, SoilKind.mobil);
59 instance.addKmKind(135.9, SoilKind.mobil);
60 instance.addKmKind(136, SoilKind.starr);
61 instance.addKmKind(136.5, SoilKind.mobil);
62 instance.addKmKind(139.9, SoilKind.mobil);
63 instance.addKmKind(140, SoilKind.starr);
64 instance.addKmKind(140.5, SoilKind.mobil);
65 instance.addKmKind(165, SoilKind.mobil);
66 instance.addKmKind(165.1, SoilKind.starr);
67 instance.addKmKind(165.9, SoilKind.mobil);
68 instance.addKmKind(180.8, SoilKind.mobil);
69 instance.addKmKind(180.9, SoilKind.starr);
70 instance.addKmKind(182, SoilKind.mobil);
71 instance.addKmKind(221.3, SoilKind.mobil);
72
73 return instance;
74 }
75
76 private SoilKindKmValueFinder() {
77 /* only instantiate me via static constructor */
78 } 80 }
79 81
80 /***** METHODS *****/ 82 /***** METHODS *****/
81 83
82 /** 84 /**
83 * Searches a km with its soil kind 85 * Searches a km with its soil kind
84 */ 86 */
85 public SoilKind findSoilKind(final double km) throws ArgumentOutsideDomainException { 87 public SoilKind findSoilKind(final double km) throws ArgumentOutsideDomainException {
86 if ((this.kms == null) || (this.kms.size() == 0)) 88 if ((this.kmMobility == null) || this.kmMobility.isEmpty())
87 throw new ArgumentOutsideDomainException(km, Double.NaN, Double.NaN); 89 throw new ArgumentOutsideDomainException(km, Double.NaN, Double.NaN);
88 90 else if (this.kmMobility.containsKey(Double.valueOf(km)))
89 // TODO: Voraussetzung für die binäre suche ist, dass nach km sortiert ist. 91 return this.kmMobility.get(Double.valueOf(km));
90 // In diesem Fall könnte man ggf. auch gleich eine bessere Datenklasse benutzen, z.B. eine TreeMap<Double, SoilKind> 92 else {
91 // (also station -> art), und deren funktionen zum finden verwenden: 93 // FIXME: Assert minimum distance between neighbouring stations and candidate km?
92 // final double station = 0.0; 94 final Entry<Double, SoilKind> streamUp = this.kmMobility.floorEntry(Double.valueOf(km));
93 // final NavigableMap<Double, SoilKind> data = new TreeMap<>(); 95 if (streamUp == null)
94 // data.ceilingEntry(station);
95 // data.floorEntry(station);
96
97 int i = this.kms.binarySearch(km);
98 if (i >= 0) {
99 // Exact km match
100 return this.values.get(i);
101 } else {
102 // Out of range or within km interval
103 if (i < 0)
104 i = -i - 1;
105 if ((i <= 0) || (i >= this.kms.size()))
106 throw new ArgumentOutsideDomainException(km, Double.NaN, Double.NaN); 96 throw new ArgumentOutsideDomainException(km, Double.NaN, Double.NaN);
107 if (km <= ((this.kms.get(i - 1) + this.kms.get(i)) / 2)) 97 else {
108 return this.values.get(i - 1); 98 // Return the soil kind of the neighbouring station with the shorter distance to the candidate.
109 else 99 final Entry<Double, SoilKind> streamDown = this.kmMobility.ceilingEntry(Double.valueOf(km));
110 return this.values.get(i); 100 if (streamDown == null)
101 return streamUp.getValue();
102 else if ((streamUp.getKey().doubleValue() + streamDown.getKey().doubleValue()) / 2 <= km)
103 return streamUp.getValue();
104 else
105 return streamDown.getValue();
106 }
111 } 107 }
112 } 108 }
113
114 private void addKmKind(final double km, final SoilKind kind) {
115 this.kms.add(km);
116 this.values.add(kind);
117 }
118 } 109 }

http://dive4elements.wald.intevation.org