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