Coverage Report

Created: 2025-07-23 09:13

/src/gdal/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Purpose:  Implementation of the CPCIDSKEphemerisSegment class.
4
 *
5
 ******************************************************************************
6
 * Copyright (c) 2009
7
 * PCI Geomatics, 90 Allstate Parkway, Markham, Ontario, Canada.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 ****************************************************************************/
11
12
#include "segment/cpcidsksegment.h"
13
#include "core/pcidsk_utils.h"
14
#include "segment/cpcidskephemerissegment.h"
15
#include "pcidsk_exception.h"
16
#include "core/pcidsk_utils.h"
17
18
#include <vector>
19
#include <string>
20
#include <cassert>
21
#include <cstring>
22
#include <memory>
23
24
using namespace PCIDSK;
25
26
0
PCIDSKEphemerisSegment::~PCIDSKEphemerisSegment() = default;
27
28
namespace
29
{
30
    /**
31
     * Function to get the minimum value of two values.
32
     *
33
     * @param a The first value.
34
     * @param b The second value.
35
     *
36
     * @return The minimum value of the two specified values.
37
     */
38
    int MinFunction(int a,int b)
39
0
    {
40
0
        return (a<b)?a:b;
41
0
    }
42
}
43
44
/**
45
 * Ephemeris Segment constructor
46
 * @param fileIn the PCIDSK file
47
 * @param segmentIn the segment index
48
 * @param segment_pointer the segment pointer
49
 * @param bLoad true to load the segment, else false (default true)
50
 */
51
CPCIDSKEphemerisSegment::CPCIDSKEphemerisSegment(PCIDSKFile *fileIn,
52
                                                   int segmentIn,
53
                                                   const char *segment_pointer,
54
                                                   bool bLoad) :
55
0
    CPCIDSKSegment(fileIn, segmentIn, segment_pointer),
56
0
    loaded_(false),mbModified(false)
57
0
{
58
0
    mpoEphemeris = nullptr;
59
0
    if(bLoad)
60
0
    {
61
0
        Load();
62
0
    }
63
0
}
Unexecuted instantiation: PCIDSK::CPCIDSKEphemerisSegment::CPCIDSKEphemerisSegment(PCIDSK::PCIDSKFile*, int, char const*, bool)
Unexecuted instantiation: PCIDSK::CPCIDSKEphemerisSegment::CPCIDSKEphemerisSegment(PCIDSK::PCIDSKFile*, int, char const*, bool)
64
65
66
CPCIDSKEphemerisSegment::~CPCIDSKEphemerisSegment()
67
0
{
68
0
    delete mpoEphemeris;
69
0
}
70
71
/**
72
 * Load the contents of the segment
73
 */
74
void CPCIDSKEphemerisSegment::Load()
75
0
{
76
    // Check if we've already loaded the segment into memory
77
0
    if (loaded_) {
78
0
        return;
79
0
    }
80
81
0
    seg_data.SetSize((int)data_size - 1024);
82
83
0
    if(data_size == 1024)
84
0
        return;
85
86
0
    ReadFromFile(seg_data.buffer, 0, data_size - 1024);
87
88
    // We test the name of the binary segment before starting to read
89
    // the buffer.
90
0
    if (!STARTS_WITH(seg_data.buffer, "ORBIT   "))
91
0
    {
92
0
        seg_data.Put("ORBIT   ",0,8);
93
0
        loaded_ = true;
94
0
        return ;
95
0
    }
96
97
0
    mpoEphemeris = BinaryToEphemeris(0);
98
99
    // We've now loaded the structure up with data. Mark it as being loaded
100
    // properly.
101
0
    loaded_ = true;
102
0
}
103
104
/**
105
 * Write the segment on disk
106
 */
107
void CPCIDSKEphemerisSegment::Write(void)
108
0
{
109
    //We are not writing if nothing was loaded.
110
0
    if (!loaded_) {
111
0
        return;
112
0
    }
113
114
0
    EphemerisToBinary( mpoEphemeris, 0);
115
116
0
    seg_data.Put("ORBIT   ",0,8);
117
118
0
    WriteToFile(seg_data.buffer,0,seg_data.buffer_size);
119
120
0
    mbModified = false;
121
0
}
122
123
/**
124
 * Synchronize the segment, if it was modified then
125
 * write it into disk.
126
 */
127
void CPCIDSKEphemerisSegment::Synchronize()
128
0
{
129
0
    if(mbModified)
130
0
    {
131
0
        this->Write();
132
0
    }
133
0
}
134
135
/************************************************************************/
136
/*                              ConvertDeg()                            */
137
/************************************************************************/
138
/**
139
 * if mode is 0, convert angle from 0 to 360 to 0 to 180 and 0 to -180
140
 * if mode is 1, convert angle from 0 to 180 and 0 to -180 to 0 to 360
141
 *
142
 * @param degree the degree
143
 * @param mode  the mode
144
 */
145
double CPCIDSKEphemerisSegment::ConvertDeg(double degree, int mode)
146
0
{
147
0
    double result;
148
149
0
    if (mode == 0)
150
0
    {
151
/* -------------------------------------------------------------------- */
152
/*      degree is in range of 0 to 360                                  */
153
/* -------------------------------------------------------------------- */
154
0
        if (degree > 180)
155
0
            result = degree - 360;
156
0
        else
157
0
            result = degree;
158
0
    }
159
0
    else
160
0
    {
161
/* -------------------------------------------------------------------- */
162
/*      degree is in range of 0 to 180 and 0 to -180                    */
163
/* -------------------------------------------------------------------- */
164
0
        if (degree < 0)
165
0
            result = 360 + degree;
166
0
        else
167
0
            result = degree;
168
0
    }
169
0
    return (result);
170
0
}
171
172
/************************************************************************/
173
/*                      ReadAvhrrEphemerisSegment()                     */
174
/************************************************************************/
175
/**
176
 *  Read the contents of blocks 9, 11, and onwards from the orbit
177
 *  segment into the EphemerisSeg_t structure.
178
 * @param nStartBlock where to start to read in the buffer
179
 * @param psEphSegRec the structure to populate with information.
180
 */
181
void
182
CPCIDSKEphemerisSegment::ReadAvhrrEphemerisSegment(int nStartBlock,
183
                                         EphemerisSeg_t *psEphSegRec)
184
0
{
185
0
    int  nBlock = 0, nLine = 0;
186
0
    int nPos = 0;
187
188
0
    int nDataLength = seg_data.buffer_size;
189
/* -------------------------------------------------------------------- */
190
/*  Allocate the AVHRR segment portion of EphemerisSeg_t.               */
191
/* -------------------------------------------------------------------- */
192
0
    psEphSegRec->AvhrrSeg = new AvhrrSeg_t();
193
0
    AvhrrSeg_t* as = psEphSegRec->AvhrrSeg;
194
195
/* -------------------------------------------------------------------- */
196
/*  Read in the Ninth Block which contains general info + ephemeris     */
197
/*  info as well.                                                       */
198
/* -------------------------------------------------------------------- */
199
0
    nPos = nStartBlock + 8*512;
200
201
0
    as->szImageFormat = seg_data.Get(nPos, 16);
202
0
    as->nImageXSize = seg_data.GetInt(nPos+16, 16);
203
0
    as->nImageYSize = seg_data.GetInt(nPos+32, 16);
204
205
0
    if ( STARTS_WITH(seg_data.Get(nPos+48,9), "ASCENDING") )
206
0
        as->bIsAscending = true;
207
0
    else
208
0
        as->bIsAscending = false;
209
0
    if ( STARTS_WITH(seg_data.Get(nPos+64,7), "ROTATED") )
210
0
        as->bIsImageRotated = true;
211
0
    else
212
0
        as->bIsImageRotated = false;
213
214
0
    as->szOrbitNumber = seg_data.Get(nPos+80, 16);
215
0
    as->szAscendDescendNodeFlag = seg_data.Get(nPos+96,16);
216
0
    as->szEpochYearAndDay = seg_data.Get(nPos+112,16);
217
0
    as->szEpochTimeWithinDay = seg_data.Get(nPos+128,16);
218
0
    as->szTimeDiffStationSatelliteMsec = seg_data.Get(nPos+144,16);
219
0
    as->szActualSensorScanRate = seg_data.Get(nPos+160,16);
220
0
    as->szIdentOfOrbitInfoSource = seg_data.Get(nPos+176,16);
221
0
    as->szInternationalDesignator = seg_data.Get(nPos+192,16);
222
0
    as->szOrbitNumAtEpoch = seg_data.Get(nPos+208,16);
223
0
    as->szJulianDayAscendNode = seg_data.Get(nPos+224,16);
224
0
    as->szEpochYear = seg_data.Get(nPos+240,16);
225
0
    as->szEpochMonth = seg_data.Get(nPos+256,16);
226
0
    as->szEpochDay = seg_data.Get(nPos+272,16);
227
0
    as->szEpochHour = seg_data.Get(nPos+288,16);
228
0
    as->szEpochMinute = seg_data.Get(nPos+304,16);
229
0
    as->szEpochSecond = seg_data.Get(nPos+320,16);
230
0
    as->szPointOfAriesDegrees = seg_data.Get(nPos+336,16);
231
0
    as->szAnomalisticPeriod = seg_data.Get(nPos+352,16);
232
0
    as->szNodalPeriod = seg_data.Get(nPos+368,16);
233
0
    as->szEccentricity = seg_data.Get(nPos+384,16);
234
0
    as->szArgumentOfPerigee = seg_data.Get(nPos+400,16);
235
0
    as->szRAAN = seg_data.Get(nPos+416,16);
236
0
    as->szInclination = seg_data.Get(nPos+432,16);
237
0
    as->szMeanAnomaly = seg_data.Get(nPos+448,16);
238
0
    as->szSemiMajorAxis = seg_data.Get(nPos+464,16);
239
240
/* -------------------------------------------------------------------- */
241
/*  Skip the 10th block which is reserved for future use.               */
242
/* -------------------------------------------------------------------- */
243
244
/* -------------------------------------------------------------------- */
245
/*  Read in the 11th block, which contains indexing info.               */
246
/* -------------------------------------------------------------------- */
247
0
    nPos = nStartBlock + 512*10;
248
249
0
    as->nRecordSize             = seg_data.GetInt(nPos,    16);
250
0
    as->nBlockSize              = seg_data.GetInt(nPos+16, 16);
251
0
    as->nNumRecordsPerBlock     = seg_data.GetInt(nPos+32, 16);
252
0
    as->nNumBlocks              = seg_data.GetInt(nPos+48, 16);
253
0
    as->nNumScanlineRecords     = seg_data.GetInt(nPos+64, 16);
254
255
/* -------------------------------------------------------------------- */
256
/*  Allocate the scanline records.                                      */
257
/* -------------------------------------------------------------------- */
258
0
    if ( as->nNumScanlineRecords == 0 )
259
0
        return;
260
261
/* -------------------------------------------------------------------- */
262
/*  Now read the 12th block and onward.                                 */
263
/* -------------------------------------------------------------------- */
264
0
    nBlock = 12;
265
266
0
    if ( as->nNumRecordsPerBlock == 0 )
267
0
        return;
268
269
0
    for(nLine = 0; nLine < as->nNumScanlineRecords;
270
0
                   nLine += as->nNumRecordsPerBlock)
271
0
    {
272
0
        int nNumRecords = MinFunction(as->nNumRecordsPerBlock,
273
0
                                      as->nNumScanlineRecords - nLine);
274
0
        nPos = nStartBlock + 512*(nBlock-1);
275
0
        if( nDataLength < 512*nBlock )
276
0
        {
277
0
            break;
278
0
        }
279
280
0
        for(int i = 0; i < nNumRecords; ++i)
281
0
        {
282
0
            AvhrrLine_t sLine;
283
0
            ReadAvhrrScanlineRecord(nPos+i*80, &sLine);
284
0
            as->Line.push_back(sLine);
285
0
        }
286
287
0
        ++nBlock;
288
0
    }
289
0
}
290
291
/************************************************************************/
292
/*                      ReadAvhrrScanlineRecord()                       */
293
/************************************************************************/
294
/**
295
 *  Read from a byte buffer in order to set a scanline record.
296
 * @param nPos position in buffer
297
 * @param psScanlineRecord the record to read.
298
 */
299
void
300
CPCIDSKEphemerisSegment::ReadAvhrrScanlineRecord(int nPos,
301
                                           AvhrrLine_t *psScanlineRecord)
302
0
{
303
0
    int i;
304
0
    AvhrrLine_t *sr = psScanlineRecord;
305
306
0
    sr->nScanLineNum = ReadAvhrrInt32((unsigned char*)seg_data.Get(nPos,4));
307
0
    sr->nStartScanTimeGMTMsec = ReadAvhrrInt32((unsigned char*)seg_data.Get(nPos+4,4));
308
309
0
    for(i = 0; i < 10; ++i)
310
0
        sr->abyScanLineQuality[i] = static_cast<unsigned char>(seg_data.GetInt(nPos+8+i,1));
311
312
0
    for(i = 0; i < 5; ++i)
313
0
    {
314
0
        sr->aabyBadBandIndicators[i][0] = static_cast<unsigned char>(seg_data.GetInt(nPos+18+2*i,1));
315
0
        sr->aabyBadBandIndicators[i][1] = static_cast<unsigned char>(seg_data.GetInt(nPos+18+2*i+1,1));
316
0
    }
317
318
0
    for(i = 0; i < 8; ++i)
319
0
        sr->abySatelliteTimeCode[i] = static_cast<unsigned char>(seg_data.GetInt(nPos+28+i,1));
320
321
0
    for(i = 0; i < 3; ++i)
322
0
        sr->anTargetTempData[i] = ReadAvhrrInt32((unsigned char*)seg_data.Get(nPos+36+i*4,4));
323
0
    for(i = 0; i < 3; ++i)
324
0
        sr->anTargetScanData[i] = ReadAvhrrInt32((unsigned char*)seg_data.Get(nPos+48+i*4,4));
325
0
    for(i = 0; i < 5; ++i)
326
0
        sr->anSpaceScanData[i]  = ReadAvhrrInt32((unsigned char*)seg_data.Get(nPos+60+i*4,4));
327
0
}
328
329
/************************************************************************/
330
/*                         ReadAvhrrInt32()                             */
331
/************************************************************************/
332
/**
333
 * Read an integer from a given buffer of at least 4 bytes.
334
 * @param pbyBuf the buffer that contains the value.
335
 * @return the value
336
 */
337
int
338
CPCIDSKEphemerisSegment::ReadAvhrrInt32(unsigned char* pbyBuf)
339
0
{
340
0
    int nValue = 0;
341
0
    unsigned char* b = pbyBuf;
342
0
    nValue = (int)((b[0]<<24) | (b[1]<<16) | (b[2]<<8) | b[3]);
343
344
0
    return( nValue );
345
0
}
346
347
/************************************************************************/
348
/*                    WriteAvhrrEphemerisSegment()                      */
349
/************************************************************************/
350
/**
351
 *  Write the contents of blocks 9, 10, and onwards to the orbit
352
 *  segment from fields in the EphemerisSeg_t structure.
353
 * @param nStartBlock where to start to write the information in the buffer
354
 * @param psEphSegRec the information to write.
355
 */
356
void
357
CPCIDSKEphemerisSegment::WriteAvhrrEphemerisSegment(int nStartBlock,
358
                                           EphemerisSeg_t *psEphSegRec)
359
0
{
360
0
    int  nBlock = 0, nLine = 0;
361
0
    int nPos = 0;
362
/* -------------------------------------------------------------------- */
363
/*  Check that the AvhrrSeg is not NULL.                                */
364
/* -------------------------------------------------------------------- */
365
0
    AvhrrSeg_t* as = psEphSegRec->AvhrrSeg;
366
367
0
    if ( as == nullptr)
368
0
    {
369
0
        return ThrowPCIDSKException("The AvhrrSeg is NULL.");
370
0
    }
371
372
/* -------------------------------------------------------------------- */
373
/*      Realloc the data buffer large enough to hold all the AVHRR      */
374
/*      information, and zero it.                                       */
375
/* -------------------------------------------------------------------- */
376
0
    int nToAdd = 512 *
377
0
        (((as->nNumScanlineRecords + as->nNumRecordsPerBlock-1) /
378
0
                   as->nNumRecordsPerBlock)
379
0
        +4);
380
0
    seg_data.SetSize(seg_data.buffer_size + nToAdd);
381
382
0
    nPos = nStartBlock;
383
0
    memset(seg_data.buffer+nPos,' ',nToAdd);
384
385
/* -------------------------------------------------------------------- */
386
/*  Write the first avhrr Block.                                        */
387
/* -------------------------------------------------------------------- */
388
389
0
    seg_data.Put(as->szImageFormat.c_str(),nPos,16);
390
391
0
    seg_data.Put(as->nImageXSize,nPos+16,16);
392
0
    seg_data.Put(as->nImageYSize,nPos+32,16);
393
394
0
    if ( as->bIsAscending )
395
0
        seg_data.Put("ASCENDING",nPos+48,9);
396
0
    else
397
0
        seg_data.Put("DESCENDING",nPos+48,10);
398
399
0
    if ( as->bIsImageRotated )
400
0
        seg_data.Put("ROTATED",nPos+64,7);
401
0
    else
402
0
        seg_data.Put("NOT ROTATED",nPos+64,11);
403
404
0
    seg_data.Put(as->szOrbitNumber.c_str(),nPos+80,16);
405
0
    seg_data.Put(as->szAscendDescendNodeFlag.c_str(),nPos+96,16,true);
406
0
    seg_data.Put(as->szEpochYearAndDay.c_str(),nPos+112,16,true);
407
0
    seg_data.Put(as->szEpochTimeWithinDay.c_str(),nPos+128,16,true);
408
0
    seg_data.Put(as->szTimeDiffStationSatelliteMsec.c_str(),nPos+144,16,true);
409
0
    seg_data.Put(as->szActualSensorScanRate.c_str(),nPos+160,16,true);
410
0
    seg_data.Put(as->szIdentOfOrbitInfoSource.c_str(),nPos+176,16,true);
411
0
    seg_data.Put(as->szInternationalDesignator.c_str(),nPos+192,16,true);
412
0
    seg_data.Put(as->szOrbitNumAtEpoch.c_str(),nPos+208,16,true);
413
0
    seg_data.Put(as->szJulianDayAscendNode.c_str(),nPos+224,16,true);
414
0
    seg_data.Put(as->szEpochYear.c_str(),nPos+240,16,true);
415
0
    seg_data.Put(as->szEpochMonth.c_str(),nPos+256,16,true);
416
0
    seg_data.Put(as->szEpochDay.c_str(),nPos+272,16,true);
417
0
    seg_data.Put(as->szEpochHour.c_str(),nPos+288,16,true);
418
0
    seg_data.Put(as->szEpochMinute.c_str(),nPos+304,16,true);
419
0
    seg_data.Put(as->szEpochSecond.c_str(),nPos+320,16,true);
420
0
    seg_data.Put(as->szPointOfAriesDegrees.c_str(),nPos+336,16,true);
421
0
    seg_data.Put(as->szAnomalisticPeriod.c_str(),nPos+352,16,true);
422
0
    seg_data.Put(as->szNodalPeriod.c_str(),nPos+368,16,true);
423
0
    seg_data.Put(as->szEccentricity.c_str(), nPos+384,16,true);
424
0
    seg_data.Put(as->szArgumentOfPerigee.c_str(),nPos+400,16,true);
425
0
    seg_data.Put(as->szRAAN.c_str(),nPos+416,16,true);
426
0
    seg_data.Put(as->szInclination.c_str(),nPos+432,16,true);
427
0
    seg_data.Put(as->szMeanAnomaly.c_str(),nPos+448,16,true);
428
0
    seg_data.Put(as->szSemiMajorAxis.c_str(),nPos+464,16,true);
429
430
/* -------------------------------------------------------------------- */
431
/*  second avhrr block is all zeros.                                    */
432
/* -------------------------------------------------------------------- */
433
434
/* -------------------------------------------------------------------- */
435
/*  Write the 3rd avhrr Block.                                          */
436
/* -------------------------------------------------------------------- */
437
0
    nPos = nStartBlock + 512*2;
438
439
0
    seg_data.Put(as->nRecordSize,nPos,16);
440
0
    seg_data.Put(as->nBlockSize,nPos+16,16);
441
0
    seg_data.Put(as->nNumRecordsPerBlock,nPos+32,16);
442
0
    seg_data.Put(as->nNumBlocks,nPos+48,16);
443
0
    seg_data.Put(as->nNumScanlineRecords,nPos+64,16);
444
445
/* -------------------------------------------------------------------- */
446
/*  Write the fourth avhrr block onwards.                               */
447
/* -------------------------------------------------------------------- */
448
0
    if ( as->Line.empty() )
449
0
        return;
450
451
0
    nBlock = 4;
452
453
0
    if ( as->nNumRecordsPerBlock == 0 )
454
0
        return;
455
456
0
    for(nLine = 0; nLine < as->nNumScanlineRecords;
457
0
                   nLine += as->nNumRecordsPerBlock)
458
0
    {
459
0
        int nNumRecords = MinFunction(as->nNumRecordsPerBlock,
460
0
                                      as->nNumScanlineRecords - nLine);
461
0
        nPos = nStartBlock + (nBlock-1) * 512;
462
463
0
        for(int i = 0; i < nNumRecords; ++i)
464
0
        {
465
0
            WriteAvhrrScanlineRecord(&(as->Line[nLine+i]), nPos + i*80);
466
0
        }
467
468
0
        ++nBlock;
469
0
    }
470
0
}
471
472
/************************************************************************/
473
/*                       WriteAvhrrScanlineRecord()                     */
474
/************************************************************************/
475
/**
476
 * Write a scanline record to a byte buffer.
477
 * @param psScanlineRecord the record to write
478
 * @param nPos position in buffer
479
 */
480
void
481
CPCIDSKEphemerisSegment::WriteAvhrrScanlineRecord(
482
                                         AvhrrLine_t *psScanlineRecord,
483
                                         int nPos)
484
0
{
485
0
    int i;
486
0
    AvhrrLine_t *sr = psScanlineRecord;
487
0
    unsigned char* b = (unsigned char*)&(seg_data.buffer[nPos]);
488
489
0
    WriteAvhrrInt32(sr->nScanLineNum, b);
490
0
    WriteAvhrrInt32(sr->nStartScanTimeGMTMsec, b+4);
491
492
0
    for(i=0 ; i < 10 ; i++)
493
0
        seg_data.Put(sr->abyScanLineQuality[i],nPos+8+i,1);
494
495
0
    for(i = 0; i < 5; ++i)
496
0
    {
497
0
        seg_data.Put(sr->aabyBadBandIndicators[i][0],nPos+18+i*2,1);
498
0
        seg_data.Put(sr->aabyBadBandIndicators[i][1],nPos+18+i*2+1,1);
499
0
    }
500
501
0
    for(i=0 ; i < 8 ; i++)
502
0
        seg_data.Put(sr->abySatelliteTimeCode[i],nPos+28+i,1);
503
504
0
    for(i = 0; i < 3; ++i)
505
0
        WriteAvhrrInt32(sr->anTargetTempData[i], b+(36+i*4));
506
0
    for(i = 0; i < 3; ++i)
507
0
        WriteAvhrrInt32(sr->anTargetScanData[i], b+(48+i*4));
508
0
    for(i = 0; i < 5; ++i)
509
0
        WriteAvhrrInt32(sr->anSpaceScanData[i],  b+(60+i*4));
510
511
0
}
512
513
/************************************************************************/
514
/*                         WriteAvhrrInt32()                            */
515
/************************************************************************/
516
/**
517
 * Write an integer into a given buffer of at least 4 bytes.
518
 * @param nValue the value to write
519
 * @param pbyBuf the buffer to write into.
520
 */
521
void CPCIDSKEphemerisSegment::WriteAvhrrInt32(int nValue,
522
                                              unsigned char* pbyBuf)
523
0
{
524
0
    pbyBuf[0] = static_cast<unsigned char>((nValue & 0xff000000) >> 24);
525
0
    pbyBuf[1] = static_cast<unsigned char>((nValue & 0x00ff0000) >> 16);
526
0
    pbyBuf[2] = static_cast<unsigned char>((nValue & 0x0000ff00) >> 8);
527
0
    pbyBuf[3] = static_cast<unsigned char>(nValue & 0x000000ff);
528
0
}
529
530
531
/************************************************************************/
532
/*                        BinaryToEphemeris()                           */
533
/************************************************************************/
534
/**
535
 * Read binary information from a binary buffer to create an
536
 * EphemerisSeg_t structure. The caller is responsible to free the memory
537
 * of the returned structure with delete.
538
 *
539
 * @param nStartBlock where to start read the orbit info into the buffer.
540
 * @return the orbit information.
541
 */
542
EphemerisSeg_t *
543
CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
544
545
0
{
546
0
    int             i;
547
0
    int nPos = nStartBlock;
548
549
0
    std::unique_ptr<EphemerisSeg_t> l_segment(new EphemerisSeg_t());
550
551
/* -------------------------------------------------------------------- */
552
/*      Process first block.                                            */
553
/* -------------------------------------------------------------------- */
554
555
0
    l_segment->SatelliteDesc = seg_data.Get(nPos+8,32);
556
0
    l_segment->SceneID = seg_data.Get(nPos+40, 32);
557
558
/* -------------------------------------------------------------------- */
559
/*      Process the second block.                                       */
560
/* -------------------------------------------------------------------- */
561
0
    nPos = nStartBlock + 512;
562
563
0
    l_segment->SatelliteSensor = seg_data.Get(nPos, 16);
564
0
    for (i=0; i<16; i++)
565
0
    {
566
0
        if (l_segment->SatelliteSensor[i] == ' ')
567
0
        {
568
0
            l_segment->SatelliteSensor = l_segment->SatelliteSensor.substr(0,i);
569
0
            break;
570
0
        }
571
0
    }
572
573
0
    l_segment->SensorNo = seg_data.Get(nPos+22, 2);
574
0
    l_segment->DateImageTaken = seg_data.Get(nPos+44, 22);
575
576
0
    if (seg_data.buffer[nPos+66] == 'Y' ||
577
0
        seg_data.buffer[nPos+66] == 'y')
578
0
        l_segment->SupSegExist = true;
579
0
    else
580
0
        l_segment->SupSegExist = false;
581
0
    l_segment->FieldOfView = seg_data.GetDouble(nPos+88, 22);
582
0
    l_segment->ViewAngle = seg_data.GetDouble(nPos+110, 22);
583
0
    l_segment->NumColCentre = seg_data.GetDouble(nPos+132, 22);
584
0
    l_segment->RadialSpeed = seg_data.GetDouble(nPos+154, 22);
585
0
    l_segment->Eccentricity = seg_data.GetDouble(nPos+176, 22);
586
0
    l_segment->Height = seg_data.GetDouble(nPos+198, 22);
587
0
    l_segment->Inclination = seg_data.GetDouble(nPos+220, 22);
588
0
    l_segment->TimeInterval = seg_data.GetDouble(nPos+242, 22);
589
0
    l_segment->NumLineCentre = seg_data.GetDouble(nPos+264, 22);
590
0
    l_segment->LongCentre = seg_data.GetDouble(nPos+286, 22);
591
0
    l_segment->AngularSpd = seg_data.GetDouble(nPos+308, 22);
592
0
    l_segment->AscNodeLong = seg_data.GetDouble(nPos+330, 22);
593
0
    l_segment->ArgPerigee = seg_data.GetDouble(nPos+352, 22);
594
0
    l_segment->LatCentre = seg_data.GetDouble(nPos+374, 22);
595
0
    l_segment->EarthSatelliteDist = seg_data.GetDouble(nPos+396, 22);
596
0
    l_segment->NominalPitch = seg_data.GetDouble(nPos+418, 22);
597
0
    l_segment->TimeAtCentre = seg_data.GetDouble(nPos+440, 22);
598
0
    l_segment->SatelliteArg = seg_data.GetDouble(nPos+462, 22);
599
0
    l_segment->bDescending = true;
600
0
    if (seg_data.buffer[nPos+484] == 'A')
601
0
        l_segment->bDescending = false;
602
603
/* -------------------------------------------------------------------- */
604
/*      Process the third block.                                        */
605
/* -------------------------------------------------------------------- */
606
0
    nPos = nStartBlock + 2*512;
607
608
0
    l_segment->XCentre = seg_data.GetDouble(nPos, 22);
609
0
    l_segment->YCentre = seg_data.GetDouble(nPos+22, 22);
610
0
    l_segment->UtmXCentre = seg_data.GetDouble(nPos+44, 22);
611
0
    l_segment->UtmYCentre = seg_data.GetDouble(nPos+66, 22);
612
0
    l_segment->PixelRes = seg_data.GetDouble(nPos+88, 22);
613
0
    l_segment->LineRes = seg_data.GetDouble(nPos+110, 22);
614
0
    if (seg_data.buffer[nPos+132] == 'Y' ||
615
0
        seg_data.buffer[nPos+132] == 'y')
616
0
        l_segment->CornerAvail = true;
617
0
    else
618
0
        l_segment->CornerAvail = false;
619
0
    l_segment->MapUnit = seg_data.Get(nPos+133, 16);
620
621
0
    l_segment->XUL = seg_data.GetDouble(nPos+149, 22);
622
0
    l_segment->YUL = seg_data.GetDouble(nPos+171, 22);
623
0
    l_segment->XUR = seg_data.GetDouble(nPos+193, 22);
624
0
    l_segment->YUR = seg_data.GetDouble(nPos+215, 22);
625
0
    l_segment->XLR = seg_data.GetDouble(nPos+237, 22);
626
0
    l_segment->YLR = seg_data.GetDouble(nPos+259, 22);
627
0
    l_segment->XLL = seg_data.GetDouble(nPos+281, 22);
628
0
    l_segment->YLL = seg_data.GetDouble(nPos+303, 22);
629
0
    l_segment->UtmXUL = seg_data.GetDouble(nPos+325, 22);
630
0
    l_segment->UtmYUL = seg_data.GetDouble(nPos+347, 22);
631
0
    l_segment->UtmXUR = seg_data.GetDouble(nPos+369, 22);
632
0
    l_segment->UtmYUR = seg_data.GetDouble(nPos+391, 22);
633
0
    l_segment->UtmXLR = seg_data.GetDouble(nPos+413, 22);
634
0
    l_segment->UtmYLR = seg_data.GetDouble(nPos+435, 22);
635
0
    l_segment->UtmXLL = seg_data.GetDouble(nPos+457, 22);
636
0
    l_segment->UtmYLL = seg_data.GetDouble(nPos+479, 22);
637
638
/* -------------------------------------------------------------------- */
639
/*      Process the 4th block (Corner lat/long coordinates)             */
640
/* -------------------------------------------------------------------- */
641
0
    nPos = nStartBlock + 3*512;
642
643
0
    l_segment->LongCentreDeg = seg_data.GetDouble(nPos, 16);
644
0
    l_segment->LatCentreDeg = seg_data.GetDouble(nPos+16, 16);
645
0
    l_segment->LongUL =  seg_data.GetDouble(nPos+32, 16);
646
0
    l_segment->LatUL = seg_data.GetDouble(nPos+48, 16);
647
0
    l_segment->LongUR =  seg_data.GetDouble(nPos+64, 16);
648
0
    l_segment->LatUR = seg_data.GetDouble(nPos+80, 16);
649
0
    l_segment->LongLR = seg_data.GetDouble(nPos+96, 16);
650
0
    l_segment->LatLR = seg_data.GetDouble(nPos+112, 16);
651
0
    l_segment->LongLL = seg_data.GetDouble(nPos+128, 16);
652
0
    l_segment->LatLL = seg_data.GetDouble(nPos+144, 16);
653
0
    l_segment->HtCentre = seg_data.GetDouble(nPos+160, 16);
654
0
    l_segment->HtUL = seg_data.GetDouble(nPos+176, 16);
655
0
    l_segment->HtUR = seg_data.GetDouble(nPos+192, 16);
656
0
    l_segment->HtLR = seg_data.GetDouble(nPos+208, 16);
657
0
    l_segment->HtLL = seg_data.GetDouble(nPos+224, 16);
658
659
/* -------------------------------------------------------------------- */
660
/*      Process the 5th block.                                          */
661
/* -------------------------------------------------------------------- */
662
0
    nPos = nStartBlock + 512*4;
663
664
0
    l_segment->ImageRecordLength = seg_data.GetInt(nPos, 16);
665
0
    l_segment->NumberImageLine = seg_data.GetInt(nPos+16, 16);
666
0
    l_segment->NumberBytePerPixel = seg_data.GetInt(nPos+32, 16);
667
0
    l_segment->NumberSamplePerLine = seg_data.GetInt(nPos+48, 16);
668
0
    l_segment->NumberPrefixBytes = seg_data.GetInt(nPos+64, 16);
669
0
    l_segment->NumberSuffixBytes = seg_data.GetInt(nPos+80, 16);
670
671
/* -------------------------------------------------------------------- */
672
/*      Process the 6th and 7th block.                                  */
673
/* -------------------------------------------------------------------- */
674
0
    nPos = nStartBlock + 5*512;
675
676
0
    l_segment->SPNCoeff = 0;
677
678
0
    if(STARTS_WITH(seg_data.Get(nPos,8), "SPOT1BOD") ||
679
0
       STARTS_WITH(seg_data.Get(nPos,8), "SPOT1BNW"))
680
0
    {
681
0
        l_segment->SPNCoeff = seg_data.GetInt(nPos+22, 22);
682
0
        for (i=0; i<20; i++)
683
0
        {
684
0
            l_segment->SPCoeff1B[i] =
685
0
                seg_data.GetDouble(nPos+(i+2)*22, 22);
686
0
        }
687
688
0
        if (STARTS_WITH(seg_data.Get(nPos,8), "SPOT1BNW"))
689
0
        {
690
0
            nPos = nStartBlock + 6*512;
691
692
0
            for (i=0; i<19; i++)
693
0
            {
694
0
                l_segment->SPCoeff1B[i+20] =
695
0
                    seg_data.GetDouble(nPos+i*22, 22);
696
0
            }
697
0
            l_segment->SPCoeffSg[0] = seg_data.GetInt(nPos+418, 8);
698
0
            l_segment->SPCoeffSg[1] = seg_data.GetInt(nPos+426, 8);
699
0
            l_segment->SPCoeffSg[2] = seg_data.GetInt(nPos+434, 8);
700
0
            l_segment->SPCoeffSg[3] = seg_data.GetInt(nPos+442, 8);
701
0
        }
702
0
    }
703
704
/* -------------------------------------------------------------------- */
705
/*      6th and 7th block of ORBIT segment are blank.                   */
706
/*      Read in the 8th block.                                          */
707
/* -------------------------------------------------------------------- */
708
0
    nPos = nStartBlock + 7*512;
709
710
0
    if (STARTS_WITH(seg_data.Get(nPos,8), "ATTITUDE"))
711
0
        l_segment->Type = OrbAttitude;
712
0
    else if (STARTS_WITH(seg_data.Get(nPos,8), "RADAR   "))
713
0
        l_segment->Type = OrbLatLong;
714
0
    else if (STARTS_WITH(seg_data.Get(nPos,8), "AVHRR   "))
715
0
        l_segment->Type = OrbAvhrr;
716
0
    else if (STARTS_WITH(seg_data.Get(nPos,8), "NO_DATA "))
717
0
        l_segment->Type = OrbNone;
718
0
    else
719
0
        return (EphemerisSeg_t*)ThrowPCIDSKExceptionPtr("Invalid Orbit type found: [%s]",
720
0
                              seg_data.Get(nPos,8));
721
722
/* -------------------------------------------------------------------- */
723
/*      Orbit segment is a Satellite Attitude Segment(ATTITUDE) only    */
724
/*      for SPOT 1A.                                                    */
725
/* -------------------------------------------------------------------- */
726
0
    if (l_segment->Type == OrbAttitude)
727
0
    {
728
0
        AttitudeSeg_t  *AttitudeSeg;
729
0
        int            nBlock, nData;
730
731
0
        AttitudeSeg = l_segment->AttitudeSeg = new AttitudeSeg_t();
732
733
/* -------------------------------------------------------------------- */
734
/*      Read in the 9th block.                                          */
735
/* -------------------------------------------------------------------- */
736
0
        nPos = nStartBlock + 512*8;
737
738
0
        AttitudeSeg->Roll = seg_data.GetDouble(nPos, 22);
739
0
        AttitudeSeg->Pitch = seg_data.GetDouble(nPos+22, 22);
740
0
        AttitudeSeg->Yaw = seg_data.GetDouble(nPos+44, 22);
741
0
        AttitudeSeg->NumberOfLine = seg_data.GetInt(nPos+88, 22);
742
0
        if (AttitudeSeg->NumberOfLine % ATT_SEG_LINE_PER_BLOCK != 0)
743
0
            AttitudeSeg->NumberBlockData = 1 +
744
0
                AttitudeSeg->NumberOfLine / ATT_SEG_LINE_PER_BLOCK;
745
0
        else
746
0
            AttitudeSeg->NumberBlockData =
747
0
                AttitudeSeg->NumberOfLine / ATT_SEG_LINE_PER_BLOCK;
748
749
/* -------------------------------------------------------------------- */
750
/*      Read in the line required.                                      */
751
/* -------------------------------------------------------------------- */
752
0
        for (nBlock=0, nData=0; nBlock<AttitudeSeg->NumberBlockData;
753
0
             nBlock++)
754
0
        {
755
/* -------------------------------------------------------------------- */
756
/*      Read in 10+nBlock th block as required.                         */
757
/* -------------------------------------------------------------------- */
758
0
            nPos = nStartBlock + 512*(9+nBlock);
759
760
/* -------------------------------------------------------------------- */
761
/*      Fill in the lines as required.                                  */
762
/* -------------------------------------------------------------------- */
763
0
            for (i=0;
764
0
                 i<ATT_SEG_LINE_PER_BLOCK
765
0
                    && nData < AttitudeSeg->NumberOfLine;
766
0
                 i++, nData++)
767
0
            {
768
0
                AttitudeLine_t oAttitudeLine;
769
0
                oAttitudeLine.ChangeInAttitude
770
0
                    = seg_data.GetDouble(nPos+i*44, 22);
771
0
                oAttitudeLine.ChangeEarthSatelliteDist
772
0
                    = seg_data.GetDouble(nPos+i*44+22, 22);
773
0
                AttitudeSeg->Line.push_back(oAttitudeLine);
774
0
            }
775
0
        }
776
777
0
        if (nData != AttitudeSeg->NumberOfLine)
778
0
        {
779
0
            return (EphemerisSeg_t*)ThrowPCIDSKExceptionPtr("Number of data line read (%d) "
780
0
                     "does not matches with what is specified in "
781
0
                     "the segment (%d).\n", nData,
782
0
                     AttitudeSeg->NumberOfLine);
783
0
        }
784
0
    }
785
/* -------------------------------------------------------------------- */
786
/*      Radar segment (LATLONG)                                         */
787
/* -------------------------------------------------------------------- */
788
0
    else if (l_segment->Type == OrbLatLong)
789
0
    {
790
0
        RadarSeg_t *RadarSeg;
791
0
        int         nBlock, nData;
792
793
0
        RadarSeg = l_segment->RadarSeg = new RadarSeg_t();
794
/* -------------------------------------------------------------------- */
795
/*      Read in the 9th block.                                          */
796
/* -------------------------------------------------------------------- */
797
0
        nPos = nStartBlock + 512*8;
798
799
0
        RadarSeg->Identifier = seg_data.Get(nPos, 16);
800
0
        RadarSeg->Facility = seg_data.Get(nPos+16, 16);
801
0
        RadarSeg->Ellipsoid = seg_data.Get(nPos+32, 16);
802
803
0
        RadarSeg->EquatorialRadius = seg_data.GetDouble(nPos+48, 16);
804
0
        RadarSeg->PolarRadius = seg_data.GetDouble(nPos+64, 16);
805
0
        RadarSeg->IncidenceAngle = seg_data.GetDouble(nPos+80, 16);
806
0
        RadarSeg->LineSpacing = seg_data.GetDouble(nPos+96, 16);
807
0
        RadarSeg->PixelSpacing = seg_data.GetDouble(nPos+112, 16);
808
0
        RadarSeg->ClockAngle = seg_data.GetDouble(nPos+128, 16);
809
810
/* -------------------------------------------------------------------- */
811
/*      Read in the 10th block.                                         */
812
/* -------------------------------------------------------------------- */
813
0
        nPos = nStartBlock + 9*512;
814
815
0
        RadarSeg->NumberBlockData = seg_data.GetInt(nPos, 8);
816
0
        RadarSeg->NumberData = seg_data.GetInt(nPos+8, 8);
817
818
/* -------------------------------------------------------------------- */
819
/*      Read in the 11-th through 11+RadarSeg->NumberBlockData th block */
820
/*      for the ancillary data present.                                 */
821
/* -------------------------------------------------------------------- */
822
0
        for (nBlock = 0, nData = 0;
823
0
             nBlock < RadarSeg->NumberBlockData; nBlock++)
824
0
        {
825
/* -------------------------------------------------------------------- */
826
/*      Read in one block of data.                                      */
827
/* -------------------------------------------------------------------- */
828
0
            nPos = nStartBlock + 512*(10+nBlock);
829
830
0
            for (i=0;
831
0
                 i<ANC_DATA_PER_BLK &&  nData < RadarSeg->NumberData;
832
0
                 i++, nData++)
833
0
            {
834
0
                int     offset;
835
0
                char   *currentindex;
836
0
                void   *currentptr;
837
0
                double  tmp;
838
0
                int32   tmpInt;
839
0
                const double million = 1000000.0;
840
841
/* -------------------------------------------------------------------- */
842
/*      Reading in one ancillary data at a time.                        */
843
/* -------------------------------------------------------------------- */
844
0
                AncillaryData_t oData;
845
0
                offset = i*ANC_DATA_SIZE;
846
847
0
                currentindex = (char *)seg_data.Get(nPos+offset,4);
848
0
                currentptr = (char *) currentindex;
849
0
                SwapData(currentptr,4,1);
850
0
                tmpInt = *((int32 *) currentptr);
851
0
                oData.SlantRangeFstPixel = tmpInt;
852
853
0
                currentindex = (char *)seg_data.Get(nPos+offset+4,4);
854
0
                currentptr = (char *) currentindex;
855
0
                SwapData(currentptr,4,1);
856
0
                tmpInt = *((int32 *) currentptr);
857
0
                oData.SlantRangeLastPixel = tmpInt;
858
859
0
                currentindex = (char *)seg_data.Get(nPos+offset+8,4);
860
0
                currentptr = (char *) currentindex;
861
0
                SwapData(currentptr,4,1);
862
0
                tmpInt = *((int32 *) currentptr);
863
0
                tmp = (double) tmpInt / million;
864
0
                oData.FstPixelLat
865
0
                    = (float) ConvertDeg(tmp, 0);
866
867
0
                currentindex = (char *)seg_data.Get(nPos+offset+12,4);
868
0
                currentptr = (char *) currentindex;
869
0
                SwapData(currentptr,4,1);
870
0
                tmpInt = *((int32 *) currentptr);
871
0
                tmp = (double) tmpInt / million;
872
0
                oData.MidPixelLat
873
0
                    = (float) ConvertDeg(tmp, 0);
874
875
0
                currentindex = (char *)seg_data.Get(nPos+offset+16,4);
876
0
                currentptr = (char *) currentindex;
877
0
                SwapData(currentptr,4,1);
878
0
                tmpInt = *((int32 *) currentptr);
879
0
                tmp = (double) tmpInt / million;
880
0
                oData.LstPixelLat
881
0
                    = (float) ConvertDeg(tmp, 0);
882
883
0
                currentindex = (char *)seg_data.Get(nPos+offset+20,4);
884
0
                currentptr = (char *) currentindex;
885
0
                SwapData(currentptr,4,1);
886
0
                tmpInt = *((int32 *) currentptr);
887
0
                tmp = (double) tmpInt / million;
888
0
                oData.FstPixelLong
889
0
                    = (float) ConvertDeg(tmp, 0);
890
891
0
                currentindex = (char *)seg_data.Get(nPos+offset+24,4);
892
0
                currentptr = (char *) currentindex;
893
0
                SwapData(currentptr,4,1);
894
0
                tmpInt = *((int32 *) currentptr);
895
0
                tmp = (double) tmpInt / million;
896
0
                oData.MidPixelLong
897
0
                    = (float) ConvertDeg(tmp, 0);
898
899
0
                currentindex = (char *)seg_data.Get(nPos+offset+28,4);
900
0
                currentptr = (char *) currentindex;
901
0
                SwapData(currentptr,4,1);
902
0
                tmpInt = *((int32 *) currentptr);
903
0
                tmp = (double) tmpInt / million;
904
0
                oData.LstPixelLong
905
0
                    = (float) ConvertDeg(tmp, 0);
906
907
0
                RadarSeg->Line.push_back(oData);
908
0
            }
909
0
        }
910
911
0
        if (RadarSeg->NumberData != nData)
912
0
        {
913
0
            return (EphemerisSeg_t*)ThrowPCIDSKExceptionPtr("Number "
914
0
                     "of data lines read (%d) does not match with"
915
0
                     "\nwhat is specified in segment (%d).\n", nData,
916
0
                     RadarSeg->NumberData);
917
0
        }
918
0
    }
919
/* -------------------------------------------------------------------- */
920
/*      AVHRR segment                                                   */
921
/* -------------------------------------------------------------------- */
922
0
    else if (l_segment->Type == OrbAvhrr)
923
0
    {
924
0
        ReadAvhrrEphemerisSegment( nStartBlock, l_segment.get());
925
0
    }
926
927
0
    return l_segment.release();
928
0
}
929
930
/************************************************************************/
931
/*                        EphemerisToBinary()                           */
932
/************************************************************************/
933
/**
934
 * Write an Orbit segment information into a binary buffer of size 4096.
935
 * The caller is responsible to free this memory with delete [].
936
 *
937
 * @param psOrbit the orbit information to write into the binary
938
 * @param nStartBlock where to start writing in the buffer.
939
 */
940
void
941
CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
942
                                              int nStartBlock )
943
944
0
{
945
0
    int i,j;
946
947
/* -------------------------------------------------------------------- */
948
/*      The binary data must be at least 8 blocks (4096 bytes) long     */
949
/*      for the common information.                                     */
950
/* -------------------------------------------------------------------- */
951
0
    seg_data.SetSize(nStartBlock+4096);
952
0
    memset(seg_data.buffer+nStartBlock,' ',4096);
953
954
0
    int nPos = nStartBlock;
955
956
/* -------------------------------------------------------------------- */
957
/*      Write the first block                                           */
958
/* -------------------------------------------------------------------- */
959
960
0
    seg_data.Put("ORBIT   ",nPos,8);
961
0
    seg_data.Put(psOrbit->SatelliteDesc.c_str(), nPos+8,32,true);
962
0
    seg_data.Put(psOrbit->SceneID.c_str(), nPos+40,32,true);
963
964
/* -------------------------------------------------------------------- */
965
/*      Write the second block                                          */
966
/* -------------------------------------------------------------------- */
967
0
    nPos = nStartBlock + 1*512;
968
969
0
    seg_data.Put(psOrbit->SatelliteSensor.c_str(), nPos,16);
970
0
    seg_data.Put(psOrbit->SensorNo.c_str(),nPos+22,2,true);
971
0
    seg_data.Put(psOrbit->DateImageTaken.c_str(), nPos+44,22,true);
972
973
0
    if (psOrbit->SupSegExist)
974
0
        seg_data.Put("Y",nPos+66,1);
975
0
    else
976
0
        seg_data.Put("N",nPos+66,1);
977
978
0
    seg_data.Put(psOrbit->FieldOfView,nPos+88,22,"%22.14f");
979
0
    seg_data.Put(psOrbit->ViewAngle,nPos+110,22,"%22.14f");
980
0
    seg_data.Put(psOrbit->NumColCentre,nPos+132,22,"%22.14f");
981
0
    seg_data.Put(psOrbit->RadialSpeed,nPos+154,22,"%22.14f");
982
0
    seg_data.Put(psOrbit->Eccentricity,nPos+176,22,"%22.14f");
983
0
    seg_data.Put(psOrbit->Height,nPos+198,22,"%22.14f");
984
0
    seg_data.Put(psOrbit->Inclination,nPos+220,22,"%22.14f");
985
0
    seg_data.Put(psOrbit->TimeInterval,nPos+242,22,"%22.14f");
986
0
    seg_data.Put(psOrbit->NumLineCentre,nPos+264,22,"%22.14f");
987
0
    seg_data.Put(psOrbit->LongCentre,nPos+286,22,"%22.14f");
988
0
    seg_data.Put(psOrbit->AngularSpd,nPos+308,22,"%22.14f");
989
0
    seg_data.Put(psOrbit->AscNodeLong,nPos+330,22,"%22.14f");
990
0
    seg_data.Put(psOrbit->ArgPerigee,nPos+352,22,"%22.14f");
991
0
    seg_data.Put(psOrbit->LatCentre,nPos+374,22,"%22.14f");
992
0
    seg_data.Put(psOrbit->EarthSatelliteDist,nPos+396,22,"%22.14f");
993
0
    seg_data.Put(psOrbit->NominalPitch,nPos+418,22,"%22.14f");
994
0
    seg_data.Put(psOrbit->TimeAtCentre,nPos+440,22,"%22.14f");
995
0
    seg_data.Put(psOrbit->SatelliteArg,nPos+462,22,"%22.14f");
996
997
0
    if (psOrbit->bDescending)
998
0
        seg_data.Put("DESCENDING",nPos+484,10);
999
0
    else
1000
0
        seg_data.Put("ASCENDING ",nPos+484,10);
1001
1002
/* -------------------------------------------------------------------- */
1003
/*      Write the third block                                           */
1004
/* -------------------------------------------------------------------- */
1005
0
    nPos = nStartBlock + 512*2;
1006
1007
0
    seg_data.Put(psOrbit->XCentre,nPos,22,"%22.14f");
1008
0
    seg_data.Put(psOrbit->YCentre,nPos+22,22,"%22.14f");
1009
0
    seg_data.Put(psOrbit->UtmXCentre,nPos+44,22,"%22.14f");
1010
0
    seg_data.Put(psOrbit->UtmYCentre,nPos+66,22,"%22.14f");
1011
0
    seg_data.Put(psOrbit->PixelRes,nPos+88,22,"%22.14f");
1012
0
    seg_data.Put(psOrbit->LineRes,nPos+110,22,"%22.14f");
1013
1014
0
    if (psOrbit->CornerAvail == true)
1015
0
        seg_data.Put("Y",nPos+132,1);
1016
0
    else
1017
0
        seg_data.Put("N",nPos+132,1);
1018
1019
0
    seg_data.Put(psOrbit->MapUnit.c_str(),nPos+133,16,true);
1020
1021
0
    seg_data.Put(psOrbit->XUL,nPos+149,22,"%22.14f");
1022
0
    seg_data.Put(psOrbit->YUL,nPos+171,22,"%22.14f");
1023
0
    seg_data.Put(psOrbit->XUR,nPos+193,22,"%22.14f");
1024
0
    seg_data.Put(psOrbit->YUR,nPos+215,22,"%22.14f");
1025
0
    seg_data.Put(psOrbit->XLR,nPos+237,22,"%22.14f");
1026
0
    seg_data.Put(psOrbit->YLR,nPos+259,22,"%22.14f");
1027
0
    seg_data.Put(psOrbit->XLL,nPos+281,22,"%22.14f");
1028
0
    seg_data.Put(psOrbit->YLL,nPos+303,22,"%22.14f");
1029
0
    seg_data.Put(psOrbit->UtmXUL,nPos+325,22,"%22.14f");
1030
0
    seg_data.Put(psOrbit->UtmYUL,nPos+347,22,"%22.14f");
1031
0
    seg_data.Put(psOrbit->UtmXUR,nPos+369,22,"%22.14f");
1032
0
    seg_data.Put(psOrbit->UtmYUR,nPos+391,22,"%22.14f");
1033
0
    seg_data.Put(psOrbit->UtmXLR,nPos+413,22,"%22.14f");
1034
0
    seg_data.Put(psOrbit->UtmYLR,nPos+435,22,"%22.14f");
1035
0
    seg_data.Put(psOrbit->UtmXLL,nPos+457,22,"%22.14f");
1036
0
    seg_data.Put(psOrbit->UtmYLL,nPos+479,22,"%22.14f");
1037
1038
/* -------------------------------------------------------------------- */
1039
/*      Write the fourth block                                          */
1040
/* -------------------------------------------------------------------- */
1041
0
    nPos = nStartBlock + 512*3;
1042
1043
0
    seg_data.Put(psOrbit->LongCentreDeg,nPos,22,"%16.7f");
1044
0
    seg_data.Put(psOrbit->LatCentreDeg,nPos+16,22,"%16.7f");
1045
0
    seg_data.Put(psOrbit->LongUL,nPos+32,22,"%16.7f");
1046
0
    seg_data.Put(psOrbit->LatUL,nPos+48,22,"%16.7f");
1047
0
    seg_data.Put(psOrbit->LongUR,nPos+64,22,"%16.7f");
1048
0
    seg_data.Put(psOrbit->LatUR,nPos+80,22,"%16.7f");
1049
0
    seg_data.Put(psOrbit->LongLR,nPos+96,22,"%16.7f");
1050
0
    seg_data.Put(psOrbit->LatLR,nPos+112,22,"%16.7f");
1051
0
    seg_data.Put(psOrbit->LongLL,nPos+128,22,"%16.7f");
1052
0
    seg_data.Put(psOrbit->LatLL,nPos+144,22,"%16.7f");
1053
0
    seg_data.Put(psOrbit->HtCentre,nPos+160,22,"%16.7f");
1054
0
    seg_data.Put(psOrbit->HtUL,nPos+176,22,"%16.7f");
1055
0
    seg_data.Put(psOrbit->HtUR,nPos+192,22,"%16.7f");
1056
0
    seg_data.Put(psOrbit->HtLR,nPos+208,22,"%16.7f");
1057
0
    seg_data.Put(psOrbit->HtLL,nPos+224,22,"%16.7f");
1058
1059
/* -------------------------------------------------------------------- */
1060
/*      Write the fifth block                                           */
1061
/* -------------------------------------------------------------------- */
1062
0
    nPos = nStartBlock + 512*4;
1063
1064
0
    seg_data.Put(psOrbit->ImageRecordLength,nPos,16);
1065
0
    seg_data.Put(psOrbit->NumberImageLine,nPos+16,16);
1066
0
    seg_data.Put(psOrbit->NumberBytePerPixel,nPos+32,16);
1067
0
    seg_data.Put(psOrbit->NumberSamplePerLine,nPos+48,16);
1068
0
    seg_data.Put(psOrbit->NumberPrefixBytes,nPos+64,16);
1069
0
    seg_data.Put(psOrbit->NumberSuffixBytes,nPos+80,16);
1070
1071
/* -------------------------------------------------------------------- */
1072
/*      Write the sixth and seventh block (blanks)                      */
1073
/*      For SPOT it is not blank                                        */
1074
/* -------------------------------------------------------------------- */
1075
0
    nPos = nStartBlock + 512*5;
1076
1077
0
    if (psOrbit->SPNCoeff > 0)
1078
0
    {
1079
0
        if (psOrbit->SPNCoeff == 20)
1080
0
        {
1081
0
            seg_data.Put("SPOT1BOD",nPos,8);
1082
0
            seg_data.Put(psOrbit->SPNCoeff,nPos+22,22);
1083
1084
0
            j = 44;
1085
0
            for (i=0; i<20; i++)
1086
0
            {
1087
0
                seg_data.Put(psOrbit->SPCoeff1B[i],
1088
0
                                     nPos+j,22,"%22.14f");
1089
0
                j += 22;
1090
0
            }
1091
0
        }
1092
0
        else
1093
0
        {
1094
0
            seg_data.Put("SPOT1BNW",nPos,8);
1095
0
            seg_data.Put(psOrbit->SPNCoeff,nPos+22,22);
1096
1097
0
            j = 44;
1098
0
            for (i=0; i<20; i++)
1099
0
            {
1100
0
                seg_data.Put(psOrbit->SPCoeff1B[i],
1101
0
                                     nPos+j,22,"%22.14f");
1102
0
                j += 22;
1103
0
            }
1104
1105
0
            nPos = nStartBlock + 512*6;
1106
1107
0
            j = 0;
1108
0
            for (i=20; i<39; i++)
1109
0
            {
1110
0
                seg_data.Put(psOrbit->SPCoeff1B[i],
1111
0
                                     nPos+j,22,"%22.14f");
1112
0
                j += 22;
1113
0
            }
1114
1115
0
            seg_data.Put(psOrbit->SPCoeffSg[0],nPos+418,8);
1116
0
            seg_data.Put(psOrbit->SPCoeffSg[1],nPos+426,8);
1117
0
            seg_data.Put(psOrbit->SPCoeffSg[2],nPos+434,8);
1118
0
            seg_data.Put(psOrbit->SPCoeffSg[3],nPos+442,8);
1119
0
        }
1120
0
    }
1121
1122
/* -------------------------------------------------------------------- */
1123
/*      Write the eighth block.                                         */
1124
/* -------------------------------------------------------------------- */
1125
0
    nPos = nStartBlock + 512*7;
1126
1127
0
    if (psOrbit->Type == OrbAttitude)
1128
0
        seg_data.Put("ATTITUDE",nPos,8);
1129
0
    else if (psOrbit->Type == OrbLatLong)
1130
0
        seg_data.Put("RADAR   ",nPos,8);
1131
0
    else if (psOrbit->Type == OrbAvhrr)
1132
0
        seg_data.Put("AVHRR   ",nPos,8);
1133
0
    else if (psOrbit->Type == OrbNone)
1134
0
        seg_data.Put("NO_DATA ",nPos,8);
1135
0
    else
1136
0
    {
1137
0
        return ThrowPCIDSKException("Invalid Orbit type.");
1138
0
    }
1139
1140
/* ==================================================================== */
1141
/*      Orbit segment is a Satellite Attitude Segment(ATTITUDE) only    */
1142
/*      for SPOT 1A.                                                    */
1143
/* ==================================================================== */
1144
0
    if (psOrbit->Type == OrbAttitude)
1145
0
    {
1146
0
        AttitudeSeg_t *AttitudeSeg;
1147
0
        int             nBlock, nData;
1148
1149
0
        AttitudeSeg = psOrbit->AttitudeSeg;
1150
1151
0
        if (AttitudeSeg == nullptr)
1152
0
        {
1153
0
            return ThrowPCIDSKException("The AttitudeSeg is NULL.");
1154
0
        }
1155
1156
/* -------------------------------------------------------------------- */
1157
/*      Add one block                                                   */
1158
/* -------------------------------------------------------------------- */
1159
0
        seg_data.SetSize(seg_data.buffer_size + 512);
1160
1161
0
        nPos = nStartBlock + 512*8;
1162
0
        memset(seg_data.buffer+nPos,' ',512);
1163
1164
/* -------------------------------------------------------------------- */
1165
/*      Write the ninth block.                                          */
1166
/* -------------------------------------------------------------------- */
1167
1168
0
        seg_data.Put(AttitudeSeg->Roll,nPos,22,"%22.14f");
1169
0
        seg_data.Put(AttitudeSeg->Pitch,nPos+22,22,"%22.14f");
1170
0
        seg_data.Put(AttitudeSeg->Yaw,nPos+44,22,"%22.14f");
1171
1172
0
        if (AttitudeSeg->NumberOfLine % ATT_SEG_LINE_PER_BLOCK != 0)
1173
0
            AttitudeSeg->NumberBlockData = 1 +
1174
0
                AttitudeSeg->NumberOfLine / ATT_SEG_LINE_PER_BLOCK;
1175
0
        else
1176
0
            AttitudeSeg->NumberBlockData =
1177
0
                AttitudeSeg->NumberOfLine / ATT_SEG_LINE_PER_BLOCK;
1178
1179
0
        seg_data.Put(AttitudeSeg->NumberBlockData,nPos+66,22);
1180
0
        seg_data.Put(AttitudeSeg->NumberOfLine,nPos+88,22);
1181
1182
/* -------------------------------------------------------------------- */
1183
/*      Add NumberBlockData blocks to array.                            */
1184
/* -------------------------------------------------------------------- */
1185
0
        seg_data.SetSize(seg_data.buffer_size +
1186
0
                                 512 * AttitudeSeg->NumberBlockData);
1187
1188
0
        nPos = nStartBlock + 512*9;
1189
0
        memset(seg_data.buffer+nPos,' ',
1190
0
               512 * AttitudeSeg->NumberBlockData);
1191
1192
/* -------------------------------------------------------------------- */
1193
/*      Write out the line required.                                    */
1194
/* -------------------------------------------------------------------- */
1195
0
        for (nBlock=0, nData=0; nBlock<AttitudeSeg->NumberBlockData;
1196
0
             nBlock++)
1197
0
        {
1198
0
            nPos = nStartBlock + 512*(nBlock + 9);
1199
1200
/* -------------------------------------------------------------------- */
1201
/*      Fill in buffer as required.                                     */
1202
/* -------------------------------------------------------------------- */
1203
0
            for (i=0;
1204
0
                i<ATT_SEG_LINE_PER_BLOCK
1205
0
                    && nData < AttitudeSeg->NumberOfLine;
1206
0
                i++, nData++)
1207
0
            {
1208
0
                seg_data.Put(
1209
0
                    AttitudeSeg->Line[nData].ChangeInAttitude,
1210
0
                    nPos+i*44,22,"%22.14f");
1211
0
                seg_data.Put(
1212
0
                    AttitudeSeg->Line[nData].ChangeEarthSatelliteDist,
1213
0
                    nPos+i*44+22,22,"%22.14f");
1214
0
            }
1215
0
        }
1216
1217
0
        if (nData != AttitudeSeg->NumberOfLine)
1218
0
        {
1219
0
            return ThrowPCIDSKException("Number of data line written"
1220
0
                    " (%d) does not match with\nwhat is specified "
1221
0
                    " in the segment (%d).\n",
1222
0
                    nData, AttitudeSeg->NumberOfLine);
1223
0
        }
1224
0
    }
1225
1226
/* ==================================================================== */
1227
/*      Radar segment (LATLONG)                                         */
1228
/* ==================================================================== */
1229
0
    else if (psOrbit->Type == OrbLatLong)
1230
0
    {
1231
0
        RadarSeg_t *RadarSeg;
1232
0
        int         nBlock, nData;
1233
1234
0
        RadarSeg = psOrbit->RadarSeg;
1235
1236
0
        if (RadarSeg == nullptr)
1237
0
        {
1238
0
            return ThrowPCIDSKException("The RadarSeg is NULL.");
1239
0
        }
1240
1241
/* -------------------------------------------------------------------- */
1242
/*      Add two blocks.                                                 */
1243
/* -------------------------------------------------------------------- */
1244
0
        seg_data.SetSize(seg_data.buffer_size + 512*2);
1245
1246
0
        nPos = nStartBlock + 512*8;
1247
0
        memset(seg_data.buffer+nPos,' ', 512*2);
1248
1249
/* -------------------------------------------------------------------- */
1250
/*      Write out the ninth block.                                      */
1251
/* -------------------------------------------------------------------- */
1252
0
        seg_data.Put(RadarSeg->Identifier.c_str(), nPos,16);
1253
0
        seg_data.Put(RadarSeg->Facility.c_str(), nPos+16,16);
1254
0
        seg_data.Put(RadarSeg->Ellipsoid.c_str(), nPos+32,16);
1255
1256
0
        seg_data.Put(RadarSeg->EquatorialRadius,nPos+48,16,"%16.7f");
1257
0
        seg_data.Put(RadarSeg->PolarRadius,nPos+64,16,"%16.7f");
1258
0
        seg_data.Put(RadarSeg->IncidenceAngle,nPos+80,16,"%16.7f");
1259
0
        seg_data.Put(RadarSeg->LineSpacing,nPos+96,16,"%16.7f");
1260
0
        seg_data.Put(RadarSeg->PixelSpacing,nPos+112,16,"%16.7f");
1261
0
        seg_data.Put(RadarSeg->ClockAngle,nPos+128,16,"%16.7f");
1262
1263
/* -------------------------------------------------------------------- */
1264
/*      Write out the tenth block.                                      */
1265
/* -------------------------------------------------------------------- */
1266
0
        nPos = nStartBlock + 512*9;
1267
1268
0
        seg_data.Put(RadarSeg->NumberBlockData,nPos,8);
1269
0
        seg_data.Put(RadarSeg->NumberData,nPos+8,8);
1270
1271
/* -------------------------------------------------------------------- */
1272
/*      Make room for all the following per-line data.                  */
1273
/* -------------------------------------------------------------------- */
1274
0
        seg_data.SetSize(seg_data.buffer_size +
1275
0
                                 512 * RadarSeg->NumberBlockData);
1276
1277
0
        nPos = nStartBlock + 512*10;
1278
0
        memset(seg_data.buffer+nPos,' ',
1279
0
               512 * RadarSeg->NumberBlockData);
1280
1281
/* -------------------------------------------------------------------- */
1282
/*      Write out the 11-th through 11+psOrbit->NumberBlockData  block  */
1283
/*      for the ancillary data present.                                 */
1284
/* -------------------------------------------------------------------- */
1285
0
        for (nBlock = 0, nData = 0;
1286
0
             nBlock < RadarSeg->NumberBlockData; nBlock++)
1287
0
        {
1288
0
            for (i=0;
1289
0
                 i<ANC_DATA_PER_BLK &&  nData < RadarSeg->NumberData;
1290
0
                 i++, nData++)
1291
0
            {
1292
0
                int             offset;
1293
0
                char            *currentptr, *currentindex;
1294
0
                double          tmp, tmpDouble;
1295
0
                const double    million = 1000000.0;
1296
0
                int32           tmpInt;
1297
1298
/* -------------------------------------------------------------------- */
1299
/*      Point to correct block                                          */
1300
/* -------------------------------------------------------------------- */
1301
0
                nPos = nStartBlock + 512*(10+nBlock);
1302
1303
/* -------------------------------------------------------------------- */
1304
/*      Writing out one ancillary data at a time.                       */
1305
/* -------------------------------------------------------------------- */
1306
0
                offset = i*ANC_DATA_SIZE;
1307
1308
0
                currentptr =
1309
0
                    (char *) &(RadarSeg->Line[nData].SlantRangeFstPixel);
1310
0
                SwapData(currentptr,4,1);
1311
0
                currentindex = &(seg_data.buffer[nPos+offset]);
1312
0
                std::memcpy((void *) currentindex,currentptr, 4);
1313
1314
0
                currentptr =
1315
0
                    (char *) &(RadarSeg->Line[nData].SlantRangeLastPixel);
1316
0
                SwapData(currentptr,4,1);
1317
0
                currentindex += 4;
1318
0
                std::memcpy((void *) currentindex,currentptr, 4);
1319
1320
0
                tmp = ConvertDeg(RadarSeg->Line[nData].FstPixelLat, 1);
1321
0
                tmpDouble =  tmp * million;
1322
0
                tmpInt = (int32) tmpDouble;
1323
0
                currentptr = (char *) &tmpInt;
1324
0
                SwapData(currentptr,4,1);
1325
0
                currentindex += 4;
1326
0
                std::memcpy((void *) currentindex,currentptr, 4);
1327
1328
0
                tmp = ConvertDeg(RadarSeg->Line[nData].MidPixelLat, 1);
1329
0
                tmpDouble =  tmp * million;
1330
0
                tmpInt = (int32) tmpDouble;
1331
0
                currentptr = (char *) &tmpInt;
1332
0
                SwapData(currentptr,4,1);
1333
0
                currentindex += 4;
1334
0
                std::memcpy((void *) currentindex,currentptr, 4);
1335
1336
0
                tmp = ConvertDeg(RadarSeg->Line[nData].LstPixelLat, 1);
1337
0
                tmpDouble =  tmp * million;
1338
0
                tmpInt = (int32) tmpDouble;
1339
0
                currentptr = (char *) &tmpInt;
1340
0
                SwapData(currentptr,4,1);
1341
0
                currentindex += 4;
1342
0
                std::memcpy((void *) currentindex,currentptr, 4);
1343
1344
0
                tmp = ConvertDeg(RadarSeg->Line[nData].FstPixelLong, 1);
1345
0
                tmpDouble =  tmp * million;
1346
0
                tmpInt = (int32) tmpDouble;
1347
0
                currentptr = (char *) &tmpInt;
1348
0
                SwapData(currentptr,4,1);
1349
0
                currentindex += 4;
1350
0
                std::memcpy((void *) currentindex,currentptr, 4);
1351
1352
0
                tmp = ConvertDeg(RadarSeg->Line[nData].MidPixelLong, 1);
1353
0
                tmpDouble = tmp * million;
1354
0
                tmpInt = (int32) tmpDouble;
1355
0
                currentptr = (char *) &tmpInt;
1356
0
                SwapData(currentptr,4,1);
1357
0
                currentindex += 4;
1358
0
                std::memcpy((void *) currentindex,currentptr, 4);
1359
1360
0
                tmp = ConvertDeg(RadarSeg->Line[nData].LstPixelLong, 1);
1361
0
                tmpDouble =  tmp * million;
1362
0
                tmpInt = (int32) tmpDouble;
1363
0
                currentptr = (char *) &tmpInt;
1364
0
                SwapData(currentptr,4,1);
1365
0
                currentindex += 4;
1366
0
                std::memcpy((void *) currentindex,currentptr, 4);
1367
0
            }
1368
0
        }
1369
0
    }
1370
1371
/* ==================================================================== */
1372
/*      AVHRR segment                                                   */
1373
/* ==================================================================== */
1374
0
    else if ( psOrbit->Type == OrbAvhrr &&
1375
0
              psOrbit->AvhrrSeg->nNumRecordsPerBlock > 0 )
1376
0
    {
1377
0
        WriteAvhrrEphemerisSegment(nStartBlock + 8*512 , psOrbit);
1378
0
    }
1379
0
}