source: ntrip/trunk/BNC/rinex/rnxobsfile.cpp@ 3908

Last change on this file since 3908 was 3869, checked in by mervart, 13 years ago
File size: 20.8 KB
Line 
1// Part of BNC, a utility for retrieving decoding and
2// converting GNSS data streams from NTRIP broadcasters.
3//
4// Copyright (C) 2007
5// German Federal Agency for Cartography and Geodesy (BKG)
6// http://www.bkg.bund.de
7// Czech Technical University Prague, Department of Geodesy
8// http://www.fsv.cvut.cz
9//
10// Email: euref-ip@bkg.bund.de
11//
12// This program is free software; you can redistribute it and/or
13// modify it under the terms of the GNU General Public License
14// as published by the Free Software Foundation, version 2.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25/* -------------------------------------------------------------------------
26 * BKG NTRIP Client
27 * -------------------------------------------------------------------------
28 *
29 * Class: t_rnxObsFile
30 *
31 * Purpose: Reads RINEX Observation File
32 *
33 * Author: L. Mervart
34 *
35 * Created: 24-Jan-2012
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41#include <iostream>
42#include <iomanip>
43#include <sstream>
44#include "rnxobsfile.h"
45#include "bncutils.h"
46#include "bncversion.h"
47
48using namespace std;
49
50const QString t_rnxObsFile::t_rnxObsHeader::_emptyStr;
51
52// Constructor
53////////////////////////////////////////////////////////////////////////////
54t_rnxObsFile::t_rnxObsHeader::t_rnxObsHeader() {
55 _antNEU.ReSize(3); _antNEU = 0.0;
56 _antXYZ.ReSize(3); _antXYZ = 0.0;
57 _antBSG.ReSize(3); _antBSG = 0.0;
58 _xyz.ReSize(3); _xyz = 0.0;
59 _version = 0.0;
60 _interval = 0.0;
61 for (unsigned iPrn = 1; iPrn <= MAXPRN_GPS; iPrn++) {
62 _wlFactorsL1[iPrn] = 1;
63 _wlFactorsL2[iPrn] = 1;
64 }
65}
66
67// Destructor
68////////////////////////////////////////////////////////////////////////////
69t_rnxObsFile::t_rnxObsHeader::~t_rnxObsHeader() {
70}
71
72// Read Header
73////////////////////////////////////////////////////////////////////////////
74t_irc t_rnxObsFile::t_rnxObsHeader::read(QTextStream* stream, int maxLines) {
75 int numLines = 0;
76 while ( stream->status() == QTextStream::Ok && !stream->atEnd() ) {
77 QString line = stream->readLine(); ++ numLines;
78 if (line.isEmpty()) {
79 continue;
80 }
81 if (line.indexOf("END OF FILE") != -1) {
82 break;
83 }
84 QString value = line.mid(0,60).trimmed();
85 QString key = line.mid(60).trimmed();
86 if (key == "END OF HEADER") {
87 break;
88 }
89 else if (key == "RINEX VERSION / TYPE") {
90 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
91 in >> _version;
92 }
93 else if (key == "MARKER NAME") {
94 _markerName = value;
95 }
96 else if (key == "ANT # / TYPE") {
97 _antennaName = line.mid(20,20).trimmed();
98 }
99 else if (key == "INTERVAL") {
100 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
101 in >> _interval;
102 }
103 else if (key == "WAVELENGTH FACT L1/2") {
104 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
105 int wlFactL1 = 0;
106 int wlFactL2 = 0;
107 int numSat = 0;
108 in >> wlFactL1 >> wlFactL2 >> numSat;
109 if (numSat == 0) {
110 for (unsigned iPrn = 1; iPrn <= MAXPRN_GPS; iPrn++) {
111 _wlFactorsL1[iPrn] = wlFactL1;
112 _wlFactorsL2[iPrn] = wlFactL2;
113 }
114 }
115 else {
116 for (int ii = 0; ii < numSat; ii++) {
117 QString prn; in >> prn;
118 if (prn[0] == 'G') {
119 int iPrn;
120 readInt(prn, 1, 2, iPrn);
121 _wlFactorsL1[iPrn] = wlFactL1;
122 _wlFactorsL2[iPrn] = wlFactL2;
123 }
124 }
125 }
126 }
127 else if (key == "APPROX POSITION XYZ") {
128 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
129 in >> _xyz[0] >> _xyz[1] >> _xyz[2];
130 }
131 else if (key == "ANTENNA: DELTA H/E/N") {
132 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
133 in >> _antNEU[2] >> _antNEU[1] >> _antNEU[0];
134 }
135 else if (key == "ANTENNA: DELTA X/Y/Z") {
136 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
137 in >> _antXYZ[0] >> _antXYZ[1] >> _antXYZ[2];
138 }
139 else if (key == "ANTENNA: B.SIGHT XYZ") {
140 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
141 in >> _antBSG[0] >> _antBSG[1] >> _antBSG[2];
142 }
143 else if (key == "# / TYPES OF OBSERV") {
144 QTextStream* in = new QTextStream(value.toAscii(), QIODevice::ReadOnly);
145 int nTypes;
146 *in >> nTypes;
147 _obsTypesV2.clear();
148 for (int ii = 0; ii < nTypes; ii++) {
149 if (ii > 0 && ii % 9 == 0) {
150 line = stream->readLine(); ++numLines;
151 delete in;
152 in = new QTextStream(line.toAscii(), QIODevice::ReadOnly);
153 }
154 QString hlp;
155 *in >> hlp;
156 _obsTypesV2.push_back(hlp);
157 }
158 }
159 else if (key == "SYS / # / OBS TYPES") {
160 QTextStream* in = new QTextStream(value.toAscii(), QIODevice::ReadOnly);
161 char sys;
162 int nTypes;
163 *in >> sys >> nTypes;
164 _obsTypesV3[sys].clear();
165 for (int ii = 0; ii < nTypes; ii++) {
166 if (ii > 0 && ii % 13 == 0) {
167 line = stream->readLine(); ++numLines;
168 delete in;
169 in = new QTextStream(line.toAscii(), QIODevice::ReadOnly);
170 }
171 QString hlp;
172 *in >> hlp;
173 _obsTypesV3[sys].push_back(hlp);
174 }
175 delete in;
176 }
177 else if (key == "TIME OF FIRST OBS") {
178 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
179 int year, month, day, hour, min;
180 double sec;
181 in >> year >> month >> day >> hour >> min >> sec;
182 _startTime.set(year, month, day, hour, min, sec);
183 }
184 if (maxLines > 0 && numLines == maxLines) {
185 break;
186 }
187 }
188
189 return success;
190}
191
192// Number of Observation Types (satellite-system specific)
193////////////////////////////////////////////////////////////////////////////
194int t_rnxObsFile::t_rnxObsHeader::nTypes(char sys) const {
195 if (_version < 3.0) {
196 return _obsTypesV2.size();
197 }
198 else {
199 map<char, vector<QString> >::const_iterator it = _obsTypesV3.find(sys);
200 if (it != _obsTypesV3.end()) {
201 return it->second.size();
202 }
203 else {
204 return 0;
205 }
206 }
207}
208
209// Observation Type (satellite-system specific)
210////////////////////////////////////////////////////////////////////////////
211const QString& t_rnxObsFile::t_rnxObsHeader::obsType(char sys, int index) const {
212 if (_version < 3.0) {
213 return _obsTypesV2.at(index);
214 }
215 else {
216 map<char, vector<QString> >::const_iterator it = _obsTypesV3.find(sys);
217 if (it != _obsTypesV3.end()) {
218 return it->second.at(index);
219 }
220 else {
221 return _emptyStr;
222 }
223 }
224}
225
226// Constructor
227////////////////////////////////////////////////////////////////////////////
228t_rnxObsFile::t_rnxObsFile(const QString& fileName, e_inpOut inpOut) {
229 _inpOut = inpOut;
230 _stream = 0;
231 _flgPowerFail = false;
232 if (_inpOut == input) {
233 openRead(fileName);
234 }
235 else {
236 openWrite(fileName);
237 }
238}
239
240// Open for input
241////////////////////////////////////////////////////////////////////////////
242void t_rnxObsFile::openRead(const QString& fileName) {
243
244 _fileName = fileName; expandEnvVar(_fileName);
245 _file = new QFile(_fileName);
246 _file->open(QIODevice::ReadOnly | QIODevice::Text);
247 _stream = new QTextStream();
248 _stream->setDevice(_file);
249
250 _header.read(_stream);
251
252 // Guess Observation Interval
253 // --------------------------
254 if (_header._interval == 0.0) {
255 bncTime ttPrev;
256 for (int iEpo = 0; iEpo < 10; iEpo++) {
257 const t_rnxEpo* rnxEpo = nextEpoch();
258 if (!rnxEpo) {
259 throw QString("t_rnxObsFile: not enough epochs");
260 }
261 if (iEpo > 0) {
262 double dt = rnxEpo->tt - ttPrev;
263 if (_header._interval == 0.0 || dt < _header._interval) {
264 _header._interval = dt;
265 }
266 }
267 ttPrev = rnxEpo->tt;
268 }
269 _stream->seek(0);
270 _header.read(_stream);
271 }
272
273 // Time of first observation
274 // -------------------------
275 if (!_header._startTime.valid()) {
276 const t_rnxEpo* rnxEpo = nextEpoch();
277 if (!rnxEpo) {
278 throw QString("t_rnxObsFile: not enough epochs");
279 }
280 _header._startTime = rnxEpo->tt;
281 _stream->seek(0);
282 _header.read(_stream);
283 }
284}
285
286// Open for output
287////////////////////////////////////////////////////////////////////////////
288void t_rnxObsFile::openWrite(const QString& fileName) {
289
290 _fileName = fileName; expandEnvVar(_fileName);
291 _file = new QFile(_fileName);
292 _file->open(QIODevice::WriteOnly | QIODevice::Text);
293 _stream = new QTextStream();
294 _stream->setDevice(_file);
295}
296
297// Destructor
298////////////////////////////////////////////////////////////////////////////
299t_rnxObsFile::~t_rnxObsFile() {
300 close();
301}
302
303// Close
304////////////////////////////////////////////////////////////////////////////
305void t_rnxObsFile::close() {
306 delete _stream; _stream = 0;
307 delete _file; _file = 0;
308}
309
310// Handle Special Epoch Flag
311////////////////////////////////////////////////////////////////////////////
312void t_rnxObsFile::handleEpochFlag(int flag, const QString& line) {
313
314 // Power Failure
315 // -------------
316 if (flag == 1) {
317 _flgPowerFail = true;
318 }
319
320 // Start moving antenna
321 // --------------------
322 else if (flag == 2) {
323 // no action
324 }
325
326 // Re-Read Header
327 // --------------
328 else if (flag == 3 || flag == 4) {
329 int numLines = 0;
330 if (version() < 3.0) {
331 readInt(line, 29, 3, numLines);
332 }
333 else {
334 readInt(line, 32, 3, numLines);
335 }
336 _header.read(_stream, numLines);
337 }
338
339 // Unhandled Flag
340 // --------------
341 else {
342 throw QString("t_rnxObsFile: unhandled flag\n" + line);
343 }
344}
345
346// Retrieve single Epoch
347////////////////////////////////////////////////////////////////////////////
348const t_rnxObsFile::t_rnxEpo* t_rnxObsFile::nextEpoch() {
349
350 _currEpo.clear();
351
352 if (version() < 3.0) {
353 return nextEpochV2();
354 }
355 else {
356 return nextEpochV3();
357 }
358}
359
360// Retrieve single Epoch (RINEX Version 3)
361////////////////////////////////////////////////////////////////////////////
362const t_rnxObsFile::t_rnxEpo* t_rnxObsFile::nextEpochV3() {
363
364 while ( _stream->status() == QTextStream::Ok && !_stream->atEnd() ) {
365
366 QString line = _stream->readLine();
367
368 if (line.isEmpty()) {
369 continue;
370 }
371
372 int flag = 0;
373 readInt(line, 31, 1, flag);
374 if (flag > 0) {
375 handleEpochFlag(flag, line);
376 continue;
377 }
378
379 QTextStream in(line.mid(1).toAscii(), QIODevice::ReadOnly);
380
381 // Epoch Time
382 // ----------
383 int year, month, day, hour, min;
384 double sec;
385 in >> year >> month >> day >> hour >> min >> sec;
386 _currEpo.tt.set(year, month, day, hour, min, sec);
387
388 // Number of Satellites
389 // --------------------
390 int numSat;
391 readInt(line, 32, 3, numSat);
392
393 _currEpo.rnxSat.resize(numSat);
394
395 // Observations
396 // ------------
397 for (int iSat = 0; iSat < numSat; iSat++) {
398 line = _stream->readLine();
399 _currEpo.rnxSat[iSat].satSys = line.toAscii()[0];
400 readInt(line, 1, 2, _currEpo.rnxSat[iSat].satNum);
401 char sys = line.toAscii()[0];
402 for (int iType = 0; iType < _header.nTypes(sys); iType++) {
403 int pos = 3 + 16*iType;
404 double obsValue = 0.0;
405 int lli = 0;
406 int snr = 0;
407 readDbl(line, pos, 14, obsValue);
408 readInt(line, pos + 14, 1, lli);
409 readInt(line, pos + 15, 1, snr);
410
411 if (_flgPowerFail) {
412 lli |= 1;
413 }
414
415 _currEpo.rnxSat[iSat].obs.push_back(obsValue);
416 _currEpo.rnxSat[iSat].lli.push_back(lli);
417 _currEpo.rnxSat[iSat].snr.push_back(snr);
418 }
419 }
420
421 _flgPowerFail = false;
422
423 return &_currEpo;
424 }
425
426 return 0;
427}
428
429// Retrieve single Epoch (RINEX Version 2)
430////////////////////////////////////////////////////////////////////////////
431const t_rnxObsFile::t_rnxEpo* t_rnxObsFile::nextEpochV2() {
432
433 while ( _stream->status() == QTextStream::Ok && !_stream->atEnd() ) {
434
435 QString line = _stream->readLine();
436
437 if (line.isEmpty()) {
438 continue;
439 }
440
441 int flag = 0;
442 readInt(line, 28, 1, flag);
443 if (flag > 0) {
444 handleEpochFlag(flag, line);
445 continue;
446 }
447
448 QTextStream in(line.toAscii(), QIODevice::ReadOnly);
449
450 // Epoch Time
451 // ----------
452 int year, month, day, hour, min;
453 double sec;
454 in >> year >> month >> day >> hour >> min >> sec;
455 if (year < 80) {
456 year += 2000;
457 }
458 else if (year < 100) {
459 year += 1900;
460 }
461 _currEpo.tt.set(year, month, day, hour, min, sec);
462
463 // Number of Satellites
464 // --------------------
465 int numSat;
466 readInt(line, 29, 3, numSat);
467
468 _currEpo.rnxSat.resize(numSat);
469
470 // Read Satellite Numbers
471 // ----------------------
472 int pos = 32;
473 for (int iSat = 0; iSat < numSat; iSat++) {
474 if (iSat > 0 && iSat % 12 == 0) {
475 line = _stream->readLine();
476 pos = 32;
477 }
478
479 _currEpo.rnxSat[iSat].satSys = line.toAscii()[pos];
480 readInt(line, pos + 1, 2, _currEpo.rnxSat[iSat].satNum);
481
482 pos += 3;
483 }
484
485 // Read Observation Records
486 // ------------------------
487 for (int iSat = 0; iSat < numSat; iSat++) {
488 line = _stream->readLine();
489 pos = 0;
490 for (int iType = 0; iType < _header.nTypes(_currEpo.rnxSat[iSat].satSys); iType++) {
491 if (iType > 0 && iType % 5 == 0) {
492 line = _stream->readLine();
493 pos = 0;
494 }
495 double obsValue = 0.0;
496 int lli = 0;
497 int snr = 0;
498 readDbl(line, pos, 14, obsValue);
499 readInt(line, pos + 14, 1, lli);
500 readInt(line, pos + 15, 1, snr);
501
502 if (_flgPowerFail) {
503 lli |= 1;
504 }
505
506 _currEpo.rnxSat[iSat].obs.push_back(obsValue);
507 _currEpo.rnxSat[iSat].lli.push_back(lli);
508 _currEpo.rnxSat[iSat].snr.push_back(snr);
509
510 pos += 16;
511 }
512 }
513
514 _flgPowerFail = false;
515
516 return &_currEpo;
517 }
518
519 return 0;
520}
521
522// Set Header Information
523////////////////////////////////////////////////////////////////////////////
524void t_rnxObsFile::setHeader(const t_rnxObsHeader& header) {
525 _header._version = header._version;
526 _header._interval = header._interval;
527 _header._antennaName = header._antennaName;
528 _header._markerName = header._markerName;
529 _header._antNEU = header._antNEU;
530 _header._antXYZ = header._antXYZ;
531 _header._antBSG = header._antBSG;
532 _header._xyz = header._xyz;
533 for (unsigned iPrn = 1; iPrn <= MAXPRN_GPS; iPrn++) {
534 _header._wlFactorsL1[iPrn] = header._wlFactorsL1[iPrn];
535 _header._wlFactorsL2[iPrn] = header._wlFactorsL2[iPrn];
536 }
537 _header._startTime = header._startTime;
538 for (unsigned ii = 0; ii < header._obsTypesV2.size(); ii++) {
539 _header._obsTypesV2.push_back(header._obsTypesV2[ii]);
540 }
541 map<char, vector<QString> >::const_iterator it;
542 for (it = header._obsTypesV3.begin(); it != header._obsTypesV3.end(); it++) {
543 char sys = it->first;
544 const vector<QString>& typesV3 = it->second;
545 for (unsigned ii = 0; ii < typesV3.size(); ii++) {
546 _header._obsTypesV3[sys].push_back(typesV3[ii]);
547 }
548 }
549}
550
551// Write Header
552////////////////////////////////////////////////////////////////////////////
553void t_rnxObsFile::writeHeader() {
554 *_stream << QString("%1 Observation data Mixed")
555 .arg(_header._version, 9, 'f', 2)
556 .leftJustified(60)
557 << "RINEX VERSION / TYPE\n";
558
559 *_stream << QString("%1%2%3")
560 .arg("BNC "BNCVERSION, -20)
561 .arg("BKG", -20)
562 .arg(currentDateAndTimeGPS().date().toString("dd-MMM-yyyy"), -20)
563 .leftJustified(60)
564 << "PGM / RUN BY / DATE\n";
565
566 *_stream << QString("%1")
567 .arg(_header._markerName, -60)
568 .leftJustified(60)
569 << "MARKER NAME\n";
570
571 *_stream << QString("%1%2")
572 .arg("Observer", -20) // TODO
573 .arg("Agency", -40) // TODO
574 .leftJustified(60)
575 << "OBSERVER / AGENCY\n";
576
577 *_stream << QString("%1%2%3")
578 .arg("xxxx", -20) // TODO
579 .arg("Receiver", -20) // TODO
580 .arg("yyyy", -20) // TODO
581 .leftJustified(60)
582 << "REC # / TYPE / VERS\n";
583
584 *_stream << QString("%1%2")
585 .arg("xxxx", -20) // TODO
586 .arg(_header._antennaName, -20)
587 .leftJustified(60)
588 << "ANT # / TYPE\n";
589
590 *_stream << QString("%1%2%3")
591 .arg(_header._xyz(1), 14, 'f', 4)
592 .arg(_header._xyz(2), 14, 'f', 4)
593 .arg(_header._xyz(3), 14, 'f', 4)
594 .leftJustified(60)
595 << "APPROX POSITION XYZ\n";
596
597 *_stream << QString("%1%2%3")
598 .arg(_header._antNEU(3), 14, 'f', 4)
599 .arg(_header._antNEU(2), 14, 'f', 4)
600 .arg(_header._antNEU(1), 14, 'f', 4)
601 .leftJustified(60)
602 << "ANTENNA: DELTA H/E/N\n";
603
604 QString hlp;
605 QTextStream(&hlp) << QString("%1").arg(_header._obsTypesV2.size(), 6);
606 for (unsigned ii = 0; ii < _header._obsTypesV2.size(); ii++) {
607 QTextStream(&hlp) << QString("%1").arg(_header._obsTypesV2[ii], 6);
608 if (ii > 0 && (ii % 8 == 0 || ii == _header._obsTypesV2.size()-1)) {
609 *_stream << hlp.leftJustified(60) << "# / TYPES OF OBSERV\n";
610 hlp = QString().leftJustified(6);
611 }
612 }
613
614 *_stream << QString("%1")
615 .arg(_header._interval, 10, 'f', 3)
616 .leftJustified(60)
617 << "INTERVAL\n";
618
619 unsigned year, month, day, hour, min;
620 double sec;
621 _header._startTime.civil_date(year, month, day);
622 _header._startTime.civil_time(hour, min, sec);
623 *_stream << QString("%1%2%3%4%5%6%7")
624 .arg(year, 6)
625 .arg(month, 6)
626 .arg(day, 6)
627 .arg(hour, 6)
628 .arg(min, 6)
629 .arg(sec, 13, 'f', 7)
630 .arg("GPS", 8)
631 .leftJustified(60)
632 << "TIME OF FIRST OBS\n";
633
634 *_stream << QString()
635 .leftJustified(60)
636 << "END OF HEADER\n";
637}
638
639// Write Data Epoch
640////////////////////////////////////////////////////////////////////////////
641void t_rnxObsFile::writeEpoch(const t_rnxEpo* epo) {
642 if (version() < 3.0) {
643 return writeEpochV2(epo);
644 }
645 else {
646 return writeEpochV3(epo);
647 }
648}
649
650// Write Data Epoch (RINEX Version 2)
651////////////////////////////////////////////////////////////////////////////
652void t_rnxObsFile::writeEpochV2(const t_rnxEpo* epo) {
653
654 unsigned year, month, day, hour, min;
655 double sec;
656 epo->tt.civil_date(year, month, day);
657 epo->tt.civil_time(hour, min, sec);
658
659 QString dateStr;
660 QTextStream(&dateStr) << QString(" %1 %2 %3 %4 %5%6")
661 .arg(int(fmod(year, 100)), 2, 10, QChar('0'))
662 .arg(month, 2, 10, QChar('0'))
663 .arg(day, 2, 10, QChar('0'))
664 .arg(hour, 2, 10, QChar('0'))
665 .arg(min, 2, 10, QChar('0'))
666 .arg(sec, 11, 'f', 7);
667
668 int flag = 0;
669 *_stream << dateStr
670 << QString("%1%2").arg(flag, 3).arg(epo->rnxSat.size(), 3);
671 for (unsigned iSat = 0; iSat < epo->rnxSat.size(); iSat++) {
672 const t_rnxSat& rnxSat = epo->rnxSat[iSat];
673 if (iSat > 0 && iSat % 12 == 0) {
674 *_stream << endl << QString().leftJustified(32);
675 }
676 *_stream << rnxSat.satSys << QString("%1").arg(rnxSat.satNum, 2);
677 }
678 *_stream << endl;
679 for (unsigned iSat = 0; iSat < epo->rnxSat.size(); iSat++) {
680 const t_rnxSat& rnxSat = epo->rnxSat[iSat];
681 for (unsigned iType = 0; iType < rnxSat.obs.size(); iType++) {
682 if (iType > 0 && iType % 5 == 0) {
683 *_stream << endl;
684 }
685 if (rnxSat.obs[iType] == 0.0) {
686 *_stream << QString().leftJustified(16);
687 }
688 else {
689 *_stream << QString("%1%2%3")
690 .arg(rnxSat.obs[iType], 14, 'f', 3)
691 .arg(rnxSat.lli[iType],1)
692 .arg(rnxSat.snr[iType],1);
693 }
694 }
695 *_stream << endl;
696 }
697}
698
699// Write Data Epoch (RINEX Version 3)
700////////////////////////////////////////////////////////////////////////////
701void t_rnxObsFile::writeEpochV3(const t_rnxEpo* epo) {
702
703 unsigned year, month, day, hour, min;
704 double sec;
705 epo->tt.civil_date(year, month, day);
706 epo->tt.civil_time(hour, min, sec);
707
708 QString dateStr;
709 QTextStream(&dateStr) << QString("> %1 %2 %3 %4 %5%6")
710 .arg(year, 4)
711 .arg(month, 2, 10, QChar('0'))
712 .arg(day, 2, 10, QChar('0'))
713 .arg(hour, 2, 10, QChar('0'))
714 .arg(min, 2, 10, QChar('0'))
715 .arg(sec, 11, 'f', 7);
716
717 int flag = 0;
718 *_stream << dateStr
719 << QString("%1%2\n").arg(flag, 3).arg(epo->rnxSat.size(), 3);
720
721 for (unsigned iSat = 0; iSat < epo->rnxSat.size(); iSat++) {
722 const t_rnxSat& rnxSat = epo->rnxSat[iSat];
723 *_stream << rnxSat.satSys
724 << QString("%1").arg(rnxSat.satNum, 2, 10, QChar('0'));
725 for (unsigned iType = 0; iType < rnxSat.obs.size(); iType++) {
726 if (rnxSat.obs[iType] == 0.0) {
727 *_stream << QString().leftJustified(16);
728 }
729 else {
730 *_stream << QString("%1%2%3")
731 .arg(rnxSat.obs[iType], 14, 'f', 3)
732 .arg(rnxSat.lli[iType],1)
733 .arg(rnxSat.snr[iType],1);
734 }
735 }
736 *_stream << endl;
737 }
738}
Note: See TracBrowser for help on using the repository browser.