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 }