1 //==============================================================================
2 //
3 // This file is part of GPSTk, the GPS Toolkit.
4 //
5 // The GPSTk is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation; either version 3.0 of the License, or
8 // any later version.
9 //
10 // The GPSTk is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with GPSTk; if not, write to the Free Software Foundation,
17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 //
19 // This software was developed by Applied Research Laboratories at the
20 // University of Texas at Austin.
21 // Copyright 2004-2020, The Board of Regents of The University of Texas System
22 //
23 //==============================================================================
24
25 //==============================================================================
26 //
27 // This software was developed by Applied Research Laboratories at the
28 // University of Texas at Austin, under contract to an agency or agencies
29 // within the U.S. Department of Defense. The U.S. Government retains all
30 // rights to use, duplicate, distribute, disclose, or release this software.
31 //
32 // Pursuant to DoD Directive 523024
33 //
34 // DISTRIBUTION STATEMENT A: This software has been approved for public
35 // release, distribution is unlimited.
36 //
37 //==============================================================================
38
39 /**
40 * @file Timetable.cpp
41 * Compute reference satellites time table for program DDBase.
42 */
43
44 //------------------------------------------------------------------------------------
45 //------------------------------------------------------------------------------------
46 // includes
47 // system
48 #include "TimeString.hpp"
49 #include "GPSWeekSecond.hpp"
50
51 // GPSTk
52 // Geomatics
53 #include "DDid.hpp"
54 #include "index.hpp"
55 // DDBase
56 #include "DDBase.hpp"
57
58 //------------------------------------------------------------------------------------
59 using namespace std;
60 using namespace gpstk;
61 using namespace StringUtils;
62
63 //------------------------------------------------------------------------------------
64 // ElevationMask.cpp
65 double RotatedAntennaElevation(double elevation, double azimuth);
66
67 //------------------------------------------------------------------------------------
68 // Segment structure used in deducing time table functions implemented in
69 // Timetable.cpp
70 class TTSegment {
71 public:
72 std::string site1,site2;
73 gpstk::GSatID sat;
74 int start,stop; // starting and ending counts
75 int usestart,usestop; // counts to actually use in timetable
76 int length; // length (in data points)
77 double minelev; // minimum elevation in this segment
78 double maxelev; // maximum elevation in this segment
79
TTSegment(void)80 TTSegment(void)
81 : start(-1), stop(-1), usestart(-1), usestop(-1),
82 length(0), minelev(0.0), maxelev(0.0)
83 {}
metric(void) const84 double metric(void) const
85 { return (double(length)/100.0 + 100.0*(minelev+maxelev)/90.0); }
86
87 void findElev(void);
88
89 friend ostream& operator<<(ostream& s, const TTSegment& t);
90
91 friend bool increasingMetricSort(const TTSegment& left, const TTSegment& right);
92 friend bool decreasingMetricSort(const TTSegment& left, const TTSegment& right);
93 friend bool startSort(const TTSegment& left, const TTSegment& right);
94 };
95
96 //------------------------------------------------------------------------------------
97 // local data
98 list<TTSegment> TimeTable; // satellite time table
99 map<SDid,SDData> SDmap; // map of SD data - not full single differences
100
101 //------------------------------------------------------------------------------------
102 // prototypes -- this module only
103 int ReadTimeTable(void);
104 int ComputeBaselineTimeTable(const string& bl);
105 int TTComputeSingleDifferences(const string& bl, const double ElevLimit);
106 int TimeTableAlgorithm(list<TTSegment>& TTS, list<TTSegment>& TTab);
107 bool startSort(const TTSegment& left, const TTSegment& right);
108 bool increasingMetricSort(const TTSegment& left, const TTSegment& right);
109 bool decreasingMetricSort(const TTSegment& left, const TTSegment& right);
110
111 //------------------------------------------------------------------------------------
112 // Find the entry in the timetable which applies to the baseline given in sdid and
113 // the time tt. Set the satellite in sdid to the reference satellite, and set the
114 // time tt to the time (in the future) when the reference will change again.
115 // return 0 on success, 1 on failure.
QueryTimeTable(SDid & sdid,CommonTime & tt)116 int QueryTimeTable(SDid& sdid, CommonTime& tt)
117 {
118 try {
119 int ntt(static_cast<int>(0.5+(tt-FirstEpoch)/CI.DataInterval));
120 // loop over the timetable, looking for a match : baseline and time
121 list<TTSegment>::iterator ttit;
122 for(ttit=TimeTable.begin(); ttit != TimeTable.end(); ttit++) {
123 if(((ttit->site1 == sdid.site1 && ttit->site2 == sdid.site2) ||
124 (ttit->site1 == sdid.site2 && ttit->site2 == sdid.site1) ) &&
125 ttit->usestart <= ntt && ttit->usestop >= ntt)
126 { // success
127 sdid.sat = ttit->sat;
128 tt = FirstEpoch+CI.DataInterval*ttit->usestop;
129 return 0;
130 }
131 }
132
133 return 1; // failure
134 }
135 catch(Exception& e) { GPSTK_RETHROW(e); }
136 catch(std::exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
137 catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
138 }
139
140 //------------------------------------------------------------------------------------
141 // Find the start and stop counts in the timetable which applies to the given baseline
QueryTimeTable(string baseline,int & beg,int & end)142 int QueryTimeTable(string baseline, int& beg, int& end)
143 {
144 try {
145 string site1=word(baseline,0,'-');
146 string site2=word(baseline,1,'-');
147 beg = end = -1;
148 // loop over the timetable, looking for a match in baseline
149 list<TTSegment>::iterator ttit;
150 for(ttit=TimeTable.begin(); ttit != TimeTable.end(); ttit++) {
151 if((ttit->site1 == site1 && ttit->site2 == site2) ||
152 (ttit->site1 == site2 && ttit->site2 == site1) )
153 { // success
154 if(beg == -1 || ttit->usestart < beg) beg = ttit->usestart;
155 if(end == -1 || ttit->usestop > end) end = ttit->usestop;
156 }
157 }
158 return 0;
159 }
160 catch(Exception& e) { GPSTK_RETHROW(e); }
161 catch(std::exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
162 catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
163 }
164
165 //------------------------------------------------------------------------------------
Timetable(void)166 int Timetable(void)
167 {
168 try {
169 if(CI.Verbose) oflog << "BEGIN Timetable()"
170 << " at total time " << fixed << setprecision(3)
171 << double(clock()-totaltime)/double(CLOCKS_PER_SEC) << " seconds."
172 << endl;
173
174 int iret;
175 size_t ib;
176 list<TTSegment>::iterator ttit;
177
178 if(CI.TimeTableFile.size() > 0) {
179 iret = ReadTimeTable();
180 }
181 else if(CI.RefSat.id != -1) { // user says use this sat only
182 // loop over baselines
183 for(ib=0; ib<Baselines.size(); ib++) {
184 TTSegment ts;
185 ts.site1 = word(Baselines[ib],0,'-');
186 ts.site2 = word(Baselines[ib],1,'-');
187 ts.sat = CI.RefSat;
188 ts.start = ts.usestart = 0;
189 ts.stop = ts.usestop = maxCount;
190 ts.minelev = ts.maxelev = 0.0;
191 ts.length = ts.stop - ts.start + 1;
192 TimeTable.push_back(ts);
193 iret = 0;
194 }
195 }
196 else {
197 // loop over baselines
198 for(ib=0; ib<Baselines.size(); ib++) {
199 iret = ComputeBaselineTimeTable(Baselines[ib]);
200 if(iret) break;
201 } // end loop over baselines
202 }
203
204 if(iret == 0) {
205 // write out timetable to log
206 // REF site site sat week use_start use_stop data_start data_stop
207 CommonTime tt;
208 GSatID sat;
209 oflog << "Here is the time table (" << TimeTable.size() << ")" << endl;
210 if(CI.Screen)
211 cout << "Time table (" << TimeTable.size() << "):" << endl;
212 oflog << "# " << Title << endl;
213 oflog << "# REF site site sat week use_start use_stop data_start data_stop\n";
214 if(CI.Screen)
215 cout << "# REF site site sat week use_start use_stop data_start data_stop\n";
216 for(ttit=TimeTable.begin(); ttit != TimeTable.end(); ttit++) {
217 oflog << "REF " << ttit->site1 << " " << ttit->site2 << " " << ttit->sat;
218 if(CI.Screen)
219 cout << "REF " << ttit->site1 << " " << ttit->site2 << " " << ttit->sat;
220 tt = FirstEpoch + CI.DataInterval * ttit->usestart;
221 oflog << printTime(tt," %4F %10.3g"); // TD week rollover!
222 if(CI.Screen)
223 cout << printTime(tt," %4F %10.3g"); // TD week rollover!
224 tt = FirstEpoch + CI.DataInterval * ttit->usestop;
225 oflog << printTime(tt," %10.3g");
226 if(CI.Screen)
227 cout << printTime(tt," %10.3g");
228 tt = FirstEpoch + CI.DataInterval * ttit->start;
229 oflog << printTime(tt," %10.3g");
230 if(CI.Screen)
231 cout << printTime(tt," %10.3g");
232 tt = FirstEpoch + CI.DataInterval * ttit->stop;
233 oflog << printTime(tt," %10.3g");
234 if(CI.Screen)
235 cout << printTime(tt," %10.3g");
236 // TD? ttit->minelev, ttit->maxelev, ttit->length, ttit->metric()
237 oflog << " " << fixed << setw(4) << setprecision(1) << ttit->minelev;
238 if(CI.Screen)
239 cout << " " << fixed << setw(4) << setprecision(1) << ttit->minelev;
240 oflog << " " << fixed << setw(4) << setprecision(1) << ttit->maxelev;
241 if(CI.Screen)
242 cout << " " << fixed << setw(4) << setprecision(1) << ttit->maxelev;
243 // write the number of counts for this ref
244 oflog << " " << setw(5) << ttit->length;
245 if(CI.Screen)
246 cout << " " << setw(5) << ttit->length;
247 oflog << endl;
248 if(CI.Screen)
249 cout << endl;
250
251 // for next time
252 sat = ttit->sat;
253 }
254 oflog << "End of time table." << endl;
255 if(CI.Screen)
256 cout << "End of time table." << endl;
257 }
258
259 return iret;
260
261 return 0;
262 }
263 catch(Exception& e) { GPSTK_RETHROW(e); }
264 catch(std::exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
265 catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
266 } // end Timetable()
267
268 //------------------------------------------------------------------------------------
269 // Input the time table from a file
ReadTimeTable(void)270 int ReadTimeTable(void)
271 {
272 try {
273 int week;
274 double sow;
275 string line;
276 CommonTime tt;
277
278 // open an input file for all timetables
279 if(CI.Debug) oflog << "Try to open time table file " << CI.TimeTableFile << endl;
280 ifstream ttifs(CI.TimeTableFile.c_str());
281 if(!ttifs) {
282 cerr << "Failed to open input time table file " << CI.TimeTableFile << endl;
283 return -3;
284 }
285
286 //REF site site sat week use_start use_stop data_start data_stop
287 do {
288 getline(ttifs,line);
289 stripTrailing(line,'\r');
290 if(ttifs.eof() || !ttifs.good()) break;
291
292 if(line.size() <= 0) continue; // skip blank lines
293 if(line[0] == '#') continue; // skip comments
294 if(numWords(line) < 9) continue; // TD msg? // skip bad lines
295 if(words(line,0,1) != string("REF")) continue; // only REF lines
296 TTSegment ts;
297 ts.site1 = words(line,1,1);
298 ts.site2 = words(line,2,1);
299 ts.sat.fromString(words(line,3,1));
300
301 week = asInt(words(line,4,1));
302 sow = asInt(words(line,5,1));
303 tt=GPSWeekSecond(week,sow); // TD handle week rollover
304 ts.usestart = int(0.5+(tt-FirstEpoch)/CI.DataInterval);
305
306 sow = asInt(words(line,6,1));
307 tt=GPSWeekSecond(week,sow);
308 ts.usestop = int(0.5+(tt-FirstEpoch)/CI.DataInterval);
309
310 sow = asInt(words(line,7,1));
311 tt=GPSWeekSecond(week,sow);
312 ts.start = int(0.5+(tt-FirstEpoch)/CI.DataInterval);
313
314 sow = asInt(words(line,8,1));
315 tt=GPSWeekSecond(week,sow);
316 ts.stop = int(0.5+(tt-FirstEpoch)/CI.DataInterval);
317
318 //ts.minelev = ts.maxelev = 0.0;
319 ts.length = ts.stop - ts.start + 1;
320 ts.findElev();
321 TimeTable.push_back(ts);
322
323 } while(1);
324 // close the output timetable file
325 ttifs.close();
326
327 oflog << "Read time table from file " << CI.TimeTableFile << endl;
328
329 return 0;
330 }
331 catch(Exception& e) { GPSTK_RETHROW(e); }
332 catch(std::exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
333 catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
334 }
335
336 //------------------------------------------------------------------------------------
ComputeBaselineTimeTable(const string & bl)337 int ComputeBaselineTimeTable(const string& bl)
338 {
339 try {
340 int j;
341 size_t i;
342 map<SDid,SDData>::const_iterator it;
343 list<TTSegment> SegList;
344
345 SDmap.clear();
346 i = TTComputeSingleDifferences(bl,40.0);
347 if(i) return i;
348
349 // now compute the timetable based on SDmap
350 for(it=SDmap.begin(); it != SDmap.end(); it++) {
351 TTSegment ts;
352 ts.site1 = it->first.site1;
353 ts.site2 = it->first.site2;
354 ts.sat = it->first.sat;
355 ts.start = it->second.count[0];
356 ts.minelev = ts.maxelev = 0.0;
357 for(i=0; i<it->second.count.size()-1; i++) {
358 j = it->second.count.at(i+1) - it->second.count.at(i);
359 if(j > 1) {
360 TTSegment tts;
361 tts = ts;
362 tts.stop = it->second.count.at(i);
363 tts.length = tts.stop - tts.start + 1;
364 tts.findElev();
365 SegList.push_back(tts);
366 ts.start = it->second.count.at(i+1);
367 }
368 }
369 ts.stop = it->second.count[it->second.count.size()-1];
370 ts.length = ts.stop - ts.start + 1;
371 ts.findElev();
372 SegList.push_back(ts);
373 }
374
375 if(SegList.size() == 0) return -2;
376
377 // figure out the time table from the list of segments
378 list<TTSegment> TTable;
379 i = TimeTableAlgorithm(SegList, TTable);
380 if(i) return i;
381
382 // add this timetable to the master timetable.
383 list<TTSegment>::iterator ttit;
384 for(ttit=TTable.begin(); ttit != TTable.end(); ttit++)
385 TimeTable.push_back(*ttit);
386
387 return 0;
388 }
389 catch(Exception& e) { GPSTK_RETHROW(e); }
390 catch(std::exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
391 catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
392 }
393
394 //------------------------------------------------------------------------------------
TTComputeSingleDifferences(const string & bl,const double ElevLimit)395 int TTComputeSingleDifferences(const string& bl, const double ElevLimit)
396 {
397 try {
398 size_t i,j;
399 int k;
400 const size_t MinSize = 10;
401 double elevi,elevj;
402 GSatID sat;
403 map<GSatID,RawData>::const_iterator it,jt;
404 map<SDid,SDData>::const_iterator kt;
405 ofstream rawofs;
406 format f62(6,2),f133(13,3);
407
408 // loop over buffered raw data of sats common to both
409 string est=word(bl,0,'-');
410 string fix=word(bl,1,'-');
411
412 for(it=Stations[est].RawDataBuffers.begin();
413 it != Stations[est].RawDataBuffers.end(); it++) {
414
415 // consider each satellite
416 sat = it->first;
417 if(CI.Verbose) oflog << "Single difference " << est << " " << fix << " " << sat;
418
419 // is sat also found at fixed site?
420 jt = Stations[fix].RawDataBuffers.find(sat);
421 if(jt == Stations[fix].RawDataBuffers.end()) {
422 if(CI.Verbose) oflog << " not found on both sites" << endl;
423 continue;
424 }
425
426 if(CI.Verbose) oflog << " (raw buffers size: " << it->second.count.size()
427 << " " << jt->second.count.size() << ")";
428
429 // is there enough data in the buffers?
430 if(it->second.count.size() < MinSize || jt->second.count.size() < MinSize) {
431 if(CI.Verbose) oflog << " raw buffers size too small: "
432 << it->second.count.size() << " and " << jt->second.count.size() << endl;
433 continue;
434 }
435
436 // compute continuous segments of SD data
437 // sdd.count is the intersection of the two count vectors
438 SDid sdid(fix,est,sat);
439 SDData sdd;
440 sdd.elevmin = 100.0;
441 sdd.elevmax = -1.0;
442 i = j = 0;
443 do {
444 if(it->second.count[i] == jt->second.count[j]) {
445 elevi = RotatedAntennaElevation(it->second.elev[i],it->second.az[i]);
446 elevj = RotatedAntennaElevation(jt->second.elev[j],jt->second.az[j]);
447 if(elevi >= ElevLimit && elevj >= ElevLimit) {
448 sdd.count.push_back(it->second.count[i]);
449 if(elevi < sdd.elevmin) sdd.elevmin = elevi;
450 if(elevi > sdd.elevmax) sdd.elevmax = elevi;
451 }
452 i++;
453 j++;
454 }
455 else if(it->second.count[i] < jt->second.count[j]) {
456 i++;
457 }
458 else {
459 j++;
460 }
461 } while( i < it->second.count.size() &&
462 j < jt->second.count.size() );
463
464 // TD ?
465 if(sdd.count.size() < MinSize) {
466 if(CI.Verbose) oflog << " size is too small ("
467 << sdd.count.size() << ")" << endl;
468 continue;
469 }
470
471 // save it in the map
472 SDmap[sdid] = sdd;
473
474 if(CI.Verbose) oflog << endl;
475
476 } // end loop over raw buffered data common to both sites
477
478 // write out a summary of single differences
479 oflog << "Single differences summary :" << endl;
480 for(k=1,kt=SDmap.begin(); kt != SDmap.end(); kt++,k++) {
481 oflog << " " << setw(2) << k << " " << kt->first
482 << " " << setw(5) << kt->second.count.size()
483 << " " << setw(5) << kt->second.count.at(0)
484 << " - " << setw(5) << kt->second.count.at(kt->second.count.size()-1);
485 // elevation
486 oflog << " elev: "
487 << fixed << setw(4) << setprecision(1) << kt->second.elevmin
488 << " - " << setw(4) << setprecision(1) << kt->second.elevmax;
489 // gaps - (count : number of pts)
490 for(i=0; i<kt->second.count.size()-1; i++) {
491 j = kt->second.count.at(i+1) - kt->second.count.at(i);
492 if(j > 1)
493 oflog << " (" << kt->second.count.at(i)+1 << ":" << j-1 << ")";
494 }
495 oflog << endl;
496 }
497
498 if(SDmap.size() == 0) {
499 oflog << "Returning error code -1 from TTComputeSingleDifferences()" << endl;
500 return -1;
501 }
502
503 return 0;
504 }
505 catch(Exception& e) { GPSTK_RETHROW(e); }
506 catch(std::exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
507 catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
508 }
509
510 //------------------------------------------------------------------------------------
511 // preprocess the segment list - get first and last counts
TimeTableAlgorithm(list<TTSegment> & TTS,list<TTSegment> & TTab)512 int TimeTableAlgorithm(list<TTSegment>& TTS, list<TTSegment>& TTab)
513 {
514 try {
515 bool keep;
516 int i,beg=0,end;
517 int begcount,endcount;
518 list<TTSegment>::iterator ttit,ttjt;
519 typedef pair<int,int> seg;
520 list<seg> Segs;
521 list<seg>::iterator lit,ljt;
522
523 // 0 sort list in order of decreasing metric()
524 // 0.5 delete very small segments
525 // 0.6 run through the list, finding the smallest begin, and largest end, counts;
526 // call these the begin and end counts.
527 // 1. run through the sorted list, starting at largest metric(), and pick out
528 // first segments which have the begin and/or end counts; add these to TTab
529 // and erase from TTS.
530 // 2. run through TTS again, starting at the largest metric(); if a segment
531 // includes some counts that have not been covered before, than add this
532 // to TTab and erase from TTS. Quit when either the entire range from
533 // begcount to endcount is covered, a given minimum metric() is reached,
534 // or when the end of TTS is reached.
535 // 3. if gaps remain in the coverage, these are real gaps in the data and
536 // the estimation will have to reset.
537 // 4. sort TTab in increasing order. Run through TTab looking for
538 // segments which can be removed without generating gaps; remove these.
539
540 // 0. sort in reverse order (largest metric() first)
541 // [ list has its own sort sort(TTS.rbegin(),TTS.rend()); ]
542 TTS.sort(decreasingMetricSort);
543
544 // 0.5 delete very small segments and output the sorted list
545 // 0.6 find begcount and endcount (after deletion)
546 begcount = endcount = -1;
547 oflog << "Here is the sorted list of segments:" << endl;
548 for(i=1,ttit=TTS.begin(); ttit != TTS.end(); i++) {
549 oflog << " " << setw(4) << i << *ttit;
550 if(ttit->length < 10) {
551 oflog << " -- delete this segment: too small";
552 ttit = TTS.erase(ttit); // ttit now points to next seg
553 }
554 else {
555 if(begcount < 0 || ttit->start < begcount)
556 begcount = ttit->start;
557 if(endcount < 0 || ttit->stop > endcount)
558 endcount = ttit->stop;
559 ttit++;
560 }
561 oflog << endl;
562 }
563 oflog << "End the sorted list; limits : " << begcount << " - " << endcount << endl;
564
565 // 1.find the begin point
566 for(ttit=TTS.begin(); ttit != TTS.end(); ttit++) {
567 if(ttit->start == begcount) {
568 oflog << "Found the begin time: " << *ttit << endl;
569 TTab.push_back(*ttit);
570 beg = ttit->stop;
571 TTS.erase(ttit);
572 break;
573 }
574 }
575
576 if(beg == endcount) {
577 // one segment covers it all - done!
578 oflog << "One segment covers it all!" << endl;
579 end = endcount;
580 }
581 else {
582 // find the end point
583 for(ttit=TTS.begin(); ttit != TTS.end(); ttit++) {
584 if(ttit->stop == endcount) {
585 oflog << "Found the end time: " << *ttit << endl;
586 TTab.push_back(*ttit);
587 end = ttit->start;
588 TTS.erase(ttit);
589 break;
590 }
591 }
592
593 if(TTab.size() != 2) {
594 // error, we didn't find the beg and end -- throw?
595 return -2;
596 }
597 }
598
599 // start list of segs with the ones that contain endpoints
600 ttit = TTab.begin();
601 Segs.push_back(make_pair(ttit->start,ttit->stop));
602 ttit++;
603 if(ttit != TTab.end())
604 Segs.push_back(make_pair(ttit->start,ttit->stop));
605
606 if(beg >= end) { // two segments cover it all
607 if(Segs.size() > 1) { // TD unsure if the logic is wrong here...
608 ljt = lit = Segs.begin();
609 ljt++;
610 lit->second = ljt->second;
611 if(CI.Debug) oflog << "Two segments cover it all: erase seg ("
612 << ljt->first << "-" << ljt->second << ")" << endl;
613 Segs.erase(ljt);
614 }
615 }
616 else {
617 // 2.
618 // start with
619 // |======1st Seg======| gap |=====last Seg======|
620 //
621 // in general, new segs can be added, so Segs looks like this:
622 // |===1st Seg===| gap |===2nd Seg===| gap |===last Seg===|
623 //
624 // consider 8 cases of new segments from TTS:
625 // 1. |--------------| covers end of seg
626 // 2. |-------| lies entirely w/in gap
627 // 3. |--------| covers beg of seg
628 // 4. |--------------------| covers entire gap
629 // 5. |----------------------| covers entire seg
630 // 6. covers seg and gap |-------------------------------------|
631 // 7. |-------------------------------------| covers gap and seg
632 // 8. |-----| lies entirely w/in seg
633 //
634 // Here is the algorithm:
635 // for each new segment extending from b to e
636 // for each i in list of segments in list (extending bi to ei) {
637 // if(b > ei) skip to the next i
638 // if(e > ei) { // b <= ei and e > ei
639 // mod seg i so that ei -> e // case 1,4,7
640 // if(b < bi) mod seg i so that bi -> b // case 5,6
641 // while (e >= bj) where j > i,
642 // merge segments i and j and delete j // case 4,6,7
643 // keep this segment
644 // }
645 // else { // b <= ei and e <= ei
646 // if(e >= bi) {
647 // if(b < bi) {
648 // mod segment i so bi -> b // case 3
649 // keep this segment
650 // }
651 // //else { ignore this segment } // case 8
652 // }
653 // else {
654 // make a new segment (b,e),
655 // and insert it before segment i // case 2
656 // keep this segment
657 // }
658 // }
659 // } // end of loop over segments i
660 // if(keep) add this segment to the time table
661 //
662 // loop over all segments, in decreasing order of metric()
663 for(i=1,ttit=TTS.begin(); ttit != TTS.end(); i++,ttit++) { // i temp
664
665 if(CI.Debug) { // temp
666 oflog << "Here is the current time table (" << TTab.size() << ")"
667 << endl;
668 for(ttjt=TTab.begin(); ttjt != TTab.end(); ttjt++)
669 oflog << " " << *ttjt << endl;
670 }
671
672 if(CI.Debug) {
673 oflog << "and here is the seg list";
674 for(lit=Segs.begin(); lit != Segs.end(); lit++)
675 oflog << " (" << lit->first << "-" << lit->second << ")";
676 oflog << endl;
677 }
678
679 // done if one segment covers all
680 lit = Segs.begin();
681 if(Segs.size() == 1 && lit->first == begcount && lit->second == endcount)
682 break;
683
684 // keep this? you don't want metric to become very small -> failure
685 if(ttit->metric() <= 100.0) break; // TD input param
686
687 beg = ttit->start;
688 end = ttit->stop;
689 if(CI.Debug) oflog << "consider new segment ("
690 << beg << "-" << end << ")" << endl;
691
692 // loop over the segs
693 keep = false;
694 lit = Segs.begin();
695 while(lit != Segs.end()) {
696 if(beg > lit->second) {
697 if(CI.Debug) oflog << " skip seg ("
698 << lit->first << "-" << lit->second << ")" << endl;
699 lit++;
700 continue;
701 }
702 if(end > lit->second) {
703 if(CI.Debug) oflog << " mod 1 seg ("
704 << lit->first << "-" << lit->second << ")";
705 lit->second = end;
706 if(beg < lit->first) lit->first=beg;
707 if(CI.Debug) oflog << " to ("
708 << lit->first << "-" << lit->second << ")" << endl;
709 ljt = lit;
710 while(++ljt != Segs.end() && end >= ljt->first) {
711 // merge i and j
712 if(CI.Debug) oflog << " merge segs ("
713 << lit->first << "-" << lit->second << ") and ("
714 << ljt->first << "-" << ljt->second << ")";
715 lit->second = ljt->second;
716 if(CI.Debug) oflog << " and erase seg ("
717 << ljt->first << "-" << ljt->second << ")" << endl;
718 Segs.erase(ljt);
719 ljt = lit;
720 }
721 keep = true;
722 }
723 else {
724 if(end >= lit->first) {
725 if(beg < lit->first) {
726 if(CI.Debug) oflog << " mod 2 seg ("
727 << lit->first << "-" << lit->second << ")";
728 lit->first = beg;
729 keep = true;
730 if(CI.Debug) oflog << " to ("
731 << lit->first << "-" << lit->second << ")" << endl;
732 }
733 //else { keep=false; ignore -- this seg has nothing new }
734 }
735 else {
736 seg newseg(beg,end);
737 if(CI.Debug) oflog << " add seg ("
738 << newseg.first << "-" << newseg.second << ")" << endl;
739 Segs.insert(lit,newseg);
740 keep = true;
741 }
742 }
743 break;
744 } // end while loop over segs
745
746 if(keep) {
747 TTab.push_back(*ttit);
748 TTab.sort(startSort); // temp
749 }
750
751 if(CI.Debug) if(i > 100) break; // temp
752
753 } // end for loop over segments TTS
754
755 } // end if(initial gap is non-zero)
756
757 // 3. are there gaps?
758 if(Segs.size() != 1) {
759 oflog << "There are real gaps in the data; segments with data:" << endl;
760 for(lit=Segs.begin(); lit != Segs.end(); lit++)
761 oflog << " (" << lit->first << "-" << lit->second << ")";
762 oflog << endl;
763 }
764 else oflog << "There are no gaps in the data" << endl;
765
766 // sort the timetable
767 TTab.sort(startSort);
768
769 // TD 4. edit TTab, removing segments that do not create gaps
770
771 // decide on actual transition times
772 for(ttit=TTab.begin(); ttit != TTab.end(); ttit++) {
773 //if(CI.Verbose) oflog << " " << *ttit << endl;
774
775 // compute the count at which to switch
776 if(ttit == TTab.begin()) {
777 ttit->usestart = ttit->start; // usestart = start for first segment
778 ttjt = ttit; // initialize ttjt
779 }
780 else if(ttjt->stop > ttit->start) { // if there is overlap, switch at midpoint
781 ttit->usestart = (ttjt->stop + ttit->start)/2;
782 }
783 else {
784 ttit->usestart = ttit->start; // there is a gap
785 }
786 ttit->usestop = ttit->stop; // change later, except for last segment
787 if(ttit != TTab.begin()) {
788 ttjt->usestop = ttit->usestart; // count at the switch point
789 ttjt++; // ttjt lags behind ttit by 1
790 }
791 }
792
793 return 0;
794 }
795 catch(Exception& e) { GPSTK_RETHROW(e); }
796 catch(std::exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
797 catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
798 }
799
800 //------------------------------------------------------------------------------------
findElev(void)801 void TTSegment::findElev(void)
802 {
803 int i,k;
804 double elevi;
805 RawData& rd=Stations[site1].RawDataBuffers[sat];
806 minelev = 99.0;
807 maxelev = -1.0;
808 k = index(rd.count,start);
809 if(k == -1) return;
810 for(i=k; i<k+length; i++) {
811 elevi = RotatedAntennaElevation(rd.elev.at(i),rd.az.at(i));
812 if(elevi > maxelev) maxelev = elevi;
813 if(elevi < minelev) minelev = elevi;
814 }
815 }
816
817 //------------------------------------------------------------------------------------
818 // friends of TTSegment, defined there
startSort(const TTSegment & left,const TTSegment & right)819 bool startSort(const TTSegment& left, const TTSegment& right)
820 { return (left.start < right.start); }
821
increasingMetricSort(const TTSegment & left,const TTSegment & right)822 bool increasingMetricSort(const TTSegment& left, const TTSegment& right)
823 { return (left.metric() < right.metric()); }
824
decreasingMetricSort(const TTSegment & left,const TTSegment & right)825 bool decreasingMetricSort(const TTSegment& left, const TTSegment& right)
826 { return (left.metric() > right.metric()); }
827
828 //------------------------------------------------------------------------------------
operator <<(ostream & os,const TTSegment & t)829 ostream& operator<<(ostream& os, const TTSegment& t)
830 {
831 try {
832 os << " " << t.site1
833 << " " << t.site2
834 << " " << t.sat
835 << " " << setw(5) << t.length
836 << " " << setw(5) << t.start
837 << " - " << setw(5) << t.stop
838 << " " << fixed << setw(4) << setprecision(1) << t.minelev
839 << " - " << fixed << setw(4) << setprecision(1) << t.maxelev
840 << " " << setw(7) << setprecision(2) << t.metric();
841 return os;
842 }
843 catch(Exception& e) { GPSTK_RETHROW(e); }
844 catch(std::exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
845 catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
846 }
847
848 //------------------------------------------------------------------------------------
849 //------------------------------------------------------------------------------------
850