1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.forces.gravity.potential;
18
19 import java.io.BufferedReader;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.InputStreamReader;
23 import java.text.ParseException;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Locale;
27
28 import org.hipparchus.util.FastMath;
29 import org.hipparchus.util.Precision;
30 import org.orekit.errors.OrekitException;
31 import org.orekit.errors.OrekitMessages;
32 import org.orekit.time.DateComponents;
33 import org.orekit.utils.Constants;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public class SHMFormatReader extends PotentialCoefficientsReader {
50
51
52 private static final String GRCOEF = "GRCOEF";
53
54
55 private static final String GRCOF2 = "GRCOF2";
56
57
58 private static final String GRDOTA = "GRDOTA";
59
60
61 private DateComponents referenceDate;
62
63
64 private final List<List<Double>> cDot;
65
66
67 private final List<List<Double>> sDot;
68
69
70
71
72
73 public SHMFormatReader(final String supportedNames, final boolean missingCoefficientsAllowed) {
74 super(supportedNames, missingCoefficientsAllowed);
75 referenceDate = null;
76 cDot = new ArrayList<List<Double>>();
77 sDot = new ArrayList<List<Double>>();
78 }
79
80
81 public void loadData(final InputStream input, final String name)
82 throws IOException, ParseException, OrekitException {
83
84
85 setReadComplete(false);
86 referenceDate = null;
87 cDot.clear();
88 sDot.clear();
89
90 boolean normalized = false;
91 TideSystem tideSystem = TideSystem.UNKNOWN;
92
93 final BufferedReader r = new BufferedReader(new InputStreamReader(input, "UTF-8"));
94 boolean okEarth = false;
95 boolean okSHM = false;
96 boolean okCoeffs = false;
97 double[][] c = null;
98 double[][] s = null;
99 String line = r.readLine();
100 if ((line != null) &&
101 "FIRST ".equals(line.substring(0, 6)) &&
102 "SHM ".equals(line.substring(49, 56))) {
103 for (line = r.readLine(); line != null; line = r.readLine()) {
104 if (line.length() >= 6) {
105 final String[] tab = line.split("\\s+");
106
107
108 if ("EARTH".equals(tab[0])) {
109 setMu(parseDouble(tab[1]));
110 setAe(parseDouble(tab[2]));
111 okEarth = true;
112 }
113
114
115 if ("SHM".equals(tab[0])) {
116
117 final int degree = FastMath.min(getMaxParseDegree(), Integer.parseInt(tab[1]));
118 final int order = FastMath.min(getMaxParseOrder(), degree);
119 c = buildTriangularArray(degree, order, missingCoefficientsAllowed() ? 0.0 : Double.NaN);
120 s = buildTriangularArray(degree, order, missingCoefficientsAllowed() ? 0.0 : Double.NaN);
121 final String lowerCaseLine = line.toLowerCase(Locale.US);
122 normalized = lowerCaseLine.contains("fully normalized");
123 if (lowerCaseLine.contains("exclusive permanent tide")) {
124 tideSystem = TideSystem.TIDE_FREE;
125 } else {
126 tideSystem = TideSystem.UNKNOWN;
127 }
128 okSHM = true;
129 }
130
131
132 if (GRCOEF.equals(line.substring(0, 6)) || GRCOF2.equals(tab[0]) || GRDOTA.equals(tab[0])) {
133 final int i = Integer.parseInt(tab[1]);
134 final int j = Integer.parseInt(tab[2]);
135 if (i < c.length && j < c[i].length) {
136 if (GRDOTA.equals(tab[0])) {
137
138
139 extendListOfLists(cDot, i, j, 0.0);
140 extendListOfLists(sDot, i, j, 0.0);
141 parseCoefficient(tab[3], cDot, i, j, "Cdot", name);
142 parseCoefficient(tab[4], sDot, i, j, "Sdot", name);
143
144
145 final DateComponents#DateComponents">DateComponents localRef = new DateComponents(Integer.parseInt(tab[7].substring(0, 4)),
146 Integer.parseInt(tab[7].substring(4, 6)),
147 Integer.parseInt(tab[7].substring(6, 8)));
148 if (referenceDate == null) {
149
150 referenceDate = localRef;
151 } else if (!referenceDate.equals(localRef)) {
152 throw new OrekitException(OrekitMessages.SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD,
153 referenceDate, localRef, name);
154 }
155
156 } else {
157
158
159 parseCoefficient(tab[3], c, i, j, "C", name);
160 parseCoefficient(tab[4], s, i, j, "S", name);
161 okCoeffs = true;
162
163 }
164 }
165 }
166
167 }
168 }
169 }
170
171 if (missingCoefficientsAllowed() && c.length > 0 && c[0].length > 0) {
172
173 if (Precision.equals(c[0][0], 0.0, 0)) {
174 c[0][0] = 1.0;
175 }
176 }
177
178 if (!(okEarth && okSHM && okCoeffs)) {
179 String loaderName = getClass().getName();
180 loaderName = loaderName.substring(loaderName.lastIndexOf('.') + 1);
181 throw new OrekitException(OrekitMessages.UNEXPECTED_FILE_FORMAT_ERROR_FOR_LOADER,
182 name, loaderName);
183 }
184
185 setRawCoefficients(normalized, c, s, name);
186 setTideSystem(tideSystem);
187 setReadComplete(true);
188
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202
203 public RawSphericalHarmonicsProvider getProvider(final boolean wantNormalized,
204 final int degree, final int order) {
205
206
207 RawSphericalHarmonicsProvider provider = getConstantProvider(wantNormalized, degree, order);
208
209 if (!cDot.isEmpty()) {
210
211
212 final double[][] cArray = toArray(cDot);
213 final double[][] sArray = toArray(sDot);
214 rescale(1.0 / Constants.JULIAN_YEAR, true, cArray, sArray, wantNormalized, cArray, sArray);
215 provider = new SecularTrendSphericalHarmonics(provider, referenceDate, cArray, sArray);
216
217 }
218
219 return provider;
220
221 }
222
223 }