1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ccsds.ndm.odm.ocm;
18
19 import java.io.IOException;
20 import java.util.ArrayList;
21 import java.util.List;
22
23 import org.orekit.bodies.OneAxisEllipsoid;
24 import org.orekit.errors.OrekitIllegalArgumentException;
25 import org.orekit.errors.OrekitMessages;
26 import org.orekit.files.ccsds.ndm.odm.OdmHeader;
27 import org.orekit.files.ccsds.section.XmlStructureKey;
28 import org.orekit.files.ccsds.utils.FileFormat;
29 import org.orekit.files.ccsds.utils.generation.Generator;
30 import org.orekit.files.ccsds.utils.generation.KvnGenerator;
31 import org.orekit.files.ccsds.utils.generation.XmlGenerator;
32 import org.orekit.files.general.EphemerisFile;
33 import org.orekit.files.general.EphemerisFile.SatelliteEphemeris;
34 import org.orekit.files.general.EphemerisFileWriter;
35 import org.orekit.frames.Frame;
36 import org.orekit.utils.AccurateFormatter;
37 import org.orekit.utils.Formatter;
38 import org.orekit.utils.TimeStampedPVCoordinates;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 public class EphemerisOcmWriter implements EphemerisFileWriter {
61
62
63 private final OcmWriter writer;
64
65
66 private final OdmHeader header;
67
68
69 private final OcmMetadata metadata;
70
71
72 private final TrajectoryStateHistoryMetadata trajectoryMetadata;
73
74
75 private final FileFormat fileFormat;
76
77
78 private final String outputName;
79
80
81 private final int unitsColumn;
82
83
84 private final double maxRelativeOffset;
85
86
87 private final Formatter formatter;
88
89
90
91
92 private final OneAxisEllipsoid body;
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 public EphemerisOcmWriter(final OcmWriter writer,
120 final OdmHeader header, final OcmMetadata metadata,
121 final TrajectoryStateHistoryMetadata template,
122 final FileFormat fileFormat, final String outputName,
123 final double maxRelativeOffset, final int unitsColumn, final Formatter formatter) {
124 this.writer = writer;
125 this.header = header;
126 this.metadata = metadata.copy(header == null ? writer.getDefaultVersion() : header.getFormatVersion());
127 this.trajectoryMetadata = template.copy(header == null ? writer.getDefaultVersion() : header.getFormatVersion());
128 this.fileFormat = fileFormat;
129 this.outputName = outputName;
130 this.maxRelativeOffset = maxRelativeOffset;
131 this.unitsColumn = unitsColumn;
132 this.body = Double.isNaN(writer.getEquatorialRadius()) ?
133 null :
134 new OneAxisEllipsoid(writer.getEquatorialRadius(),
135 writer.getFlattening(),
136 template.getTrajReferenceFrame().asFrame());
137 this.formatter = formatter;
138 }
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 public EphemerisOcmWriter(final OcmWriter writer,
165 final OdmHeader header, final OcmMetadata metadata,
166 final TrajectoryStateHistoryMetadata template,
167 final FileFormat fileFormat, final String outputName,
168 final double maxRelativeOffset, final int unitsColumn) {
169 this(writer, header, metadata, template, fileFormat, outputName, maxRelativeOffset, unitsColumn, new AccurateFormatter());
170 }
171
172
173
174
175
176
177
178
179
180
181
182
183 @Override
184 public <C extends TimeStampedPVCoordinates, S extends EphemerisFile.EphemerisSegment<C>>
185 void write(final Appendable appendable, final EphemerisFile<C, S> ephemerisFile)
186 throws IOException {
187
188 if (appendable == null) {
189 throw new OrekitIllegalArgumentException(OrekitMessages.NULL_ARGUMENT, "writer");
190 }
191
192 if (ephemerisFile == null) {
193 return;
194 }
195
196 final String name;
197 if (metadata.getObjectName() != null) {
198 name = metadata.getObjectName();
199 } else if (metadata.getInternationalDesignator() != null) {
200 name = metadata.getInternationalDesignator();
201 } else if (metadata.getObjectDesignator() != null) {
202 name = metadata.getObjectDesignator();
203 } else {
204 name = Ocm.UNKNOWN_OBJECT;
205 }
206 final SatelliteEphemeris<C, S> satEphem = ephemerisFile.getSatellites().get(name);
207 if (satEphem == null) {
208 throw new OrekitIllegalArgumentException(OrekitMessages.VALUE_NOT_FOUND,
209 name, "ephemerisFile");
210 }
211
212
213 final List<S> blocks = satEphem.getSegments();
214 if (blocks.isEmpty()) {
215
216 return;
217 }
218
219 try (Generator generator = fileFormat == FileFormat.KVN ?
220 new KvnGenerator(appendable, OcmWriter.KVN_PADDING_WIDTH, outputName,
221 maxRelativeOffset, unitsColumn, formatter) :
222 new XmlGenerator(appendable, XmlGenerator.DEFAULT_INDENT, outputName,
223 maxRelativeOffset, unitsColumn > 0, null, formatter)) {
224
225 writer.writeHeader(generator, header);
226
227 if (generator.getFormat() == FileFormat.XML) {
228 generator.enterSection(XmlStructureKey.segment.name());
229 }
230
231
232 metadata.setStartTime(blocks.get(0).getStart());
233 metadata.setStopTime(blocks.get(blocks.size() - 1).getStop());
234 new OcmMetadataWriter(metadata, writer.getTimeConverter()).write(generator);
235
236 if (generator.getFormat() == FileFormat.XML) {
237 generator.enterSection(XmlStructureKey.data.name());
238 }
239
240
241 double lastZ = Double.NaN;
242 for (final S block : blocks) {
243
244
245 trajectoryMetadata.setTrajNextID(TrajectoryStateHistoryMetadata.incrementTrajID(trajectoryMetadata.getTrajID()));
246 trajectoryMetadata.setUseableStartTime(block.getStart());
247 trajectoryMetadata.setUseableStopTime(block.getStop());
248 trajectoryMetadata.setInterpolationDegree(block.getInterpolationSamples() - 1);
249
250
251 final OrbitElementsType type = trajectoryMetadata.getTrajType();
252 final Frame frame = trajectoryMetadata.getTrajReferenceFrame().asFrame();
253 int crossings = 0;
254 final List<TrajectoryState> states = new ArrayList<>(block.getCoordinates().size());
255 for (final C pv : block.getCoordinates()) {
256 if (lastZ < 0.0 && pv.getPosition().getZ() >= 0.0) {
257
258 ++crossings;
259 }
260 lastZ = pv.getPosition().getZ();
261 states.add(new TrajectoryState(type, pv.getDate(), type.toRawElements(pv, frame, body, block.getMu())));
262 }
263 final TrajectoryStateHistory history = new TrajectoryStateHistory(trajectoryMetadata, states,
264 body, block.getMu());
265
266
267 final TrajectoryStateHistoryWriter trajectoryWriter =
268 new TrajectoryStateHistoryWriter(history, writer.getTimeConverter());
269 trajectoryWriter.write(generator);
270
271
272 trajectoryMetadata.setTrajPrevID(trajectoryMetadata.getTrajID());
273 trajectoryMetadata.setTrajID(trajectoryMetadata.getTrajNextID());
274
275 if (trajectoryMetadata.getOrbRevNum() >= 0) {
276
277 trajectoryMetadata.setOrbRevNum(trajectoryMetadata.getOrbRevNum() + crossings);
278 }
279
280 }
281
282 if (generator.getFormat() == FileFormat.XML) {
283 generator.exitSection();
284 generator.exitSection();
285 }
286
287 writer.writeFooter(generator);
288
289 }
290
291 }
292
293 }