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

Last change on this file since 3903 was 3869, checked in by mervart, 13 years ago
File size: 20.8 KB
RevLine 
[3716]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>
[3722]44#include "rnxobsfile.h"
[3716]45#include "bncutils.h"
[3850]46#include "bncversion.h"
[3716]47
48using namespace std;
49
[3718]50const QString t_rnxObsFile::t_rnxObsHeader::_emptyStr;
[3716]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////////////////////////////////////////////////////////////////////////////
[3718]74t_irc t_rnxObsFile::t_rnxObsHeader::read(QTextStream* stream, int maxLines) {
[3716]75 int numLines = 0;
[3718]76 while ( stream->status() == QTextStream::Ok && !stream->atEnd() ) {
77 QString line = stream->readLine(); ++ numLines;
78 if (line.isEmpty()) {
[3716]79 continue;
80 }
[3718]81 if (line.indexOf("END OF FILE") != -1) {
[3716]82 break;
83 }
[3718]84 QString value = line.mid(0,60).trimmed();
85 QString key = line.mid(60).trimmed();
[3716]86 if (key == "END OF HEADER") {
87 break;
88 }
89 else if (key == "RINEX VERSION / TYPE") {
[3718]90 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
[3716]91 in >> _version;
92 }
93 else if (key == "MARKER NAME") {
94 _markerName = value;
95 }
96 else if (key == "ANT # / TYPE") {
[3718]97 _antennaName = line.mid(20,20).trimmed();
[3716]98 }
99 else if (key == "INTERVAL") {
[3718]100 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
[3716]101 in >> _interval;
102 }
103 else if (key == "WAVELENGTH FACT L1/2") {
[3718]104 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
[3716]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++) {
[3718]117 QString prn; in >> prn;
[3716]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") {
[3718]128 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
[3716]129 in >> _xyz[0] >> _xyz[1] >> _xyz[2];
130 }
131 else if (key == "ANTENNA: DELTA H/E/N") {
[3718]132 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
[3716]133 in >> _antNEU[2] >> _antNEU[1] >> _antNEU[0];
134 }
135 else if (key == "ANTENNA: DELTA X/Y/Z") {
[3718]136 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
[3716]137 in >> _antXYZ[0] >> _antXYZ[1] >> _antXYZ[2];
138 }
139 else if (key == "ANTENNA: B.SIGHT XYZ") {
[3718]140 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
[3716]141 in >> _antBSG[0] >> _antBSG[1] >> _antBSG[2];
142 }
143 else if (key == "# / TYPES OF OBSERV") {
[3864]144 QTextStream* in = new QTextStream(value.toAscii(), QIODevice::ReadOnly);
[3716]145 int nTypes;
[3864]146 *in >> nTypes;
[3716]147 _obsTypesV2.clear();
148 for (int ii = 0; ii < nTypes; ii++) {
[3864]149 if (ii > 0 && ii % 9 == 0) {
150 line = stream->readLine(); ++numLines;
151 delete in;
152 in = new QTextStream(line.toAscii(), QIODevice::ReadOnly);
153 }
[3718]154 QString hlp;
[3864]155 *in >> hlp;
[3716]156 _obsTypesV2.push_back(hlp);
157 }
158 }
159 else if (key == "SYS / # / OBS TYPES") {
[3718]160 QTextStream* in = new QTextStream(value.toAscii(), QIODevice::ReadOnly);
[3716]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) {
[3718]167 line = stream->readLine(); ++numLines;
[3716]168 delete in;
[3718]169 in = new QTextStream(line.toAscii(), QIODevice::ReadOnly);
[3716]170 }
[3718]171 QString hlp;
[3716]172 *in >> hlp;
173 _obsTypesV3[sys].push_back(hlp);
174 }
175 delete in;
176 }
[3837]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 }
[3716]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 {
[3718]199 map<char, vector<QString> >::const_iterator it = _obsTypesV3.find(sys);
[3716]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////////////////////////////////////////////////////////////////////////////
[3718]211const QString& t_rnxObsFile::t_rnxObsHeader::obsType(char sys, int index) const {
[3716]212 if (_version < 3.0) {
213 return _obsTypesV2.at(index);
214 }
215 else {
[3718]216 map<char, vector<QString> >::const_iterator it = _obsTypesV3.find(sys);
[3716]217 if (it != _obsTypesV3.end()) {
218 return it->second.at(index);
219 }
220 else {
221 return _emptyStr;
222 }
223 }
224}
225
226// Constructor
227////////////////////////////////////////////////////////////////////////////
[3843]228t_rnxObsFile::t_rnxObsFile(const QString& fileName, e_inpOut inpOut) {
229 _inpOut = inpOut;
[3716]230 _stream = 0;
231 _flgPowerFail = false;
[3843]232 if (_inpOut == input) {
233 openRead(fileName);
234 }
235 else {
[3845]236 openWrite(fileName);
[3843]237 }
[3716]238}
239
[3845]240// Open for input
[3716]241////////////////////////////////////////////////////////////////////////////
[3843]242void t_rnxObsFile::openRead(const QString& fileName) {
[3718]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
[3716]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) {
[3718]259 throw QString("t_rnxObsFile: not enough epochs");
[3716]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 }
[3719]269 _stream->seek(0);
[3716]270 _header.read(_stream);
271 }
[3837]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 }
[3716]284}
285
[3845]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
[3716]297// Destructor
298////////////////////////////////////////////////////////////////////////////
299t_rnxObsFile::~t_rnxObsFile() {
300 close();
301}
302
303// Close
304////////////////////////////////////////////////////////////////////////////
305void t_rnxObsFile::close() {
306 delete _stream; _stream = 0;
[3718]307 delete _file; _file = 0;
[3716]308}
309
310// Handle Special Epoch Flag
311////////////////////////////////////////////////////////////////////////////
[3718]312void t_rnxObsFile::handleEpochFlag(int flag, const QString& line) {
[3716]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 {
[3718]342 throw QString("t_rnxObsFile: unhandled flag\n" + line);
[3716]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
[3719]364 while ( _stream->status() == QTextStream::Ok && !_stream->atEnd() ) {
[3716]365
[3718]366 QString line = _stream->readLine();
[3716]367
[3718]368 if (line.isEmpty()) {
[3716]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
[3718]379 QTextStream in(line.mid(1).toAscii(), QIODevice::ReadOnly);
[3716]380
381 // Epoch Time
382 // ----------
383 int year, month, day, hour, min;
384 double sec;
385 in >> year >> month >> day >> hour >> min >> sec;
[3720]386 _currEpo.tt.set(year, month, day, hour, min, sec);
[3716]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++) {
[3718]398 line = _stream->readLine();
[3719]399 _currEpo.rnxSat[iSat].satSys = line.toAscii()[0];
[3716]400 readInt(line, 1, 2, _currEpo.rnxSat[iSat].satNum);
[3719]401 char sys = line.toAscii()[0];
[3716]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
[3719]433 while ( _stream->status() == QTextStream::Ok && !_stream->atEnd() ) {
[3716]434
[3718]435 QString line = _stream->readLine();
[3716]436
[3718]437 if (line.isEmpty()) {
[3716]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
[3718]448 QTextStream in(line.toAscii(), QIODevice::ReadOnly);
[3716]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 }
[3720]461 _currEpo.tt.set(year, month, day, hour, min, sec);
[3716]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) {
[3718]475 line = _stream->readLine();
[3716]476 pos = 32;
477 }
478
[3719]479 _currEpo.rnxSat[iSat].satSys = line.toAscii()[pos];
[3716]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++) {
[3718]488 line = _stream->readLine();
[3716]489 pos = 0;
490 for (int iType = 0; iType < _header.nTypes(_currEpo.rnxSat[iSat].satSys); iType++) {
491 if (iType > 0 && iType % 5 == 0) {
[3718]492 line = _stream->readLine();
[3716]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
[3844]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}
[3845]550
551// Write Header
552////////////////////////////////////////////////////////////////////////////
553void t_rnxObsFile::writeHeader() {
[3849]554 *_stream << QString("%1 Observation data Mixed")
[3848]555 .arg(_header._version, 9, 'f', 2)
[3849]556 .leftJustified(60)
[3848]557 << "RINEX VERSION / TYPE\n";
558
559 *_stream << QString("%1%2%3")
[3850]560 .arg("BNC "BNCVERSION, -20)
[3848]561 .arg("BKG", -20)
562 .arg(currentDateAndTimeGPS().date().toString("dd-MMM-yyyy"), -20)
[3849]563 .leftJustified(60)
[3848]564 << "PGM / RUN BY / DATE\n";
[3849]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
[3851]586 .arg(_header._antennaName, -20)
587 .leftJustified(60)
[3849]588 << "ANT # / TYPE\n";
589
[3851]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
[3852]604 QString hlp;
[3864]605 QTextStream(&hlp) << QString("%1").arg(_header._obsTypesV2.size(), 6);
[3852]606 for (unsigned ii = 0; ii < _header._obsTypesV2.size(); ii++) {
[3864]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";
[3865]610 hlp = QString().leftJustified(6);
[3864]611 }
[3852]612 }
613
[3854]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
[3849]634 *_stream << QString()
635 .leftJustified(60)
636 << "END OF HEADER\n";
[3845]637}
638
639// Write Data Epoch
640////////////////////////////////////////////////////////////////////////////
641void t_rnxObsFile::writeEpoch(const t_rnxEpo* epo) {
[3866]642 if (version() < 3.0) {
643 return writeEpochV2(epo);
644 }
645 else {
646 return writeEpochV3(epo);
647 }
648}
[3855]649
[3866]650// Write Data Epoch (RINEX Version 2)
651////////////////////////////////////////////////////////////////////////////
652void t_rnxObsFile::writeEpochV2(const t_rnxEpo* epo) {
653
[3855]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;
[3868]660 QTextStream(&dateStr) << QString(" %1 %2 %3 %4 %5%6")
[3856]661 .arg(int(fmod(year, 100)), 2, 10, QChar('0'))
[3868]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);
[3855]667
[3857]668 int flag = 0;
669 *_stream << dateStr
670 << QString("%1%2").arg(flag, 3).arg(epo->rnxSat.size(), 3);
[3858]671 for (unsigned iSat = 0; iSat < epo->rnxSat.size(); iSat++) {
[3869]672 const t_rnxSat& rnxSat = epo->rnxSat[iSat];
[3858]673 if (iSat > 0 && iSat % 12 == 0) {
[3857]674 *_stream << endl << QString().leftJustified(32);
675 }
[3869]676 *_stream << rnxSat.satSys << QString("%1").arg(rnxSat.satNum, 2);
[3857]677 }
678 *_stream << endl;
[3858]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 }
[3845]697}
[3866]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
[3867]708 QString dateStr;
[3868]709 QTextStream(&dateStr) << QString("> %1 %2 %3 %4 %5%6")
[3867]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);
[3866]716
[3867]717 int flag = 0;
718 *_stream << dateStr
719 << QString("%1%2\n").arg(flag, 3).arg(epo->rnxSat.size(), 3);
720
[3869]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 }
[3866]738}
Note: See TracBrowser for help on using the repository browser.