1   /* Copyright 2002-2022 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.files.ilrs;
18  
19  import static org.junit.Assert.assertEquals;
20  import static org.junit.Assert.assertTrue;
21  import static org.junit.Assert.fail;
22  
23  import java.io.BufferedReader;
24  import java.io.BufferedWriter;
25  import java.io.File;
26  import java.io.FileInputStream;
27  import java.io.IOException;
28  import java.io.InputStreamReader;
29  import java.io.Reader;
30  import java.net.URISyntaxException;
31  import java.nio.charset.StandardCharsets;
32  import java.util.ArrayList;
33  import java.util.List;
34  
35  import org.hipparchus.geometry.euclidean.threed.Vector3D;
36  import org.junit.Assert;
37  import org.junit.Before;
38  import org.junit.Rule;
39  import org.junit.Test;
40  import org.junit.rules.TemporaryFolder;
41  import org.orekit.Utils;
42  import org.orekit.data.DataSource;
43  import org.orekit.errors.OrekitIllegalArgumentException;
44  import org.orekit.errors.OrekitMessages;
45  import org.orekit.files.ilrs.CPF.CPFCoordinate;
46  import org.orekit.files.ilrs.CPF.CPFEphemeris;
47  import org.orekit.time.AbsoluteDate;
48  import org.orekit.time.DateComponents;
49  import org.orekit.time.TimeScalesFactory;
50  
51  public class CPFWriterTest {
52  
53      @Rule
54      public TemporaryFolder tempFolder = new TemporaryFolder();
55  
56      @Before
57      public void setUp() throws Exception {
58          Utils.setDataRoot("regular-data");
59      }
60  
61      @Test
62      public void testWriteJason3Version2() throws IOException, URISyntaxException {
63  
64          // Simple test for version 2.0, only contains position entries
65          final String ex = "/ilrs/jason3_cpf_180613_16401.cne";
66          final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
67          final CPF file = new CPFParser().parse(source);
68  
69          String tempCPFFilePath = tempFolder.newFile("TestWriteCPF.cpf").toString();
70          CPFWriter writer = new CPFWriter(file.getHeader(), TimeScalesFactory.getUTC());
71          writer.write(tempCPFFilePath, file);
72  
73          final CPF generatedCpfFile = new CPFParser().parse(new DataSource(tempCPFFilePath));
74          compareCpfFiles(file, generatedCpfFile);
75  
76      }
77  
78      @Test
79      public void testWriteLageos1Version2() throws IOException, URISyntaxException {
80  
81          // Simple test for version 2.0, only contains position entries
82          final String ex = "/ilrs/lageos1_cpf_180613_16401.hts";
83          final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
84          final CPF file = new CPFParser().parse(source);
85  
86          String tempCPFFilePath = tempFolder.newFile("TestWriteCPF.cpf").toString();
87          CPFWriter writer = new CPFWriter(file.getHeader(), TimeScalesFactory.getUTC());
88          writer.write(tempCPFFilePath, file);
89  
90          final CPF generatedCpfFile = new CPFParser().parse(new DataSource(tempCPFFilePath));
91          compareCpfFiles(file, generatedCpfFile);
92  
93      }
94  
95      @Test
96      public void testWriteGalileoVersion1() throws IOException, URISyntaxException {
97  
98          // Simple test for version 1.0, only contains position entries
99          final String ex = "/ilrs/galileo212_cpf_180613_6641.esa";
100         final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
101         final CPF file = new CPFParser().parse(source);
102 
103         String tempCPFFilePath = tempFolder.newFile("TestWriteCPF.cpf").toString();
104         CPFWriter writer = new CPFWriter(file.getHeader(), TimeScalesFactory.getUTC());
105         writer.write(tempCPFFilePath, file);
106 
107         final CPF generatedCpfFile = new CPFParser().parse(new DataSource(tempCPFFilePath));
108         compareCpfFiles(file, generatedCpfFile);
109 
110     }
111 
112     @Test
113     public void testIssue868v1() throws IOException, URISyntaxException {
114 
115         // Load
116         final String ex = "/ilrs/galileo212_cpf_180613_6641.esa";
117         final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
118         final CPF file = new CPFParser().parse(source);
119 
120         // Write
121         String tempCPFFilePath = tempFolder.newFile("TestWriteCPF.cpf").toString();
122         CPFWriter writer = new CPFWriter(file.getHeader(), TimeScalesFactory.getUTC());
123         writer.write(tempCPFFilePath, file);
124 
125         // Verify
126         final DataSource tempSource = new DataSource(tempCPFFilePath);
127         try (Reader reader = tempSource.getOpener().openReaderOnce();
128                         BufferedReader br = (reader == null) ? null : new BufferedReader(reader)) {
129             // The testWriteGalileoVersion1() already verify the content of the file
130             // The objective here is just the verify the fix of issue #868
131             final String line1 = br.readLine();
132             Assert.assertEquals(56, line1.length());
133             final String line2 = br.readLine();
134             Assert.assertEquals(82, line2.length());
135         }
136     }
137 
138     @Test
139     public void testIssue868v2() throws IOException, URISyntaxException {
140 
141         // Load
142         final String ex = "/ilrs/lageos1_cpf_180613_16401.hts";
143         final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
144         final CPF file = new CPFParser().parse(source);
145 
146         // Write
147         String tempCPFFilePath = tempFolder.newFile("TestWriteCPF.cpf").toString();
148         CPFWriter writer = new CPFWriter(file.getHeader(), TimeScalesFactory.getUTC());
149         writer.write(tempCPFFilePath, file);
150 
151         // Verify
152         final DataSource tempSource = new DataSource(tempCPFFilePath);
153         try (Reader reader = tempSource.getOpener().openReaderOnce();
154                         BufferedReader br = (reader == null) ? null : new BufferedReader(reader)) {
155             // The testWriteLageos1Version2() already verify the content of the file
156             // The objective here is just the verify the fix of issue #868
157             final String line1 = br.readLine();
158             Assert.assertEquals(58, line1.length());
159             final String line2 = br.readLine();
160             Assert.assertEquals(85, line2.length());
161         }
162     }
163 
164     @Test
165     public void testNullFile() throws IOException {
166         final String    ex      = "/ilrs/lageos1_cpf_180613_16401.hts";
167         final DataSource source  = new DataSource(ex, () ->  getClass().getResourceAsStream(ex));
168         final CPF   cpfFile = new CPFParser().parse(source);
169         final CPFWriter writer  = new CPFWriter(cpfFile.getHeader(), TimeScalesFactory.getUTC());
170         try {
171             writer.write((BufferedWriter) null, cpfFile);
172             fail("an exception should have been thrown");
173         } catch (OrekitIllegalArgumentException oiae) {
174             assertEquals(OrekitMessages.NULL_ARGUMENT, oiae.getSpecifier());
175             assertEquals("writer", oiae.getParts()[0]);
176         }
177     }
178 
179     @Test
180     public void testNullEphemeris() throws IOException {
181         File tempCPFFile = tempFolder.newFile("TestNullEphemeris.cpf");
182         CPFWriter writer = new CPFWriter(null, TimeScalesFactory.getUTC());
183         writer.write(tempCPFFile.toString(), null);
184         assertTrue(tempCPFFile.exists());
185         try (FileInputStream   fis = new FileInputStream(tempCPFFile);
186              InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
187              BufferedReader    br  = new BufferedReader(isr)) {
188             int count = 0;
189             for (String line = br.readLine(); line != null; line = br.readLine()) {
190                 ++count;
191             }
192             assertEquals(0, count);
193         }
194     }
195 
196     /** Test for issue #844 (https://gitlab.orekit.org/orekit/orekit/-/issues/844). */
197     @Test
198     public void testIssue844() throws IOException {
199 
200         // Create header
201         final CPFHeader header = new CPFHeader();
202         header.setSource("orekit");
203         header.setStep(300);
204         header.setStartEpoch(AbsoluteDate.J2000_EPOCH.shiftedBy(-300.0));
205         header.setEndEpoch(AbsoluteDate.J2000_EPOCH.shiftedBy(300.0));
206         header.setIlrsSatelliteId("070595");
207         header.setName("tag");
208         header.setNoradId("0705");
209         header.setProductionEpoch(new DateComponents(2000, 1, 2));
210         header.setProductionHour(12);
211         header.setSequenceNumber(0705);
212         header.setSic("0705");
213         final CPFHeader headerV1 = header;
214         headerV1.setVersion(1);
215 
216         // Writer
217         final CPFWriter writer = new CPFWriter(headerV1, TimeScalesFactory.getUTC());
218 
219         // Create an empty CPF file
220         final CPF cpf = new CPF();
221 
222         // Fast check
223         assertEquals(0, cpf.getSatellites().size());
224 
225         // Add coordinates
226         final int leap = 0;
227         cpf.addSatelliteCoordinate(header.getIlrsSatelliteId(), new CPFCoordinate(AbsoluteDate.J2000_EPOCH.shiftedBy(-300.0), Vector3D.PLUS_I, leap));
228         cpf.addSatelliteCoordinate(header.getIlrsSatelliteId(), new CPFCoordinate(AbsoluteDate.J2000_EPOCH,                   Vector3D.PLUS_J, leap));
229         cpf.addSatelliteCoordinate(header.getIlrsSatelliteId(), new CPFCoordinate(AbsoluteDate.J2000_EPOCH.shiftedBy(300.0),  Vector3D.PLUS_K, leap));
230 
231         // Write the file
232         String tempCPFFilePath = tempFolder.newFile("TestWriteCPF.cpf").toString();
233         writer.write(tempCPFFilePath, cpf);
234 
235         // Verify
236         final List<CPFCoordinate> coordinatesInFile = cpf.getSatellites().get(header.getIlrsSatelliteId()).getCoordinates();
237         assertEquals(0.0, Vector3D.PLUS_I.distance(coordinatesInFile.get(0).getPosition()), 1.0e-10);
238         assertEquals(0.0, Vector3D.PLUS_J.distance(coordinatesInFile.get(1).getPosition()), 1.0e-10);
239         assertEquals(0.0, Vector3D.PLUS_K.distance(coordinatesInFile.get(2).getPosition()), 1.0e-10);
240 
241     }
242 
243     /** Test for issue #844 (https://gitlab.orekit.org/orekit/orekit/-/issues/844). */
244     @Test
245     public void testIssue844Bis() throws IOException {
246 
247         // Create header
248         final CPFHeader header = new CPFHeader();
249         header.setSource("orekit");
250         header.setStep(300);
251         header.setStartEpoch(AbsoluteDate.J2000_EPOCH.shiftedBy(-300.0));
252         header.setEndEpoch(AbsoluteDate.J2000_EPOCH.shiftedBy(300.0));
253         header.setIlrsSatelliteId("070595");
254         header.setName("tag");
255         header.setNoradId("0705");
256         header.setProductionEpoch(new DateComponents(2000, 1, 2));
257         header.setProductionHour(12);
258         header.setSequenceNumber(0705);
259         header.setSic("0705");
260         final CPFHeader headerV1 = header;
261         headerV1.setVersion(1);
262 
263         // Writer
264         final CPFWriter writer = new CPFWriter(headerV1, TimeScalesFactory.getUTC());
265 
266         // Create an empty CPF file
267         final CPF cpf = new CPF();
268 
269         // Fast check
270         assertEquals(0, cpf.getSatellites().size());
271 
272         // Add coordinates
273         final int leap = 0;
274         final List<CPFCoordinate> coordinates = new ArrayList<>();
275         coordinates.add(new CPFCoordinate(AbsoluteDate.J2000_EPOCH.shiftedBy(-300.0), Vector3D.PLUS_I, leap));
276         coordinates.add(new CPFCoordinate(AbsoluteDate.J2000_EPOCH,                   Vector3D.PLUS_J, leap));
277         coordinates.add(new CPFCoordinate(AbsoluteDate.J2000_EPOCH.shiftedBy(300.0),  Vector3D.PLUS_K, leap));
278         cpf.addSatelliteCoordinates(header.getIlrsSatelliteId(), coordinates);
279 
280         // Write the file
281         String tempCPFFilePath = tempFolder.newFile("TestWriteCPF.cpf").toString();
282         writer.write(tempCPFFilePath, cpf);
283 
284         // Verify
285         final List<CPFCoordinate> coordinatesInFile = cpf.getSatellites().get(header.getIlrsSatelliteId()).getCoordinates();
286         assertEquals(0.0, Vector3D.PLUS_I.distance(coordinatesInFile.get(0).getPosition()), 1.0e-10);
287         assertEquals(0.0, Vector3D.PLUS_J.distance(coordinatesInFile.get(1).getPosition()), 1.0e-10);
288         assertEquals(0.0, Vector3D.PLUS_K.distance(coordinatesInFile.get(2).getPosition()), 1.0e-10);
289 
290     }
291 
292     @Test
293     @Deprecated
294     public void testDefaultId() throws IOException {
295 
296         // Initialize
297         final CPF cpf = new CPF();
298 
299         // Fast check
300         assertEquals(0, cpf.getSatellites().size());
301 
302         // Add coordinates
303         final int leap = 0;
304         cpf.addSatelliteCoordinate(new CPFCoordinate(AbsoluteDate.J2000_EPOCH, Vector3D.PLUS_I, leap));
305 
306         // Verify
307         assertEquals(1, cpf.getSatellites().size());
308 
309     }
310 
311     @Test
312     @Deprecated
313     public void testOldConstructor() throws IOException {
314 
315         // Initialize
316         // Create an empty CPF file
317         final CPF cpf = new CPF();
318         final CPFEphemeris ephemeris = cpf.new CPFEphemeris();
319 
320         // Fast check
321         assertEquals(0, ephemeris.getCoordinates().size());
322         assertEquals(CPF.DEFAULT_ID, ephemeris.getId());
323 
324     }
325 
326     public static void compareCpfFiles(CPF file1, CPF file2) {
327 
328         // Header
329         final CPFHeader header1 = file1.getHeader();
330         final CPFHeader header2 = file2.getHeader();
331         compareCpfHeader(header1, header2);
332 
333         // Ephemeris
334         final CPFEphemeris eph1 = file1.getSatellites().get(header1.getIlrsSatelliteId());
335         final CPFEphemeris eph2 = file2.getSatellites().get(header2.getIlrsSatelliteId());
336         Assert.assertEquals(eph1.getId(), eph2.getId());
337         Assert.assertEquals(eph1.getStart(), eph2.getStart());
338         Assert.assertEquals(eph1.getStop(), eph2.getStop());
339 
340         // Coordinates
341         final List<CPFCoordinate> coord1 = eph1.getCoordinates();
342         final List<CPFCoordinate> coord2 = eph2.getCoordinates();
343         Assert.assertEquals(coord1.size(), coord1.size());
344         verifyEphemerisLine(coord1.get(0), coord2.get(0));
345         verifyEphemerisLine(coord1.get(1), coord2.get(1));
346         verifyEphemerisLine(coord1.get(100), coord2.get(100));
347         verifyEphemerisLine(coord1.get(coord1.size() - 1), coord2.get(coord2.size() - 1));
348 
349     }
350 
351     public static void compareCpfHeader(CPFHeader header1, CPFHeader header2) {
352         Assert.assertEquals(header1.getFormat(), header2.getFormat());
353         Assert.assertEquals(header1.getVersion(), header2.getVersion());
354         Assert.assertEquals(header1.getSource(), header2.getSource());
355         Assert.assertEquals(header1.getProductionEpoch().getYear(), header2.getProductionEpoch().getYear());
356         Assert.assertEquals(header1.getName(), header2.getName());
357         Assert.assertEquals(header1.getIlrsSatelliteId(), header2.getIlrsSatelliteId());
358         Assert.assertEquals(header1.getSic(), header2.getSic());
359         Assert.assertEquals(0.0, header1.getStartEpoch().durationFrom(header2.getStartEpoch()), 1.0e-15);
360         Assert.assertEquals(0.0, header1.getEndEpoch().durationFrom(header2.getEndEpoch()), 1.0e-15);
361     }
362 
363     public static void verifyEphemerisLine(CPFCoordinate coord1, CPFCoordinate coord2) {
364         Assert.assertEquals(0.0, coord1.getDate().durationFrom(coord2.getDate()), 1.0e-10);
365         Assert.assertEquals(0.0, coord1.getPosition().distance(coord2.getPosition()), 1.0e-10);
366     }
367 
368 }