Line data Source code
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 : 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 0 : int MinFunction(int a,int b)
39 : {
40 0 : return (a<b)?a:b;
41 : }
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 0 : CPCIDSKEphemerisSegment::CPCIDSKEphemerisSegment(PCIDSKFile *fileIn,
52 : int segmentIn,
53 : const char *segment_pointer,
54 0 : bool bLoad) :
55 : CPCIDSKSegment(fileIn, segmentIn, segment_pointer),
56 0 : loaded_(false),mbModified(false)
57 : {
58 0 : mpoEphemeris = nullptr;
59 0 : if(bLoad)
60 : {
61 0 : Load();
62 : }
63 0 : }
64 :
65 :
66 0 : CPCIDSKEphemerisSegment::~CPCIDSKEphemerisSegment()
67 : {
68 0 : delete mpoEphemeris;
69 0 : }
70 :
71 : /**
72 : * Load the contents of the segment
73 : */
74 0 : void CPCIDSKEphemerisSegment::Load()
75 : {
76 : // Check if we've already loaded the segment into memory
77 0 : if (loaded_) {
78 0 : return;
79 : }
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 : {
92 0 : seg_data.Put("ORBIT ",0,8);
93 0 : loaded_ = true;
94 0 : return ;
95 : }
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 : }
103 :
104 : /**
105 : * Write the segment on disk
106 : */
107 0 : void CPCIDSKEphemerisSegment::Write(void)
108 : {
109 : //We are not writing if nothing was loaded.
110 0 : if (!loaded_) {
111 0 : return;
112 : }
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 : }
122 :
123 : /**
124 : * Synchronize the segment, if it was modified then
125 : * write it into disk.
126 : */
127 0 : void CPCIDSKEphemerisSegment::Synchronize()
128 : {
129 0 : if(mbModified)
130 : {
131 0 : this->Write();
132 : }
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 0 : double CPCIDSKEphemerisSegment::ConvertDeg(double degree, int mode)
146 : {
147 : double result;
148 :
149 0 : if (mode == 0)
150 : {
151 : /* -------------------------------------------------------------------- */
152 : /* degree is in range of 0 to 360 */
153 : /* -------------------------------------------------------------------- */
154 0 : if (degree > 180)
155 0 : result = degree - 360;
156 : else
157 0 : result = degree;
158 : }
159 : else
160 : {
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 : else
167 0 : result = degree;
168 : }
169 0 : return (result);
170 : }
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 0 : CPCIDSKEphemerisSegment::ReadAvhrrEphemerisSegment(int nStartBlock,
183 : EphemerisSeg_t *psEphSegRec)
184 : {
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 : else
208 0 : as->bIsAscending = false;
209 0 : if ( STARTS_WITH(seg_data.Get(nPos+64,7), "ROTATED") )
210 0 : as->bIsImageRotated = true;
211 : 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 : {
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 : {
277 0 : break;
278 : }
279 :
280 0 : for(int i = 0; i < nNumRecords; ++i)
281 : {
282 0 : AvhrrLine_t sLine;
283 0 : ReadAvhrrScanlineRecord(nPos+i*80, &sLine);
284 0 : as->Line.push_back(sLine);
285 : }
286 :
287 0 : ++nBlock;
288 : }
289 : }
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 0 : CPCIDSKEphemerisSegment::ReadAvhrrScanlineRecord(int nPos,
301 : AvhrrLine_t *psScanlineRecord)
302 : {
303 : 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 : {
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 : }
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 0 : CPCIDSKEphemerisSegment::ReadAvhrrInt32(unsigned char* pbyBuf)
339 : {
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 : }
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 0 : CPCIDSKEphemerisSegment::WriteAvhrrEphemerisSegment(int nStartBlock,
358 : EphemerisSeg_t *psEphSegRec)
359 : {
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 : {
369 0 : return ThrowPCIDSKException("The AvhrrSeg is NULL.");
370 : }
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 : 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 : 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 : {
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 : {
465 0 : WriteAvhrrScanlineRecord(&(as->Line[nLine+i]), nPos + i*80);
466 : }
467 :
468 0 : ++nBlock;
469 : }
470 : }
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 0 : CPCIDSKEphemerisSegment::WriteAvhrrScanlineRecord(
482 : AvhrrLine_t *psScanlineRecord,
483 : int nPos)
484 : {
485 : 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 : {
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 : }
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 0 : void CPCIDSKEphemerisSegment::WriteAvhrrInt32(int nValue,
522 : unsigned char* pbyBuf)
523 : {
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 0 : CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
544 :
545 : {
546 : 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 : {
566 0 : if (l_segment->SatelliteSensor[i] == ' ')
567 : {
568 0 : l_segment->SatelliteSensor = l_segment->SatelliteSensor.substr(0,i);
569 0 : break;
570 : }
571 : }
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 : 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 : 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 : {
681 0 : l_segment->SPNCoeff = seg_data.GetInt(nPos+22, 22);
682 0 : for (i=0; i<20; i++)
683 : {
684 0 : l_segment->SPCoeff1B[i] =
685 0 : seg_data.GetDouble(nPos+(i+2)*22, 22);
686 : }
687 :
688 0 : if (STARTS_WITH(seg_data.Get(nPos,8), "SPOT1BNW"))
689 : {
690 0 : nPos = nStartBlock + 6*512;
691 :
692 0 : for (i=0; i<19; i++)
693 : {
694 0 : l_segment->SPCoeff1B[i+20] =
695 0 : seg_data.GetDouble(nPos+i*22, 22);
696 : }
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 : }
702 : }
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 : 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 : {
728 : AttitudeSeg_t *AttitudeSeg;
729 : 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 : 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 : nBlock++)
754 : {
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 : i<ATT_SEG_LINE_PER_BLOCK
765 0 : && nData < AttitudeSeg->NumberOfLine;
766 : i++, nData++)
767 : {
768 0 : AttitudeLine_t oAttitudeLine;
769 : oAttitudeLine.ChangeInAttitude
770 0 : = seg_data.GetDouble(nPos+i*44, 22);
771 : oAttitudeLine.ChangeEarthSatelliteDist
772 0 : = seg_data.GetDouble(nPos+i*44+22, 22);
773 0 : AttitudeSeg->Line.push_back(oAttitudeLine);
774 : }
775 : }
776 :
777 0 : if (nData != AttitudeSeg->NumberOfLine)
778 : {
779 0 : return (EphemerisSeg_t*)ThrowPCIDSKExceptionPtr("Number of data line read (%d) "
780 : "does not matches with what is specified in "
781 : "the segment (%d).\n", nData,
782 0 : AttitudeSeg->NumberOfLine);
783 : }
784 : }
785 : /* -------------------------------------------------------------------- */
786 : /* Radar segment (LATLONG) */
787 : /* -------------------------------------------------------------------- */
788 0 : else if (l_segment->Type == OrbLatLong)
789 : {
790 : RadarSeg_t *RadarSeg;
791 : 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 : {
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 : i++, nData++)
833 : {
834 : int offset;
835 : char *currentindex;
836 : void *currentptr;
837 : double tmp;
838 : 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 : 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 : 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 : 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 : 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 : 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 : oData.LstPixelLong
905 0 : = (float) ConvertDeg(tmp, 0);
906 :
907 0 : RadarSeg->Line.push_back(oData);
908 : }
909 : }
910 :
911 0 : if (RadarSeg->NumberData != nData)
912 : {
913 0 : return (EphemerisSeg_t*)ThrowPCIDSKExceptionPtr("Number "
914 : "of data lines read (%d) does not match with"
915 : "\nwhat is specified in segment (%d).\n", nData,
916 0 : RadarSeg->NumberData);
917 : }
918 : }
919 : /* -------------------------------------------------------------------- */
920 : /* AVHRR segment */
921 : /* -------------------------------------------------------------------- */
922 0 : else if (l_segment->Type == OrbAvhrr)
923 : {
924 0 : ReadAvhrrEphemerisSegment( nStartBlock, l_segment.get());
925 : }
926 :
927 0 : return l_segment.release();
928 : }
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 0 : CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
942 : int nStartBlock )
943 :
944 : {
945 : 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 : 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 : 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 : 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 : {
1079 0 : if (psOrbit->SPNCoeff == 20)
1080 : {
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 : {
1087 0 : seg_data.Put(psOrbit->SPCoeff1B[i],
1088 : nPos+j,22,"%22.14f");
1089 0 : j += 22;
1090 : }
1091 : }
1092 : else
1093 : {
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 : {
1100 0 : seg_data.Put(psOrbit->SPCoeff1B[i],
1101 : nPos+j,22,"%22.14f");
1102 0 : j += 22;
1103 : }
1104 :
1105 0 : nPos = nStartBlock + 512*6;
1106 :
1107 0 : j = 0;
1108 0 : for (i=20; i<39; i++)
1109 : {
1110 0 : seg_data.Put(psOrbit->SPCoeff1B[i],
1111 : nPos+j,22,"%22.14f");
1112 0 : j += 22;
1113 : }
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 : }
1120 : }
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 : else
1136 : {
1137 0 : return ThrowPCIDSKException("Invalid Orbit type.");
1138 : }
1139 :
1140 : /* ==================================================================== */
1141 : /* Orbit segment is a Satellite Attitude Segment(ATTITUDE) only */
1142 : /* for SPOT 1A. */
1143 : /* ==================================================================== */
1144 0 : if (psOrbit->Type == OrbAttitude)
1145 : {
1146 : AttitudeSeg_t *AttitudeSeg;
1147 : int nBlock, nData;
1148 :
1149 0 : AttitudeSeg = psOrbit->AttitudeSeg;
1150 :
1151 0 : if (AttitudeSeg == nullptr)
1152 : {
1153 0 : return ThrowPCIDSKException("The AttitudeSeg is NULL.");
1154 : }
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 : 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 : nBlock++)
1197 : {
1198 0 : nPos = nStartBlock + 512*(nBlock + 9);
1199 :
1200 : /* -------------------------------------------------------------------- */
1201 : /* Fill in buffer as required. */
1202 : /* -------------------------------------------------------------------- */
1203 0 : for (i=0;
1204 : i<ATT_SEG_LINE_PER_BLOCK
1205 0 : && nData < AttitudeSeg->NumberOfLine;
1206 : i++, nData++)
1207 : {
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 : }
1215 : }
1216 :
1217 0 : if (nData != AttitudeSeg->NumberOfLine)
1218 : {
1219 0 : return ThrowPCIDSKException("Number of data line written"
1220 : " (%d) does not match with\nwhat is specified "
1221 : " in the segment (%d).\n",
1222 0 : nData, AttitudeSeg->NumberOfLine);
1223 : }
1224 : }
1225 :
1226 : /* ==================================================================== */
1227 : /* Radar segment (LATLONG) */
1228 : /* ==================================================================== */
1229 0 : else if (psOrbit->Type == OrbLatLong)
1230 : {
1231 : RadarSeg_t *RadarSeg;
1232 : int nBlock, nData;
1233 :
1234 0 : RadarSeg = psOrbit->RadarSeg;
1235 :
1236 0 : if (RadarSeg == nullptr)
1237 : {
1238 0 : return ThrowPCIDSKException("The RadarSeg is NULL.");
1239 : }
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 : {
1288 0 : for (i=0;
1289 0 : i<ANC_DATA_PER_BLK && nData < RadarSeg->NumberData;
1290 : i++, nData++)
1291 : {
1292 : int offset;
1293 : char *currentptr, *currentindex;
1294 : double tmp, tmpDouble;
1295 0 : const double million = 1000000.0;
1296 : 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 : }
1368 : }
1369 : }
1370 :
1371 : /* ==================================================================== */
1372 : /* AVHRR segment */
1373 : /* ==================================================================== */
1374 0 : else if ( psOrbit->Type == OrbAvhrr &&
1375 0 : psOrbit->AvhrrSeg->nNumRecordsPerBlock > 0 )
1376 : {
1377 0 : WriteAvhrrEphemerisSegment(nStartBlock + 8*512 , psOrbit);
1378 : }
1379 : }
|