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