1 /* Copyright 2002-2025 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 java.io.IOException;
20 import java.util.List;
21
22 import org.orekit.errors.OrekitIllegalArgumentException;
23 import org.orekit.errors.OrekitMessages;
24 import org.orekit.files.general.EphemerisFile;
25 import org.orekit.files.general.EphemerisFile.SatelliteEphemeris;
26 import org.orekit.files.general.EphemerisFileWriter;
27 import org.orekit.files.ilrs.StreamingCpfWriter.Segment;
28 import org.orekit.time.TimeScale;
29 import org.orekit.utils.TimeStampedPVCoordinates;
30
31 /**
32 * An CPF Writer class that can take in a general {@link EphemerisFile} object
33 * and export it as a valid CPF file.
34 * <p>
35 * It supports both 1.0 and 2.0 versions
36 * <p>
37 * <b>Note:</b> By default, only required header keys are wrote (H1 and H2).
38 * Furthermore, only position data can be written.
39 * Other keys (i.e. in header and other types of ephemeris entries) are simply ignored.
40 * Contributions are welcome to support more fields in the format.
41 * @author Bryan Cazabonne
42 * @since 10.3
43 * @see <a href="https://ilrs.gsfc.nasa.gov/docs/2006/cpf_1.01.pdf">1.0 file format</a>
44 * @see <a href="https://ilrs.gsfc.nasa.gov/docs/2018/cpf_2.00h-1.pdf">2.0 file format</a>
45 */
46 public class CPFWriter implements EphemerisFileWriter {
47
48 /** Container for header data. */
49 private final CPFHeader header;
50
51 /** Time scale for dates. */
52 private final TimeScale timescale;
53
54 /** Flag for optional velocity record. */
55 private final boolean velocityFlag;
56
57 /**
58 * Constructor.
59 * <p>
60 * Using this constructor, velocity data are not written.
61 * </p>
62 * @param header container for header data
63 * @param timescale time scale for dates
64 * @see #CPFWriter(CPFHeader, TimeScale, boolean)
65 */
66 public CPFWriter(final CPFHeader header, final TimeScale timescale) {
67 this(header, timescale, false);
68 }
69
70 /**
71 * Constructor.
72 * @param header container for header data
73 * @param timescale time scale for dates
74 * @param velocityFlag true if velocity must be written
75 * @since 11.2
76 */
77 public CPFWriter(final CPFHeader header, final TimeScale timescale, final boolean velocityFlag) {
78 this.header = header;
79 this.timescale = timescale;
80 this.velocityFlag = velocityFlag;
81 }
82
83 /** {@inheritDoc} */
84 @Override
85 public <C extends TimeStampedPVCoordinates, S extends EphemerisFile.EphemerisSegment<C>>
86 void write(final Appendable writer, final EphemerisFile<C, S> ephemerisFile)
87 throws IOException {
88
89 // Verify if writer is not a null object
90 if (writer == null) {
91 throw new OrekitIllegalArgumentException(OrekitMessages.NULL_ARGUMENT, "writer");
92 }
93
94 // Verify if the populated ephemeris file to serialize into the buffer is not null
95 if (ephemerisFile == null) {
96 return;
97 }
98
99 // Get satellite and ephemeris segments to output.
100 final SatelliteEphemeris<C, S> satEphem = ephemerisFile.getSatellites().get(header.getIlrsSatelliteId());
101 final List<S> segments = satEphem.getSegments();
102
103 // Writer
104 final StreamingCpfWriter cpfWriter =
105 new StreamingCpfWriter(writer, timescale, header, velocityFlag);
106 // Write header
107 cpfWriter.writeHeader();
108
109 // Loop on ephemeris segments
110 for (final S segment : segments) {
111 final Segment segmentWriter = cpfWriter.newSegment(header.getRefFrame());
112 // Loop on coordinates
113 for (final TimeStampedPVCoordinates coordinates : segment.getCoordinates()) {
114 segmentWriter.writeEphemerisLine(coordinates);
115 }
116 }
117
118 // Write end of file
119 cpfWriter.writeEndOfFile();
120
121 }
122
123 }