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

Last change on this file since 3940 was 3940, checked in by mervart, 12 years ago
File size: 22.9 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 "bncapp.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 == "MARKER NUMBER") {
97 _markerNumber = line.mid(0,20).trimmed();
98 }
99 else if (key == "ANT # / TYPE") {
100 _antennaNumber = line.mid( 0,20).trimmed();
101 _antennaName = line.mid(20,20).trimmed();
102 }
103 else if (key == "OBSERVER / AGENCY") {
104 _observer = line.mid( 0,20).trimmed();
105 _agency = line.mid(20,40).trimmed();
106 }
107 else if (key == "REC # / TYPE / VERS") {
108 _receiverNumber = line.mid( 0,20).trimmed();
109 _receiverType = line.mid(20,20).trimmed();
110 _receiverVersion = line.mid(40,20).trimmed();
111 }
112 else if (key == "INTERVAL") {
113 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
114 in >> _interval;
115 }
116 else if (key == "WAVELENGTH FACT L1/2") {
117 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
118 int wlFactL1 = 0;
119 int wlFactL2 = 0;
120 int numSat = 0;
121 in >> wlFactL1 >> wlFactL2 >> numSat;
122 if (numSat == 0) {
123 for (unsigned iPrn = 1; iPrn <= MAXPRN_GPS; iPrn++) {
124 _wlFactorsL1[iPrn] = wlFactL1;
125 _wlFactorsL2[iPrn] = wlFactL2;
126 }
127 }
128 else {
129 for (int ii = 0; ii < numSat; ii++) {
130 QString prn; in >> prn;
131 if (prn[0] == 'G') {
132 int iPrn;
133 readInt(prn, 1, 2, iPrn);
134 _wlFactorsL1[iPrn] = wlFactL1;
135 _wlFactorsL2[iPrn] = wlFactL2;
136 }
137 }
138 }
139 }
140 else if (key == "APPROX POSITION XYZ") {
141 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
142 in >> _xyz[0] >> _xyz[1] >> _xyz[2];
143 }
144 else if (key == "ANTENNA: DELTA H/E/N") {
145 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
146 in >> _antNEU[2] >> _antNEU[1] >> _antNEU[0];
147 }
148 else if (key == "ANTENNA: DELTA X/Y/Z") {
149 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
150 in >> _antXYZ[0] >> _antXYZ[1] >> _antXYZ[2];
151 }
152 else if (key == "ANTENNA: B.SIGHT XYZ") {
153 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
154 in >> _antBSG[0] >> _antBSG[1] >> _antBSG[2];
155 }
156 else if (key == "# / TYPES OF OBSERV") {
157 QTextStream* in = new QTextStream(value.toAscii(), QIODevice::ReadOnly);
158 int nTypes;
159 *in >> nTypes;
160 _obsTypesV2.clear();
161 for (int ii = 0; ii < nTypes; ii++) {
162 if (ii > 0 && ii % 9 == 0) {
163 line = stream->readLine(); ++numLines;
164 delete in;
165 in = new QTextStream(line.toAscii(), QIODevice::ReadOnly);
166 }
167 QString hlp;
168 *in >> hlp;
169 _obsTypesV2.push_back(hlp);
170 }
171 }
172 else if (key == "SYS / # / OBS TYPES") {
173 QTextStream* in = new QTextStream(value.toAscii(), QIODevice::ReadOnly);
174 char sys;
175 int nTypes;
176 *in >> sys >> nTypes;
177 _obsTypesV3[sys].clear();
178 for (int ii = 0; ii < nTypes; ii++) {
179 if (ii > 0 && ii % 13 == 0) {
180 line = stream->readLine(); ++numLines;
181 delete in;
182 in = new QTextStream(line.toAscii(), QIODevice::ReadOnly);
183 }
184 QString hlp;
185 *in >> hlp;
186 _obsTypesV3[sys].push_back(hlp);
187 }
188 delete in;
189 }
190 else if (key == "TIME OF FIRST OBS") {
191 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
192 int year, month, day, hour, min;
193 double sec;
194 in >> year >> month >> day >> hour >> min >> sec;
195 _startTime.set(year, month, day, hour, min, sec);
196 }
197 if (maxLines > 0 && numLines == maxLines) {
198 break;
199 }
200 }
201
202 return success;
203}
204
205// Number of Observation Types (satellite-system specific)
206////////////////////////////////////////////////////////////////////////////
207int t_rnxObsFile::t_rnxObsHeader::nTypes(char sys) const {
208 if (_version < 3.0) {
209 return _obsTypesV2.size();
210 }
211 else {
212 map<char, vector<QString> >::const_iterator it = _obsTypesV3.find(sys);
213 if (it != _obsTypesV3.end()) {
214 return it->second.size();
215 }
216 else {
217 return 0;
218 }
219 }
220}
221
222// Observation Type (satellite-system specific)
223////////////////////////////////////////////////////////////////////////////
224const QString& t_rnxObsFile::t_rnxObsHeader::obsType(char sys, int index) const {
225 if (_version < 3.0) {
226 return _obsTypesV2.at(index);
227 }
228 else {
229 map<char, vector<QString> >::const_iterator it = _obsTypesV3.find(sys);
230 if (it != _obsTypesV3.end()) {
231 return it->second.at(index);
232 }
233 else {
234 return _emptyStr;
235 }
236 }
237}
238
239// Constructor
240////////////////////////////////////////////////////////////////////////////
241t_rnxObsFile::t_rnxObsFile(const QString& fileName, e_inpOut inpOut) {
242 _inpOut = inpOut;
243 _stream = 0;
244 _flgPowerFail = false;
245 if (_inpOut == input) {
246 openRead(fileName);
247 }
248 else {
249 openWrite(fileName);
250 }
251}
252
253// Open for input
254////////////////////////////////////////////////////////////////////////////
255void t_rnxObsFile::openRead(const QString& fileName) {
256
257 _fileName = fileName; expandEnvVar(_fileName);
258 _file = new QFile(_fileName);
259 _file->open(QIODevice::ReadOnly | QIODevice::Text);
260 _stream = new QTextStream();
261 _stream->setDevice(_file);
262
263 _header.read(_stream);
264
265 // Guess Observation Interval
266 // --------------------------
267 if (_header._interval == 0.0) {
268 bncTime ttPrev;
269 for (int iEpo = 0; iEpo < 10; iEpo++) {
270 const t_rnxEpo* rnxEpo = nextEpoch();
271 if (!rnxEpo) {
272 throw QString("t_rnxObsFile: not enough epochs");
273 }
274 if (iEpo > 0) {
275 double dt = rnxEpo->tt - ttPrev;
276 if (_header._interval == 0.0 || dt < _header._interval) {
277 _header._interval = dt;
278 }
279 }
280 ttPrev = rnxEpo->tt;
281 }
282 _stream->seek(0);
283 _header.read(_stream);
284 }
285
286 // Time of first observation
287 // -------------------------
288 if (!_header._startTime.valid()) {
289 const t_rnxEpo* rnxEpo = nextEpoch();
290 if (!rnxEpo) {
291 throw QString("t_rnxObsFile: not enough epochs");
292 }
293 _header._startTime = rnxEpo->tt;
294 _stream->seek(0);
295 _header.read(_stream);
296 }
297}
298
299// Open for output
300////////////////////////////////////////////////////////////////////////////
301void t_rnxObsFile::openWrite(const QString& fileName) {
302
303 _fileName = fileName; expandEnvVar(_fileName);
304 _file = new QFile(_fileName);
305 _file->open(QIODevice::WriteOnly | QIODevice::Text);
306 _stream = new QTextStream();
307 _stream->setDevice(_file);
308}
309
310// Destructor
311////////////////////////////////////////////////////////////////////////////
312t_rnxObsFile::~t_rnxObsFile() {
313 close();
314}
315
316// Close
317////////////////////////////////////////////////////////////////////////////
318void t_rnxObsFile::close() {
319 delete _stream; _stream = 0;
320 delete _file; _file = 0;
321}
322
323// Handle Special Epoch Flag
324////////////////////////////////////////////////////////////////////////////
325void t_rnxObsFile::handleEpochFlag(int flag, const QString& line) {
326
327 // Power Failure
328 // -------------
329 if (flag == 1) {
330 _flgPowerFail = true;
331 }
332
333 // Start moving antenna
334 // --------------------
335 else if (flag == 2) {
336 // no action
337 }
338
339 // Re-Read Header
340 // --------------
341 else if (flag == 3 || flag == 4) {
342 int numLines = 0;
343 if (version() < 3.0) {
344 readInt(line, 29, 3, numLines);
345 }
346 else {
347 readInt(line, 32, 3, numLines);
348 }
349 _header.read(_stream, numLines);
350 }
351
352 // Unhandled Flag
353 // --------------
354 else {
355 throw QString("t_rnxObsFile: unhandled flag\n" + line);
356 }
357}
358
359// Retrieve single Epoch
360////////////////////////////////////////////////////////////////////////////
361const t_rnxObsFile::t_rnxEpo* t_rnxObsFile::nextEpoch() {
362
363 _currEpo.clear();
364
365 if (version() < 3.0) {
366 return nextEpochV2();
367 }
368 else {
369 return nextEpochV3();
370 }
371}
372
373// Retrieve single Epoch (RINEX Version 3)
374////////////////////////////////////////////////////////////////////////////
375const t_rnxObsFile::t_rnxEpo* t_rnxObsFile::nextEpochV3() {
376
377 while ( _stream->status() == QTextStream::Ok && !_stream->atEnd() ) {
378
379 QString line = _stream->readLine();
380
381 if (line.isEmpty()) {
382 continue;
383 }
384
385 int flag = 0;
386 readInt(line, 31, 1, flag);
387 if (flag > 0) {
388 handleEpochFlag(flag, line);
389 continue;
390 }
391
392 QTextStream in(line.mid(1).toAscii(), QIODevice::ReadOnly);
393
394 // Epoch Time
395 // ----------
396 int year, month, day, hour, min;
397 double sec;
398 in >> year >> month >> day >> hour >> min >> sec;
399 _currEpo.tt.set(year, month, day, hour, min, sec);
400
401 // Number of Satellites
402 // --------------------
403 int numSat;
404 readInt(line, 32, 3, numSat);
405
406 _currEpo.rnxSat.resize(numSat);
407
408 // Observations
409 // ------------
410 for (int iSat = 0; iSat < numSat; iSat++) {
411 line = _stream->readLine();
412 _currEpo.rnxSat[iSat].satSys = line.toAscii()[0];
413 readInt(line, 1, 2, _currEpo.rnxSat[iSat].satNum);
414 char sys = line.toAscii()[0];
415 for (int iType = 0; iType < _header.nTypes(sys); iType++) {
416 int pos = 3 + 16*iType;
417 double obsValue = 0.0;
418 int lli = 0;
419 int snr = 0;
420 readDbl(line, pos, 14, obsValue);
421 readInt(line, pos + 14, 1, lli);
422 readInt(line, pos + 15, 1, snr);
423
424 if (_flgPowerFail) {
425 lli |= 1;
426 }
427
428 _currEpo.rnxSat[iSat].obs.push_back(obsValue);
429 _currEpo.rnxSat[iSat].lli.push_back(lli);
430 _currEpo.rnxSat[iSat].snr.push_back(snr);
431 }
432 }
433
434 _flgPowerFail = false;
435
436 return &_currEpo;
437 }
438
439 return 0;
440}
441
442// Retrieve single Epoch (RINEX Version 2)
443////////////////////////////////////////////////////////////////////////////
444const t_rnxObsFile::t_rnxEpo* t_rnxObsFile::nextEpochV2() {
445
446 while ( _stream->status() == QTextStream::Ok && !_stream->atEnd() ) {
447
448 QString line = _stream->readLine();
449
450 if (line.isEmpty()) {
451 continue;
452 }
453
454 int flag = 0;
455 readInt(line, 28, 1, flag);
456 if (flag > 0) {
457 handleEpochFlag(flag, line);
458 continue;
459 }
460
461 QTextStream in(line.toAscii(), QIODevice::ReadOnly);
462
463 // Epoch Time
464 // ----------
465 int year, month, day, hour, min;
466 double sec;
467 in >> year >> month >> day >> hour >> min >> sec;
468 if (year < 80) {
469 year += 2000;
470 }
471 else if (year < 100) {
472 year += 1900;
473 }
474 _currEpo.tt.set(year, month, day, hour, min, sec);
475
476 // Number of Satellites
477 // --------------------
478 int numSat;
479 readInt(line, 29, 3, numSat);
480
481 _currEpo.rnxSat.resize(numSat);
482
483 // Read Satellite Numbers
484 // ----------------------
485 int pos = 32;
486 for (int iSat = 0; iSat < numSat; iSat++) {
487 if (iSat > 0 && iSat % 12 == 0) {
488 line = _stream->readLine();
489 pos = 32;
490 }
491
492 _currEpo.rnxSat[iSat].satSys = line.toAscii()[pos];
493 readInt(line, pos + 1, 2, _currEpo.rnxSat[iSat].satNum);
494
495 pos += 3;
496 }
497
498 // Read Observation Records
499 // ------------------------
500 for (int iSat = 0; iSat < numSat; iSat++) {
501 line = _stream->readLine();
502 pos = 0;
503 for (int iType = 0; iType < _header.nTypes(_currEpo.rnxSat[iSat].satSys); iType++) {
504 if (iType > 0 && iType % 5 == 0) {
505 line = _stream->readLine();
506 pos = 0;
507 }
508 double obsValue = 0.0;
509 int lli = 0;
510 int snr = 0;
511 readDbl(line, pos, 14, obsValue);
512 readInt(line, pos + 14, 1, lli);
513 readInt(line, pos + 15, 1, snr);
514
515 if (_flgPowerFail) {
516 lli |= 1;
517 }
518
519 _currEpo.rnxSat[iSat].obs.push_back(obsValue);
520 _currEpo.rnxSat[iSat].lli.push_back(lli);
521 _currEpo.rnxSat[iSat].snr.push_back(snr);
522
523 pos += 16;
524 }
525 }
526
527 _flgPowerFail = false;
528
529 return &_currEpo;
530 }
531
532 return 0;
533}
534
535// Set Header Information
536////////////////////////////////////////////////////////////////////////////
537void t_rnxObsFile::setHeader(const t_rnxObsHeader& header) {
538 _header._version = header._version;
539 _header._interval = header._interval;
540 _header._antennaNumber = header._antennaNumber;
541 _header._antennaName = header._antennaName;
542 _header._markerName = header._markerName;
543 _header._markerNumber = header._markerNumber;
544 _header._antNEU = header._antNEU;
545 _header._antXYZ = header._antXYZ;
546 _header._antBSG = header._antBSG;
547 _header._xyz = header._xyz;
548 _header._observer = header._observer;
549 _header._agency = header._agency;
550 _header._receiverNumber = header._receiverNumber;
551 _header._receiverType = header._receiverType;
552 _header._receiverVersion = header._receiverVersion;
553
554 for (unsigned iPrn = 1; iPrn <= MAXPRN_GPS; iPrn++) {
555 _header._wlFactorsL1[iPrn] = header._wlFactorsL1[iPrn];
556 _header._wlFactorsL2[iPrn] = header._wlFactorsL2[iPrn];
557 }
558 _header._startTime = header._startTime;
559 for (unsigned ii = 0; ii < header._obsTypesV2.size(); ii++) {
560 _header._obsTypesV2.push_back(header._obsTypesV2[ii]);
561 }
562 map<char, vector<QString> >::const_iterator it;
563 for (it = header._obsTypesV3.begin(); it != header._obsTypesV3.end(); it++) {
564 char sys = it->first;
565 const vector<QString>& typesV3 = it->second;
566 for (unsigned ii = 0; ii < typesV3.size(); ii++) {
567 _header._obsTypesV3[sys].push_back(typesV3[ii]);
568 }
569 }
570}
571
572// Write Header
573////////////////////////////////////////////////////////////////////////////
574void t_rnxObsFile::writeHeader() {
575
576 bncApp* app = (bncApp*) qApp;
577
578 *_stream << QString("%1 Observation data Mixed")
579 .arg(_header._version, 9, 'f', 2)
580 .leftJustified(60)
581 << "RINEX VERSION / TYPE\n";
582
583 *_stream << QString("%1%2%3")
584 .arg(app->pgmName(), -20)
585 .arg(app->userName(), -20)
586 .arg(currentDateAndTimeGPS().date().toString("dd-MMM-yyyy"), -20)
587 .leftJustified(60)
588 << "PGM / RUN BY / DATE\n";
589
590 *_stream << QString("%1")
591 .arg(_header._markerName, -60)
592 .leftJustified(60)
593 << "MARKER NAME\n";
594
595 if (!_header._markerNumber.isEmpty()) {
596 *_stream << QString("%1")
597 .arg(_header._markerNumber, -20)
598 .leftJustified(60)
599 << "MARKER NUMBER\n";
600 }
601
602 *_stream << QString("%1%2")
603 .arg(_header._observer, -20)
604 .arg(_header._agency, -40)
605 .leftJustified(60)
606 << "OBSERVER / AGENCY\n";
607
608 *_stream << QString("%1%2%3")
609 .arg(_header._receiverNumber, -20)
610 .arg(_header._receiverType, -20)
611 .arg(_header._receiverVersion, -20)
612 .leftJustified(60)
613 << "REC # / TYPE / VERS\n";
614
615 *_stream << QString("%1%2")
616 .arg(_header._antennaNumber, -20)
617 .arg(_header._antennaName, -20)
618 .leftJustified(60)
619 << "ANT # / TYPE\n";
620
621 *_stream << QString("%1%2%3")
622 .arg(_header._xyz(1), 14, 'f', 4)
623 .arg(_header._xyz(2), 14, 'f', 4)
624 .arg(_header._xyz(3), 14, 'f', 4)
625 .leftJustified(60)
626 << "APPROX POSITION XYZ\n";
627
628 *_stream << QString("%1%2%3")
629 .arg(_header._antNEU(3), 14, 'f', 4)
630 .arg(_header._antNEU(2), 14, 'f', 4)
631 .arg(_header._antNEU(1), 14, 'f', 4)
632 .leftJustified(60)
633 << "ANTENNA: DELTA H/E/N\n";
634
635 if (_header._version < 3.0) {
636 int defaultWlFact1 = _header._wlFactorsL1[1];
637 int defaultWlFact2 = _header._wlFactorsL2[1]; // TODO check all prns
638 *_stream << QString("%1%2")
639 .arg(defaultWlFact1, 6)
640 .arg(defaultWlFact2, 6)
641 .leftJustified(60)
642 << "WAVELENGTH FACT L1/2\n";
643 }
644
645 if (_header._version < 3.0) {
646 QString hlp;
647 QTextStream(&hlp) << QString("%1").arg(_header._obsTypesV2.size(), 6);
648 for (unsigned ii = 0; ii < _header._obsTypesV2.size(); ii++) {
649 QTextStream(&hlp) << QString("%1").arg(_header._obsTypesV2[ii], 6);
650 if (ii > 0 && (ii % 8 == 0 || ii == _header._obsTypesV2.size()-1)) {
651 *_stream << hlp.leftJustified(60) << "# / TYPES OF OBSERV\n";
652 hlp = QString().leftJustified(6);
653 }
654 }
655 }
656 else {
657 map<char, vector<QString> >::const_iterator it;
658 for (it = _header._obsTypesV3.begin(); it != _header._obsTypesV3.end(); it++) {
659 char sys = it->first;
660 const vector<QString>& types = it->second;
661 QString hlp;
662 QTextStream(&hlp) << QString("%1 %2").arg(sys).arg(types.size(), 3);
663 for (unsigned ii = 0; ii < types.size(); ii++) {
664 QTextStream(&hlp) << QString(" %1").arg(types[ii], -3);
665 if (ii > 0 && (ii % 12 == 0 || ii == types.size()-1)) {
666 *_stream << hlp.leftJustified(60) << "SYS / # / OBS TYPES\n";
667 hlp = QString().leftJustified(6);
668 }
669 }
670 }
671 }
672
673 *_stream << QString("%1")
674 .arg(_header._interval, 10, 'f', 3)
675 .leftJustified(60)
676 << "INTERVAL\n";
677
678 unsigned year, month, day, hour, min;
679 double sec;
680 _header._startTime.civil_date(year, month, day);
681 _header._startTime.civil_time(hour, min, sec);
682 *_stream << QString("%1%2%3%4%5%6%7")
683 .arg(year, 6)
684 .arg(month, 6)
685 .arg(day, 6)
686 .arg(hour, 6)
687 .arg(min, 6)
688 .arg(sec, 13, 'f', 7)
689 .arg("GPS", 8)
690 .leftJustified(60)
691 << "TIME OF FIRST OBS\n";
692
693 *_stream << QString()
694 .leftJustified(60)
695 << "END OF HEADER\n";
696}
697
698// Write Data Epoch
699////////////////////////////////////////////////////////////////////////////
700void t_rnxObsFile::writeEpoch(const t_rnxEpo* epo) {
701 if (version() < 3.0) {
702 return writeEpochV2(epo);
703 }
704 else {
705 return writeEpochV3(epo);
706 }
707}
708
709// Write Data Epoch (RINEX Version 2)
710////////////////////////////////////////////////////////////////////////////
711void t_rnxObsFile::writeEpochV2(const t_rnxEpo* epo) {
712
713 unsigned year, month, day, hour, min;
714 double sec;
715 epo->tt.civil_date(year, month, day);
716 epo->tt.civil_time(hour, min, sec);
717
718 QString dateStr;
719 QTextStream(&dateStr) << QString(" %1 %2 %3 %4 %5%6")
720 .arg(int(fmod(year, 100)), 2, 10, QChar('0'))
721 .arg(month, 2, 10, QChar('0'))
722 .arg(day, 2, 10, QChar('0'))
723 .arg(hour, 2, 10, QChar('0'))
724 .arg(min, 2, 10, QChar('0'))
725 .arg(sec, 11, 'f', 7);
726
727 int flag = 0;
728 *_stream << dateStr
729 << QString("%1%2").arg(flag, 3).arg(epo->rnxSat.size(), 3);
730 for (unsigned iSat = 0; iSat < epo->rnxSat.size(); iSat++) {
731 const t_rnxSat& rnxSat = epo->rnxSat[iSat];
732 if (iSat > 0 && iSat % 12 == 0) {
733 *_stream << endl << QString().leftJustified(32);
734 }
735 *_stream << rnxSat.satSys << QString("%1").arg(rnxSat.satNum, 2);
736 }
737 *_stream << endl;
738 for (unsigned iSat = 0; iSat < epo->rnxSat.size(); iSat++) {
739 const t_rnxSat& rnxSat = epo->rnxSat[iSat];
740 for (unsigned iType = 0; iType < rnxSat.obs.size(); iType++) {
741 if (iType > 0 && iType % 5 == 0) {
742 *_stream << endl;
743 }
744 if (rnxSat.obs[iType] == 0.0) {
745 *_stream << QString().leftJustified(16);
746 }
747 else {
748 *_stream << QString("%1%2%3")
749 .arg(rnxSat.obs[iType], 14, 'f', 3)
750 .arg(rnxSat.lli[iType],1)
751 .arg(rnxSat.snr[iType],1);
752 }
753 }
754 *_stream << endl;
755 }
756}
757
758// Write Data Epoch (RINEX Version 3)
759////////////////////////////////////////////////////////////////////////////
760void t_rnxObsFile::writeEpochV3(const t_rnxEpo* epo) {
761
762 unsigned year, month, day, hour, min;
763 double sec;
764 epo->tt.civil_date(year, month, day);
765 epo->tt.civil_time(hour, min, sec);
766
767 QString dateStr;
768 QTextStream(&dateStr) << QString("> %1 %2 %3 %4 %5%6")
769 .arg(year, 4)
770 .arg(month, 2, 10, QChar('0'))
771 .arg(day, 2, 10, QChar('0'))
772 .arg(hour, 2, 10, QChar('0'))
773 .arg(min, 2, 10, QChar('0'))
774 .arg(sec, 11, 'f', 7);
775
776 int flag = 0;
777 *_stream << dateStr
778 << QString("%1%2\n").arg(flag, 3).arg(epo->rnxSat.size(), 3);
779
780 for (unsigned iSat = 0; iSat < epo->rnxSat.size(); iSat++) {
781 const t_rnxSat& rnxSat = epo->rnxSat[iSat];
782 *_stream << rnxSat.satSys
783 << QString("%1").arg(rnxSat.satNum, 2, 10, QChar('0'));
784 for (unsigned iType = 0; iType < rnxSat.obs.size(); iType++) {
785 if (rnxSat.obs[iType] == 0.0) {
786 *_stream << QString().leftJustified(16);
787 }
788 else {
789 *_stream << QString("%1%2%3")
790 .arg(rnxSat.obs[iType], 14, 'f', 3)
791 .arg(rnxSat.lli[iType],1)
792 .arg(rnxSat.snr[iType],1);
793 }
794 }
795 *_stream << endl;
796 }
797}
Note: See TracBrowser for help on using the repository browser.