~ubuntu-branches/ubuntu/warty/xplanet/warty

« back to all changes in this revision

Viewing changes to libannotate/drawSatellite.cc

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-08-24 07:14:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040824071400-2dr4qnjbjmm8z3ia
Tags: 1.0.6-1ubuntu1
Build-depend: libtiff4-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/****************************************************************************
2
 
    Xplanet 0.94 - render an image of a planet into an X window
3
 
    Copyright (C) 2002 Hari Nair <hari@alumni.caltech.edu>
4
 
 
5
 
    This program is free software; you can redistribute it and/or modify
6
 
    it under the terms of the GNU General Public License as published by
7
 
    the Free Software Foundation; either version 2 of the License, or
8
 
    (at your option) any later version.
9
 
 
10
 
    This program 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 General Public License for more details.
14
 
 
15
 
    You should have received a copy of the GNU General Public License
16
 
    along with this program; if not, write to the Free Software
17
 
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 
****************************************************************************/
19
 
 
20
 
#include <cmath>
21
 
#include <cstdio>
22
 
#include <fstream>
23
 
#include <iostream>
24
 
#include <string>
25
 
using namespace std;
26
 
 
27
 
#include <unistd.h>
28
 
 
29
 
#include "auxfiles.h"
30
 
#include "Location.h"
31
 
#include "Options.h"
32
 
#include "parse.h"
33
 
#include "Satellite.h"
34
 
#include "util.h"
35
 
 
36
 
static list<Satellite> full_satellite_list;  // need this for -sattrackid
37
 
 
38
 
static bool
39
 
satelliteFileExists(string &filename)
40
 
{
41
 
    if (opts.debug) 
42
 
    {
43
 
        cout << "\nLooking for satellite file ...\n"
44
 
             << filename << endl;
45
 
    }
46
 
 
47
 
    if (fileExists(filename)) return(true);
48
 
 
49
 
    string satellite_file = "satellites";
50
 
    satellite_file += separator;
51
 
    satellite_file += filename;
52
 
    
53
 
    if (fileExists(satellite_file))
54
 
    {
55
 
        filename = satellite_file;
56
 
        return(true);
57
 
    }
58
 
 
59
 
    satellite_file = prefix;
60
 
    satellite_file += separator;
61
 
    satellite_file += "satellites";
62
 
    satellite_file += separator;
63
 
    satellite_file += filename;
64
 
 
65
 
    if (fileExists(satellite_file))
66
 
    {
67
 
        filename = satellite_file;
68
 
        return(true);
69
 
    }
70
 
 
71
 
    return(false);
72
 
}
73
 
 
74
 
//  Given an value X and radius d, this routine draws a half-circle in
75
 
//  the plane where X is constant.
76
 
static void
77
 
drawAltitudeHalfCirc(const double rot[3][3], const double X, const double d,
78
 
                     bool Z_positive, const string arcopts, ofstream &sat_a)
79
 
{
80
 
    double Y = d;
81
 
    double Z = (1 - X*X - Y*Y);
82
 
    if (fabs(Z) < 1e-5) Z = 0;
83
 
    Z = (Z_positive ? sqrt(Z) : -sqrt(Z));
84
 
 
85
 
    Location point(0);
86
 
    point.setXYZ(X, Y, Z);
87
 
    point.rotate(rot);
88
 
    point.rectangularToSpherical();
89
 
 
90
 
    for (double siny = 1; siny >= -1; siny -= 1./10.)
91
 
    {
92
 
        double prev_lat = point.lat;
93
 
        double prev_lon = point.lon;
94
 
 
95
 
        Y = sin(M_PI_2 * siny) * d;
96
 
        Z = (1 - X*X - Y*Y);
97
 
        if (fabs(Z) < 1e-5) Z = 0;
98
 
        Z = (Z_positive ? sqrt(Z) : -sqrt(Z));
99
 
 
100
 
        point.setXYZ(X, Y, Z);
101
 
        point.rotate(rot);
102
 
        point.rectangularToSpherical();
103
 
        sat_a << prev_lat/deg_to_rad << '\t' << prev_lon/deg_to_rad 
104
 
              << '\t' << point.lat/deg_to_rad 
105
 
              << '\t' << point.lon/deg_to_rad;
106
 
        if (!arcopts.empty()) sat_a << " " << arcopts;
107
 
        sat_a << endl;
108
 
    }
109
 
}
110
 
 
111
 
// write the entry in the marker/arc file for this satellite
112
 
static void
113
 
writeSatFiles(Satellite *this_sat, char *options, 
114
 
              ofstream &sat_a, ofstream &sat_m)
115
 
{
116
 
    string arcopts;
117
 
 
118
 
    int align = AUTO;
119
 
    list<double> altcirc;
120
 
    string color;
121
 
    
122
 
    string font;
123
 
    int fontsize = opts.fontsize;
124
 
    
125
 
    string image;
126
 
    string name = this_sat->getName();
127
 
    
128
 
    char *returnstring = NULL;
129
 
    
130
 
    int trail_type = ORBIT;
131
 
    int trail_start = 0;
132
 
    int trail_end = 0;
133
 
    int trail_interval = 1;
134
 
    string transparency;
135
 
    
136
 
    bool end_of_line = false;
137
 
    bool syntax_error = false;
138
 
 
139
 
    int i = 0;
140
 
    while (!end_of_line)
141
 
    {
142
 
        switch (parse(i, options, returnstring))
143
 
        {
144
 
        case ALIGN:
145
 
            if (returnstring == NULL) break;
146
 
            switch (returnstring[0])
147
 
            {
148
 
            case 'r':
149
 
            case 'R':
150
 
                align = RIGHT;
151
 
                break;
152
 
            case 'l':
153
 
            case 'L':
154
 
                align = LEFT;
155
 
                break;
156
 
            case 'a':
157
 
            case 'A':
158
 
                align = ABOVE;
159
 
                break;
160
 
            case 'b':
161
 
            case 'B':
162
 
                align = BELOW;
163
 
                break;
164
 
            case 'c':
165
 
            case 'C':
166
 
                align = CENTER;
167
 
                break;
168
 
            default:
169
 
                cerr << "Unrecognized option for align in "
170
 
                     << "satellite file" << endl;
171
 
                break;
172
 
            }
173
 
            break;
174
 
        case ALTCIRC:
175
 
        {
176
 
            double angle;
177
 
            if (returnstring == NULL) break;
178
 
            sscanf(returnstring, "%lf", &angle);
179
 
            if (angle < 0) angle *= -1;
180
 
            if (angle > 90) angle = 90;
181
 
            angle += 90;
182
 
            altcirc.push_back(angle * deg_to_rad);
183
 
        }
184
 
        break;
185
 
        case COLOR:
186
 
            if (returnstring == NULL) break;
187
 
            color.assign(returnstring);
188
 
            arcopts += (" color=" + color);
189
 
            break; 
190
 
        case DELIMITER:
191
 
            break;
192
 
        case ENDOFLINE:
193
 
            end_of_line = true;
194
 
            break;
195
 
        case FONT:
196
 
            if (returnstring == NULL) break;
197
 
            font.assign(returnstring);
198
 
            break;
199
 
        case FONTSIZE:
200
 
            if (returnstring == NULL) break;
201
 
            sscanf(returnstring, "%d", &fontsize);
202
 
            if (fontsize < 0) fontsize = opts.fontsize;
203
 
            break;
204
 
        case IMAGE:
205
 
            if (returnstring == NULL) break;
206
 
            image.assign(returnstring);
207
 
            break;
208
 
        case NAME:
209
 
            if (returnstring == NULL) break;
210
 
            name.assign(returnstring);
211
 
            break;
212
 
        case SPACING:
213
 
        {
214
 
            if (returnstring == NULL) break;
215
 
            float spacing;
216
 
            sscanf(returnstring, "%f", &spacing);
217
 
            if (spacing < 0.001) spacing = 0.001;
218
 
            arcopts += " spacing=";
219
 
            arcopts += returnstring;
220
 
        }
221
 
        break;
222
 
        case TRAIL:
223
 
        {
224
 
            char *ptr = returnstring;
225
 
            while (ptr[0] != ',') 
226
 
            {
227
 
                if (ptr[0] == '\0') 
228
 
                {
229
 
                    syntax_error = true;
230
 
                    break;
231
 
                }
232
 
                ptr++;
233
 
            }
234
 
 
235
 
            if (syntax_error) break;
236
 
 
237
 
            if (!sscanf(++ptr, "%d,%d,%d", &trail_start, &trail_end,
238
 
                        &trail_interval) == 3)
239
 
            {
240
 
                cerr << "Need four values for trail{}!\n";
241
 
                syntax_error = true;
242
 
            }
243
 
            else
244
 
            {
245
 
                switch (returnstring[0])
246
 
                {
247
 
                case 'g':
248
 
                case 'G':
249
 
                    trail_type = GROUND;
250
 
                    break;
251
 
                case 'o':
252
 
                case 'O':
253
 
                    trail_type = ORBIT;
254
 
                    break;
255
 
                default:
256
 
                    cerr << "Unknown type of orbit trail!\n";
257
 
                    syntax_error = true;
258
 
                    break;
259
 
                }
260
 
                if (trail_interval < 1) trail_interval = 1;
261
 
            }
262
 
        }
263
 
        break;
264
 
        case TRANSPARENT:
265
 
            if (returnstring == NULL) break;
266
 
 
267
 
            transparency.assign(returnstring);
268
 
            
269
 
            int r, g, b;
270
 
            if (!sscanf(returnstring, "%d,%d,%d", &r, &g, &b) == 3)
271
 
            {
272
 
                cerr << "Need three values for transparency pixel!\n";
273
 
                syntax_error = true;
274
 
            }
275
 
 
276
 
            break;
277
 
        default:
278
 
        case UNKNOWN:
279
 
            syntax_error = true;
280
 
            break;
281
 
        }
282
 
 
283
 
        if (returnstring != NULL)
284
 
        {
285
 
            delete [] returnstring;
286
 
            returnstring = NULL;
287
 
        }
288
 
 
289
 
        if (syntax_error)
290
 
        {
291
 
            cerr << "Syntax error in satellite file\n"
292
 
                 << "line is \"" << this_sat->getID() << " " << options 
293
 
                 << "\"" << endl;
294
 
            return;
295
 
        }
296
 
 
297
 
        i++;
298
 
    }
299
 
 
300
 
    const double EARTH_RADIUS = 6378.140;
301
 
    
302
 
    // Reload TLE data here since select_ephemeris() in libsgp4sdp4
303
 
    // changes it.  This is in case the user wants to have two entries
304
 
    // with the same satellite.
305
 
    this_sat->loadTLE();
306
 
    
307
 
    time_t start_time = (time_t) (opts.time.tv_sec + trail_start * 60);
308
 
    time_t end_time = (time_t) (opts.time.tv_sec + trail_end * 60);
309
 
    time_t interval = (time_t) (trail_interval * 60);
310
 
 
311
 
    if (start_time > end_time)
312
 
    {
313
 
        time_t tmp = start_time;
314
 
        start_time = end_time;
315
 
        end_time = tmp;
316
 
    }
317
 
    
318
 
    double lat = 0, lon = 0, alt = 0;
319
 
    this_sat->getSpherical(start_time, lat, lon, alt);
320
 
    
321
 
    for (time_t t = start_time + interval; t <= end_time; t += interval)
322
 
    {
323
 
        double prev_lat = lat;
324
 
        double prev_lon = lon;
325
 
        double prev_alt = alt;
326
 
        this_sat->getSpherical(t, lat, lon, alt);
327
 
        sat_a << prev_lat/deg_to_rad << '\t' << prev_lon/deg_to_rad 
328
 
              << '\t' << lat/deg_to_rad << '\t' << lon/deg_to_rad;
329
 
        
330
 
        if (!arcopts.empty()) sat_a << " " << arcopts;
331
 
        if (trail_type == ORBIT)
332
 
            sat_a << " radius=" << 1 + prev_alt/EARTH_RADIUS
333
 
                  << " radius=" << 1 + alt/EARTH_RADIUS;
334
 
 
335
 
        sat_a << endl;
336
 
    }
337
 
    
338
 
    this_sat->getSpherical((time_t) opts.time.tv_sec, lat, lon, alt);
339
 
    
340
 
    sat_m << lat/deg_to_rad << ' ' << lon/deg_to_rad;
341
 
    if (trail_type == ORBIT)
342
 
        sat_m << " radius=" << 1 + alt/EARTH_RADIUS;
343
 
 
344
 
    if (align != AUTO) 
345
 
    {
346
 
        sat_m << " align=";
347
 
        switch (align)
348
 
        {
349
 
        case RIGHT:
350
 
            sat_m << "right";
351
 
            break;
352
 
        case ABOVE:
353
 
            sat_m << "above";
354
 
            break;
355
 
        case BELOW:
356
 
            sat_m << "below";
357
 
            break;
358
 
        case LEFT:
359
 
            sat_m << "left";
360
 
            break;
361
 
        case CENTER:
362
 
            sat_m << "center";
363
 
            break;
364
 
        default:
365
 
            cerr << "Unknown alignment????\n";
366
 
        }
367
 
    }
368
 
    if (!color.empty()) sat_m << " color=" << color;
369
 
    if (!font.empty()) sat_m << " font=" << font;
370
 
    if (fontsize != opts.fontsize) sat_m << " fontsize=" << fontsize;
371
 
    if (!image.empty()) sat_m << " image=" << image;
372
 
    if (!name.empty()) sat_m << " {" << name << "}";
373
 
    if (!transparency.empty()) 
374
 
        sat_m << " transparent={" << transparency << "}";
375
 
 
376
 
    sat_m << endl;
377
 
    
378
 
    // Distance of satellite from Earth's center, in units of Earth radii
379
 
    double Rs = 1 + alt/EARTH_RADIUS;
380
 
    
381
 
    double rot[3][3];
382
 
    rotateXYZ(rot, 0, lat, -lon);
383
 
 
384
 
    list<double>::iterator a = altcirc.begin();
385
 
    while (a != altcirc.end())
386
 
    {
387
 
        double phi = asin(sin(*a) / Rs);
388
 
        double X = -cos(*a + phi);
389
 
        double d = sin(*a + phi);
390
 
 
391
 
        drawAltitudeHalfCirc(rot, X, d, true, arcopts, sat_a);
392
 
        drawAltitudeHalfCirc(rot, X, d, false, arcopts, sat_a);
393
 
        a++;
394
 
    }
395
 
}
396
 
 
397
 
static int
398
 
readSatFileLine(const char *line, list<Satellite> &satellite_list,
399
 
                Satellite *&this_sat, char *&options)
400
 
{
401
 
    int i = 0;
402
 
    while (isDelimiter(line[i])) i++;
403
 
    if (isEndOfLine(line[i])) return(-1);
404
 
 
405
 
    int id;
406
 
    sscanf(line + i, "%d", &id);
407
 
    while (!(isDelimiter(line[i]) || isEndOfLine(line[i]))) i++; 
408
 
 
409
 
    if (id != 0)
410
 
    {
411
 
        list<Satellite>::iterator p = satellite_list.begin();
412
 
        while (p != satellite_list.end())
413
 
        {
414
 
            if (id == p->getID())
415
 
            {
416
 
                this_sat = &(*p);
417
 
                if (opts.debug) 
418
 
                {
419
 
                    cout << "Found ID #" << id << " (" 
420
 
                         << this_sat->getName() << ")\n";
421
 
                }
422
 
                break;
423
 
            }
424
 
            p++;
425
 
        }
426
 
 
427
 
        if (this_sat == NULL)
428
 
        {
429
 
            cerr << "Satellite ID #" << id << " not found in TLE file\n";
430
 
            return(-1);
431
 
        }
432
 
    }
433
 
 
434
 
    strcpy(options, line + i);
435
 
 
436
 
    return(id);
437
 
}
438
 
 
439
 
// Run through the list of satellite files and check to see that
440
 
// they exist, along with the corresponding TLE files.
441
 
static void
442
 
cullList()
443
 
{
444
 
    list<string> remove_list;
445
 
 
446
 
    list<string>::iterator p = opts.satellitefile.begin();
447
 
    while(p != opts.satellitefile.end())
448
 
    {
449
 
        if (satelliteFileExists(*p))
450
 
        {
451
 
            string tlefile = *p + ".tle";
452
 
            if (!satelliteFileExists(tlefile))
453
 
            {
454
 
                cerr << "Can't open TLE file " << tlefile << endl;
455
 
                remove_list.push_back(*p);
456
 
            }
457
 
        }
458
 
        else
459
 
        {
460
 
            cerr << "Can't open satellite file " << *p << endl;
461
 
            remove_list.push_back(*p);
462
 
        }
463
 
        p++;
464
 
    }
465
 
 
466
 
    p = remove_list.begin();
467
 
    while (p != remove_list.end())
468
 
    {
469
 
        opts.satellitefile.remove(*p);
470
 
        p++;
471
 
    }
472
 
}
473
 
 
474
 
void
475
 
createSatelliteList()
476
 
{
477
 
    cullList();
478
 
 
479
 
    list<string>::iterator p = opts.satellitefile.begin();
480
 
    while(p != opts.satellitefile.end())
481
 
    {
482
 
        string tlefile = *p + ".tle";
483
 
        ifstream infile(tlefile.c_str());
484
 
 
485
 
        char lines[3][80];
486
 
        while (infile.getline(lines[0], 80) != NULL)
487
 
        {
488
 
            if ((infile.getline(lines[1], 80) == NULL) 
489
 
                || (infile.getline(lines[2], 80) == NULL))
490
 
            {
491
 
                cerr << "Malformed TLE file?\n";
492
 
                break;
493
 
            }
494
 
            
495
 
            Satellite sat(lines);
496
 
            
497
 
            if (!sat.isGoodData()) 
498
 
            {
499
 
                cerr << "Bad TLE data\n";
500
 
                continue;
501
 
            }
502
 
            if (opts.debug) cout << "Read satellite with ID "
503
 
                                 << sat.getID() << endl;
504
 
            
505
 
            full_satellite_list.push_back(sat);
506
 
        }
507
 
 
508
 
        infile.close();
509
 
        p++;
510
 
    }
511
 
}
512
 
 
513
 
void
514
 
createSatelliteFiles(string tmpdir)
515
 
{
516
 
    int count = 0;
517
 
    list<string>::iterator p = opts.satellitefile.begin();
518
 
    while(p != opts.satellitefile.end())
519
 
    {
520
 
        list<Satellite> satellite_list;
521
 
        list<Satellite> zero_list;
522
 
        
523
 
        string tlefile = *p + ".tle";
524
 
        if (opts.debug) cout << "Opening TLE file " << tlefile << endl;
525
 
        
526
 
        ifstream infile(tlefile.c_str());
527
 
        char lines[3][80];
528
 
        while (infile.getline(lines[0], 80) != NULL)
529
 
        {
530
 
            if ((infile.getline(lines[1], 80) == NULL) 
531
 
                || (infile.getline(lines[2], 80) == NULL))
532
 
            {
533
 
                cerr << "Malformed TLE file?\n";
534
 
                break;
535
 
            }
536
 
            
537
 
            Satellite sat(lines);
538
 
            if (!sat.isGoodData()) 
539
 
            {
540
 
                cerr << "Bad TLE data\n";
541
 
                continue;
542
 
            }
543
 
            if (opts.debug) cout << "Read ID " << sat.getID() << endl;
544
 
            
545
 
            satellite_list.push_back(sat);
546
 
            zero_list.push_back(sat);
547
 
        }
548
 
        
549
 
        infile.close();
550
 
 
551
 
        // Now write one marker and one great arc file for each
552
 
        // satellite file.
553
 
 
554
 
        char pid[9];
555
 
        int digits = (int) (log10((double) opts.satellitefile.size()) 
556
 
                            + 1);
557
 
        sprintf(pid, "%5.5d-%.*d", ((int) (getpid() % 10000)), 
558
 
                digits, count++);
559
 
        
560
 
        string sat_markers = (tmpdir + separator 
561
 
                              + "xplanet-markers." + pid);
562
 
        string sat_arcs = tmpdir + separator + "xplanet-arcs." + pid;
563
 
        
564
 
        ofstream sat_a(sat_arcs.c_str());
565
 
        ofstream sat_m(sat_markers.c_str());
566
 
        
567
 
        if (opts.debug) cout << "Opening satellite file " << *p << endl;
568
 
        infile.open(p->c_str());
569
 
        
570
 
        // Now read each line and write the appropriate entry to
571
 
        // the marker/arc files
572
 
        char *line = new char[256];
573
 
        char *zero_options = NULL;
574
 
        while (infile.getline(line, 256, '\n') != NULL)
575
 
        {
576
 
            Satellite *this_sat = NULL;
577
 
            char *options = new char[256];
578
 
            int id = readSatFileLine(line, satellite_list, 
579
 
                                     this_sat, options);
580
 
            if (id == 0)
581
 
            {
582
 
                if (zero_options == NULL)
583
 
                {
584
 
                    zero_options = new char[256];
585
 
                    strcpy(zero_options, options);
586
 
                }
587
 
                else
588
 
                {
589
 
                    cerr << "ID 0 already specified in satellite file\n";
590
 
                }
591
 
            }
592
 
            else if (id > 0)
593
 
            {
594
 
                writeSatFiles(this_sat, options, sat_a, sat_m);
595
 
                zero_list.remove(*this_sat);
596
 
            }
597
 
            delete [] options;
598
 
        }
599
 
 
600
 
        if (zero_options != NULL)
601
 
        {
602
 
            list<Satellite>::iterator p2 = zero_list.begin();
603
 
            while (p2 != zero_list.end())
604
 
            {
605
 
                writeSatFiles(&(*p2), zero_options, sat_a, sat_m);
606
 
                p2++;
607
 
            }
608
 
            delete [] zero_options;
609
 
        }
610
 
 
611
 
        infile.close();
612
 
        
613
 
        sat_m.close();
614
 
        sat_a.close();
615
 
        
616
 
        opts.markerfile.push_back(sat_markers);
617
 
        opts.greatarcfile.push_back(sat_arcs);
618
 
 
619
 
        delete [] line;
620
 
        p++;
621
 
    }
622
 
}
623
 
 
624
 
void
625
 
cleanupSatelliteFiles(string tmpdir)
626
 
{
627
 
    int count = 0;
628
 
    list<string>::iterator p = opts.satellitefile.begin();
629
 
    while(p != opts.satellitefile.end())
630
 
    {
631
 
        char pid[9];
632
 
        int digits = (int) (log10((double) opts.satellitefile.size()) 
633
 
                            + 1);
634
 
        sprintf(pid, "%5.5d-%.*d", ((int) (getpid() % 10000)), 
635
 
                digits, count++);
636
 
        
637
 
        string sat_markers = tmpdir + separator + "xplanet-markers." + pid;
638
 
        string sat_arcs = tmpdir + separator + "xplanet-arcs." + pid;
639
 
 
640
 
        unlink(sat_markers.c_str());
641
 
        unlink(sat_arcs.c_str());
642
 
        p++;
643
 
    }
644
 
}
645
 
 
646
 
bool
647
 
getSatLocation(const int id, const time_t time, double &lat, double &lon,
648
 
               double &alt)
649
 
{
650
 
    Satellite *this_sat = NULL;
651
 
    list<Satellite>::iterator p = full_satellite_list.begin();
652
 
    while (p != full_satellite_list.end())
653
 
    {
654
 
        if (id == p->getID())
655
 
        {
656
 
            this_sat = &(*p);
657
 
            if (opts.debug) 
658
 
            {
659
 
                cout << "Found ID #" << id << " (" << this_sat->getName() 
660
 
                     << ")\n";
661
 
            }
662
 
            break;
663
 
        }
664
 
        p++;
665
 
    }
666
 
 
667
 
    if (this_sat == NULL) 
668
 
    {
669
 
        if (opts.satellitefile.size() == 0) 
670
 
        {
671
 
            cerr << "A TLE file must be specified using the "
672
 
                 << "-satfile option.\n";
673
 
        }
674
 
        else
675
 
        {
676
 
            cerr << "Satellite ID #" << id << " not found in TLE file\n";
677
 
        }
678
 
        return(false);
679
 
    }
680
 
 
681
 
    // Reload TLE data here since select_ephemeris() in libsgp4sdp4
682
 
    // changes it.  This is in case the user wants to have two entries
683
 
    // with the same satellite.
684
 
    this_sat->loadTLE();
685
 
    
686
 
    this_sat->getSpherical(time, lat, lon, alt);
687
 
    return(true);
688
 
}
689