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