1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.models.earth.troposphere.iturp834;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.analysis.interpolation.GridAxis;
21 import org.hipparchus.util.FastMath;
22 import org.orekit.bodies.FieldGeodeticPoint;
23 import org.orekit.bodies.GeodeticPoint;
24 import org.orekit.errors.OrekitException;
25 import org.orekit.errors.OrekitMessages;
26 import org.orekit.utils.units.Unit;
27
28 import java.io.BufferedReader;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.io.InputStreamReader;
32 import java.nio.charset.StandardCharsets;
33 import java.util.regex.Pattern;
34
35
36
37
38
39 abstract class AbstractGrid {
40
41
42 private static final String ITU_R_P_834 = "/assets/org/orekit/ITU-R-P.834/";
43
44
45 private static final Pattern SPLITTER = Pattern.compile("\\s+");
46
47
48 private static final double MIN_LAT = -90.0;
49
50
51 private static final double MAX_LAT = 90.0;
52
53
54 private static final double STEP_LAT = 1.5;
55
56
57 private static final double STEP_LAT_RAD = FastMath.toRadians(STEP_LAT);
58
59
60 private static final double MIN_LON = -180.0;
61
62
63 private static final double MAX_LON = 180.0;
64
65
66 private static final double STEP_LON = 1.5;
67
68
69 private static final double STEP_LON_RAD = FastMath.toRadians(STEP_LON);
70
71
72 private final GridAxis latitudeAxis;
73
74
75 private final GridAxis longitudeAxis;
76
77
78
79 protected AbstractGrid() {
80 latitudeAxis = buildAxis(MIN_LAT, MAX_LAT, STEP_LAT);
81 longitudeAxis = buildAxis(MIN_LON, MAX_LON, STEP_LON);
82 }
83
84
85
86
87 public GridAxis getLatitudeAxis() {
88 return latitudeAxis;
89 }
90
91
92
93
94 public GridAxis getLongitudeAxis() {
95 return longitudeAxis;
96 }
97
98
99
100
101 public double getSizeLat() {
102 return STEP_LAT_RAD;
103 }
104
105
106
107
108 public double getSizeLon() {
109 return STEP_LON_RAD;
110 }
111
112
113
114
115
116
117 protected GridCell getRawCell(final GeodeticPoint location, final double[][] rawData) {
118
119
120 final int southIndex = latitudeAxis.interpolationIndex(location.getLatitude());
121 final double southLatitude = latitudeAxis.node(southIndex);
122 final int westIndex = longitudeAxis.interpolationIndex(location.getLongitude());
123 final double westLongitude = longitudeAxis.node(westIndex);
124
125
126 return new GridCell(location.getLatitude() - southLatitude,
127 location.getLongitude() - westLongitude,
128 STEP_LAT_RAD, STEP_LON_RAD,
129 rawData[southIndex + 1][westIndex],
130 rawData[southIndex][westIndex],
131 rawData[southIndex][westIndex + 1],
132 rawData[southIndex + 1][westIndex + 1]);
133
134 }
135
136
137
138
139
140
141
142 protected <T extends CalculusFieldElement<T>> FieldGridCell<T> getRawCell(final FieldGeodeticPoint<T> location,
143 final double[][] rawData) {
144
145
146 final int southIndex = latitudeAxis.interpolationIndex(location.getLatitude().getReal());
147 final double southLatitude = latitudeAxis.node(southIndex);
148 final int westIndex = longitudeAxis.interpolationIndex(location.getLongitude().getReal());
149 final double westLongitude = longitudeAxis.node(westIndex);
150
151
152 final T zero = location.getAltitude().getField().getZero();
153 return new FieldGridCell<>(location.getLatitude().subtract(southLatitude),
154 location.getLongitude().subtract(westLongitude),
155 STEP_LAT_RAD, STEP_LON_RAD,
156 zero.newInstance(rawData[southIndex + 1][westIndex]),
157 zero.newInstance(rawData[southIndex][westIndex]),
158 zero.newInstance(rawData[southIndex][westIndex + 1]),
159 zero.newInstance(rawData[southIndex + 1][westIndex + 1]));
160
161 }
162
163
164
165
166
167
168 public abstract GridCell getCell(GeodeticPoint location, double secondOfYear);
169
170
171
172
173
174
175
176 public abstract <T extends CalculusFieldElement<T>> FieldGridCell<T> getCell(FieldGeodeticPoint<T> location,
177 T secondOfYear);
178
179
180
181
182
183
184
185 private static GridAxis buildAxis(final double min, final double max, final double step) {
186 final double[] grid = new double[(int) FastMath.rint((max - min) / step) + 1];
187 for (int i = 0; i < grid.length; i++) {
188 grid[i] = FastMath.toRadians(min + i * step);
189 }
190 return new GridAxis(grid, 2);
191 }
192
193
194
195
196
197
198 protected double[][] parse(final Unit unit, final String name) {
199
200
201 final double[][] values = new double[latitudeAxis.size()][longitudeAxis.size()];
202 try (InputStream is = ITURP834WeatherParametersProvider.class.getResourceAsStream(ITU_R_P_834 + name);
203 InputStreamReader isr = is == null ? null : new InputStreamReader(is, StandardCharsets.UTF_8);
204 BufferedReader reader = isr == null ? null : new BufferedReader(isr)) {
205 if (reader == null) {
206
207 throw new OrekitException(OrekitMessages.UNABLE_TO_FIND_FILE, name);
208 }
209 for (int row = 0; row < latitudeAxis.size(); ++row) {
210
211
212 final int latitudeIndex = latitudeAxis.size() - 1 - row;
213
214 final String line = reader.readLine();
215 final String[] fields = SPLITTER.split(line.trim());
216 if (fields.length != longitudeAxis.size()) {
217 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, row + 1, name, line);
218 }
219
220
221 for (int col = 0; col < longitudeAxis.size(); ++col) {
222
223
224
225
226
227
228
229
230
231
232
233
234 final int longitudeIndex = col < 121 ? col + 120 : col - 120;
235 values[latitudeIndex][longitudeIndex] = unit.toSI(Double.parseDouble(fields[col]));
236 }
237
238
239 values[latitudeIndex][0] = values[latitudeIndex][longitudeAxis.size() - 1];
240
241 }
242 } catch (IOException ioe) {
243
244 throw new OrekitException(OrekitMessages.INTERNAL_ERROR, ioe);
245 }
246
247
248 return values;
249
250 }
251
252 }