Mercurial > dive4elements > river
comparison artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/ChannelFinder.java @ 9432:d194c5b24bf8
Added bundu bzws w calculation and longitudinal sections of wspl and depth
author | mschaefer |
---|---|
date | Mon, 20 Aug 2018 09:46:02 +0200 |
parents | |
children | ac41551a8e4d |
comparison
equal
deleted
inserted
replaced
9431:eeea16ea0980 | 9432:d194c5b24bf8 |
---|---|
1 /** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde | |
2 * Software engineering by | |
3 * Björnsen Beratende Ingenieure GmbH | |
4 * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt | |
5 * | |
6 * This file is Free Software under the GNU AGPL (>=v3) | |
7 * and comes with ABSOLUTELY NO WARRANTY! Check out the | |
8 * documentation coming with Dive4Elements River for details. | |
9 */ | |
10 | |
11 package org.dive4elements.river.artifacts.bundu.bezugswst; | |
12 | |
13 import java.util.Map.Entry; | |
14 import java.util.NavigableMap; | |
15 import java.util.TreeMap; | |
16 | |
17 import org.dive4elements.river.artifacts.math.Linear; | |
18 import org.dive4elements.river.artifacts.model.Calculation; | |
19 import org.dive4elements.river.model.River; | |
20 import org.dive4elements.river.model.sinfo.Channel; | |
21 import org.dive4elements.river.model.sinfo.ChannelValue; | |
22 | |
23 /** | |
24 * Provides channel depth and height of a river | |
25 * | |
26 * @author Matthias Schäfer | |
27 */ | |
28 public final class ChannelFinder { | |
29 | |
30 /***** TYPES *****/ | |
31 | |
32 public enum ChannelValueType { | |
33 depth { | |
34 @Override | |
35 public Double getValue(final ChannelValue channelValue) { | |
36 return channelValue.getDepth(); | |
37 } | |
38 }, | |
39 width { | |
40 @Override | |
41 public Double getValue(final ChannelValue channelValue) { | |
42 return channelValue.getWidth(); | |
43 } | |
44 }; | |
45 | |
46 public abstract Double getValue(final ChannelValue channelValue); | |
47 } | |
48 | |
49 /***** FIELDS *****/ | |
50 | |
51 // private static Logger log = Logger.getLogger(ChannelFinder.class); | |
52 | |
53 private static double MAX_DISTANCE_KM = 1; | |
54 | |
55 private final NavigableMap<Double, ChannelValue> values = new TreeMap<>(); | |
56 | |
57 private Calculation problems; | |
58 | |
59 | |
60 /***** CONSTRUCTORS *****/ | |
61 | |
62 private ChannelFinder(final Calculation problems, final Channel channel) { | |
63 | |
64 this.problems = problems; | |
65 | |
66 for (final ChannelValue v : channel.getValues()) { | |
67 this.values.put(v.getStation(), v); | |
68 } | |
69 } | |
70 | |
71 /***** METHODS *****/ | |
72 | |
73 /** | |
74 * Loads the channel values for a river and year | |
75 * | |
76 * @return Whether the load has been successful | |
77 */ | |
78 public static ChannelFinder loadValues(final Calculation problems, final River river, final int year) { | |
79 final Channel channel = Channel.getSeries(river, year); | |
80 if (channel != null) | |
81 return new ChannelFinder(problems, channel); | |
82 | |
83 problems.addProblem("channelfinder.empty"); | |
84 return null; | |
85 } | |
86 | |
87 | |
88 /***** METHODS *****/ | |
89 | |
90 /** | |
91 * Searches the channel depth of a station | |
92 */ | |
93 public double getDepth(final double station) { | |
94 final double value = interpolateChannel(station, ChannelValueType.depth); | |
95 if (Double.isNaN(value)) | |
96 reportProblem(station); | |
97 return value; | |
98 } | |
99 | |
100 /** | |
101 * Searches the channel width of a station | |
102 */ | |
103 public double getWidth(final double station) { | |
104 final double value = interpolateChannel(station, ChannelValueType.width); | |
105 if (Double.isNaN(value)) | |
106 reportProblem(station); | |
107 return value; | |
108 } | |
109 | |
110 /** | |
111 * Searches and interpolates a channel value for a km | |
112 */ | |
113 private double interpolateChannel(final double km, final ChannelValueType type) { | |
114 | |
115 if (this.values.containsKey(km)) { | |
116 final Double value = type.getValue(this.values.get(km)); | |
117 return (value == null) ? Double.NaN : value.doubleValue(); | |
118 } | |
119 | |
120 final Entry<Double, ChannelValue> floorEntry = this.values.floorEntry(km); | |
121 final Entry<Double, ChannelValue> ceilingEntry = this.values.ceilingEntry(km); | |
122 | |
123 if ((floorEntry == null) || (ceilingEntry == null)) | |
124 return Double.NaN; | |
125 | |
126 final double floorKm = floorEntry.getKey().doubleValue(); | |
127 final double ceilKm = ceilingEntry.getKey().doubleValue(); | |
128 | |
129 /* report once if the interpolation distance exceeds 1000m */ | |
130 if ((Math.abs(floorKm - ceilKm) > MAX_DISTANCE_KM) && (this.problems != null)) { | |
131 this.problems.addProblem(km, "linearInterpolator.maxdistance", MAX_DISTANCE_KM * 1000); | |
132 this.problems = null; | |
133 return Double.NaN; | |
134 } | |
135 | |
136 final Double floorHeight = type.getValue(floorEntry.getValue()); | |
137 final Double ceilingHeight = type.getValue(ceilingEntry.getValue()); | |
138 | |
139 if (floorHeight == null || ceilingHeight == null) | |
140 return Double.NaN; | |
141 | |
142 return Linear.linear(km, floorKm, ceilKm, floorHeight, ceilingHeight); | |
143 } | |
144 | |
145 private void reportProblem(final double km) { | |
146 | |
147 if (this.problems == null) | |
148 return; | |
149 | |
150 this.problems.addProblem(km, "channelfinder.missing"); | |
151 | |
152 // report problem only once | |
153 this.problems = null; | |
154 } | |
155 } |