OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimPleiadesDimapSupportData.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 // Copyright (C) 2012 Centre National Etudes Spatiales
3 //
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 3 of the License, or (at your option) any later version.
8 //
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 //
18 // Author : Mickael Savinaud (mickael.savinaud@c-s.fr)
19 //
20 // Description:
21 //
22 // Contains declaration of class ossimPleiadesDimapSupportData
23 //
24 //*****************************************************************************
25 
28 #include <ossim/base/ossimNotify.h>
30 #include <ossim/base/ossimTrace.h>
31 
36 
37 #include <ossimPluginCommon.h>
38 #include <ossim/base/ossimCommon.h>
39 
40 #include <ossim/base/ossimDatum.h>
42 
43 #include <cstdio>
44 #include <cstdlib>
45 #include <iostream>
46 #include <iterator>
47 #include <sstream>
48 
49 
50 // Define Trace flags for use within this file:
51 static ossimTrace traceExec ("ossimPleiadesDimapSupportData:exec");
52 static ossimTrace traceDebug ("ossimPleiadesDimapSupportData:debug");
53 
54 static std::string getVectorFloat64AsString(std::vector<ossim_float64> in)
55 {
56  std::vector<ossim_float64>::iterator it;
57  std::stringstream strTmp;
58 
59  for ( it=in.begin() ; it < in.end(); it++ )
60  {
61  strTmp << " " << (*it);
62  }
63 
64  return strTmp.str();
65 }
66 
67 static std::string getVectorDoubleAsString(std::vector<double> in)
68 {
69  std::vector<double>::iterator it;
70  std::stringstream strTmp;
71 
72  for ( it=in.begin() ; it < in.end(); it++ )
73  {
74  strTmp << " " << (*it);
75  }
76 
77  return strTmp.str();
78 }
79 
80 static std::string getVectorStringAsString(std::vector<ossimString> in)
81 {
82  std::vector<ossimString>::iterator it;
83  std::stringstream strTmp;
84 
85  for ( it=in.begin() ; it < in.end(); it++ )
86  {
87  strTmp << " " << (*it);
88  }
89 
90  return strTmp.str();
91 }
92 
93 
94 
95 namespace ossimplugins
96 {
97 
98  static bool readOneXmlNode(ossimRefPtr<ossimXmlDocument> xmlDocument,
99  ossimString xpath,
100  ossimString& nodeValue)
101  {
102  vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
103 
104  xmlDocument->findNodes(xpath, xml_nodes);
105  if (xml_nodes.size() == 0)
106  {
107  if(traceDebug())
108  {
109  ossimNotify(ossimNotifyLevel_DEBUG) << " DEBUG:"
110  << "\nCould not find: " << xpath << std::endl;
111  }
112  return false;
113  }
114  if (xml_nodes.size() != 1)
115  {
116  if(traceDebug())
117  {
118  ossimNotify(ossimNotifyLevel_DEBUG) << " DEBUG:"
119  << "\nMore than one node value with " << xpath << std::endl;
120  }
121  return false;
122  }
123  nodeValue = xml_nodes[0]->getText();
124  return true;
125  }
126 
129  theDIMAPVersion(OSSIM_PLEIADES_UNKNOWN),
130  theMetadataSubProfile(OSSIM_PLEIADES_METADATA_SUBPROFILE_UNKNOWN),
131  theProductIsOk(false),
132  theRpcIsOk(false),
133  theXmlDocumentRoot(),
134 
135  theSensorID(),
136  theImageID(),
137  theProductionDate(),
138  theAcquisitionDate(),
139  theInstrument(),
140  theInstrumentIndex(),
141  theProcessingLevelString(),
142  theSpectralProcessingString(),
143 
144  theSunAzimuth(),
145  theSunElevation(),
146  theIncidenceAngle(),
147  theViewingAngle(),
148  theAzimuthAngle(),
149  theAlongTrackIncidenceAngle(),
150  theAcrossTrackIncidenceAngle(),
151 
152  theImageSize(0, 0),
153  theTileSize(0, 0),
154  theNumberOfMegaTilesInRow(0),
155  theNumberOfMegaTilesInCol(0),
156  theNumberOfMegaTiles(0),
157  theMultiDataFile(),
158 
159  theNumBands(0),
160  theBandOrder(),
161 
162  thePhysicalBias(),
163  thePhysicalGain(),
164  theSolarIrradiance(),
165 
166  theUlCorner(),
167  theUrCorner(),
168  theLrCorner(),
169  theLlCorner(),
170 
171  theSpecId(),
172  theErrBias(0),
173  theErrBiasX(0),
174  theErrBiasY(0),
175  theErrRand(0),
176  theLineOffset(0),
177  theSampOffset(0),
178  theLatOffset(0),
179  theLonOffset(0),
180  theHeightOffset(0),
181  theLineScale(0),
182  theSampScale(0),
183  theLatScale(0),
184  theLonScale(0),
185  theHeightScale(0),
186  theLineNumCoeff(),
187  theLineDenCoeff(),
188  theSampNumCoeff(),
189  theSampDenCoeff(),
190 
191  theTimeRangeStart(),
192  theTimeRangeEnd(),
193  theLinePeriod(0.0),
194  theSwathFirstCol(0),
195  theSwathLastCol(0),
196 
197  theRefGroundPoint(0.0, 0.0, 0.0),
198  theRefImagePoint(0.0, 0.0)
199  {
200  }
201 
203  {
204  }
205 
206 
208  {
212  theProductIsOk = false;
213  theRpcIsOk = false;
214  theXmlDocumentRoot = "";
215  theImageID = "";
216  theSensorID="";
217  theProductionDate = "";
218  theAcquisitionDate = "";
219  theInstrument = "";
220  theInstrumentIndex = "";
223 
224  theSunAzimuth.clear();
225  theSunElevation.clear();
226  theIncidenceAngle.clear();
227  theViewingAngle.clear();
228  theAzimuthAngle.clear();
229 
232 
238  ossimString msg = "";
239  theMultiDataFile.setBooleanValue(false, msg);
240 
241  theNumBands = 0;
242  theBandOrder.clear();
243 
244  thePhysicalBias.clear();
245  thePhysicalGain.clear();
246  theSolarIrradiance.clear();
247 
248  //---
249  // Corner points:
250  //---
255 
258 
259  //---
260  // RPC model parameters
261  //---
262  theErrBias = 0.0;
263  theErrBiasX = 0.0;
264  theErrBiasY = 0.0;
265  theErrRand = 0.0;
266  theLineOffset = 0.0;
267  theSampOffset = 0.0;
268  theLatOffset = 0.0;
269  theLonOffset = 0.0;
270  theHeightOffset = 0.0;
271  theLineScale = 0.0;
272  theSampScale = 0.0;
273  theLatScale = 0.0;
274  theLonScale = 0.0;
275  theHeightScale = 0.0;
276  theLineNumCoeff.clear();
277  theLineDenCoeff.clear();
278  theSampNumCoeff.clear();
279  theSampDenCoeff.clear();
280  theSpecId = "";
281 
282  theTimeRangeStart = "";
283  theTimeRangeEnd = "";
284  theLinePeriod = 0.0;
285  theSwathFirstCol = 0;
286  theSwathLastCol = 0;
287  }
288 
290  {
291 
292  os << "\n----------------- Info on Pleiades Image -------------------"
293  << "\n "
294  << "\n Job Number (ID): " << theImageID
295  << "\n Acquisition Date: " << theAcquisitionDate
296  << "\n Instrument: " << theInstrument
297  << "\n Instrument Index: " << theInstrumentIndex
298  << "\n Production Date: " << theProductionDate
299  << "\n Processing Level: " << theProcessingLevelString
300  << "\n Spectral Processing: " << theSpectralProcessingString
301 
302  << "\n Number of Bands: " << theNumBands
303  << "\n Bands Display Order: " << getVectorStringAsString(theBandOrder)
304 
305  << "\n Image Size: " << theImageSize
306  << "\n Tile Size: " << theTileSize
307  << "\n Number Of Tiles (Row, Col): " << theNumberOfMegaTiles << " ("
308  << theNumberOfMegaTilesInRow << ", "
309  << theNumberOfMegaTilesInCol << ")"
310 
311  << "\n Incidence Angle (TopCenter, Center, BottomCenter): " << getVectorFloat64AsString(theIncidenceAngle)
312  << "\n Viewing Angle (TopCenter, Center, BottomCenter): " << getVectorFloat64AsString(theViewingAngle)
313  << "\n Azimuth Angle (TopCenter, Center, BottomCenter): " << getVectorFloat64AsString(theAzimuthAngle)
314  << "\n Along track incidence angle (TopCenter, Center, BottomCenter): " << getVectorFloat64AsString(theAlongTrackIncidenceAngle)
315  << "\n Across track incidence angle (TopCenter, Center, BottomCenter): " << getVectorFloat64AsString(theAcrossTrackIncidenceAngle)
316  << "\n Sun Azimuth (TopCenter, Center, BottomCenter): " << getVectorFloat64AsString(theSunAzimuth)
317  << "\n Sun Elevation (TopCenter, Center, BottomCenter): " << getVectorFloat64AsString(theSunElevation)
318 
319  << "\n Physical Bias (for each band): " << getVectorFloat64AsString(thePhysicalBias)
320  << "\n Physical Gain (for each band): " << getVectorFloat64AsString(thePhysicalGain)
321  << "\n Solar Irradiance (for each band): " << getVectorFloat64AsString(theSolarIrradiance)
322 
323  << "\n Geo Center Point: " << theRefGroundPoint
324  // TODO add RefImagePoint if necessary
325 
326  << "\n Corner Points:"
327  << "\n UL: " << theUlCorner
328  << "\n UR: " << theUrCorner
329  << "\n LR: " << theLrCorner
330  << "\n LL: " << theLlCorner
331  << "\n"
332 
333  << "\n RPC model parameters:"
334  << "\n RPC ID: " << theSpecId
335  << "\n SampNumCoeff: " << getVectorDoubleAsString(theSampNumCoeff)
336  << "\n SampDenCoeff: " << getVectorDoubleAsString(theSampDenCoeff)
337  << "\n LineNumCoeff: " << getVectorDoubleAsString(theLineNumCoeff)
338  << "\n LineDenCoeff: " << getVectorDoubleAsString(theLineDenCoeff)
339  << "\n LonScale: " << theLonScale
340  << "\n LonOffset: " << theLonOffset
341  << "\n LatScale: " << theLatScale
342  << "\n LonScale: " << theLonScale
343  << "\n HeightScale: " << theHeightScale
344  << "\n HeightOffset: " << theHeightOffset
345  << "\n SampScale: " << theSampScale
346  << "\n SampOffset: " << theSampOffset
347  << "\n LineScale: " << theLineScale
348  << "\n LineOffset: " << theLineOffset
349  << "\n theErrBias: " << theErrBias
350  << "\n theErrBiasX: " << theErrBiasX
351  << "\n theErrBiasY: " << theErrBiasY
352  << "\n theErrRand: " << theErrRand
353  << "\n"
354 
355  << "\n Acquisition time parameters (only valid for SENSOR product):"
356  << "\n TimeRangeStart: "<< theTimeRangeStart
357  << "\n TimeRangeEnd: "<< theTimeRangeEnd
358  << "\n LinePeriod: "<< theLinePeriod
359  << "\n SwathFirstCol: "<< theSwathFirstCol
360  << "\n SwathLastCol: "<< theSwathLastCol
361  << "\n"
362  << "\n---------------------------------------------------------"
363  << "\n " << std::endl;
364  }
365 
367  {
368  static const char MODULE[] = "ossimPleiadesDimapSupportData::parseXmlFile";
369  //traceDebug.setTraceFlag(true);
370 
371  if(traceDebug())
372  {
373  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nFile: " << file << std::endl;
374  }
375 
376  if (allMetadataRead())
377  clearFields();
378 
379  //---
380  // Instantiate the file reading:
381  //---
382  ossim_int64 fileSize = file.fileSize();
383  std::ifstream in(file.c_str(), std::ios::binary|std::ios::in);
384  std::vector<char> fullBuffer;
385  ossimString bufferedIo;
386  if(in.good()&&(fileSize > 0))
387  {
388  char buf[100];
389  fullBuffer.resize(fileSize);
390  in.read(buf, std::min((ossim_int64)100, fileSize));
391  if(!in.fail())
392  {
393  ossimString testString = ossimString(buf,
394  buf + in.gcount());
395  if(testString.contains("xml"))
396  {
397  in.seekg(0);
398  in.read(&fullBuffer.front(), (std::streamsize)fullBuffer.size());
399  if(!in.fail())
400  {
401  bufferedIo = ossimString(fullBuffer.begin(),
402  fullBuffer.begin()+in.gcount());
403  }
404  }
405  }
406  }
407  else
408  {
409  return false;
410  }
411  //---
412  // Instantiate the XML parser:
413  //---
414  ossimRefPtr<ossimXmlDocument> xmlDocument;
415 
416  if(bufferedIo.empty())
417  {
418  xmlDocument = new ossimXmlDocument(file);
419  }
420  else
421  {
422  xmlDocument = new ossimXmlDocument;
423  std::istringstream inStringStream(bufferedIo.string());
424  if(!xmlDocument->read(inStringStream))
425  {
426  return false;
427  }
428  }
429  if (xmlDocument->getErrorStatus())
430  {
431  if(traceDebug())
432  {
434  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
435  << "\nUnable to parse xml file" << std::endl;
436  }
437  setErrorStatus();
438  return false;
439  }
440 
441  if (!parseMetadataIdentificationDIMAPv2(xmlDocument)
442  && !parseMetadataIdentificationDIMAPv1(xmlDocument))
443  {
444  if (traceDebug())
445  {
447  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
448  << "\nparseMetadataIdentification failed. Returning false"
449  << std::endl;
450  }
451  return false;
452  }
453 
456  {
457  if (theProductIsOk)
458  clearFields();
459 
460  if (!parseDatasetIdentification(xmlDocument))
461  {
462  if (traceDebug())
463  {
465  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
466  << "\nparseDatasetdentification failed. Returning false" << std::endl;
467  }
468  return false;
469  }
470 
471  if (!parseDatasetContent(xmlDocument))
472  {
474  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
475  << "\nparseDatasetContent failed. Returning false" << std::endl;
476  return false;
477  }
478 
479  if (!parseProductInformation(xmlDocument))
480  {
481  if (traceDebug())
482  {
484  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
485  << "\nparseProductInformation failed. Returning false" << std::endl;
486  }
487  return false;
488  }
489 
490  if (!parseCoordinateReferenceSystem(xmlDocument))
491  {
492  if (traceDebug())
493  {
495  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
496  << "\nparseCoordinateReferenceSystem failed. Returning false" << std::endl;
497  }
498  return false;
499  }
500 
501  if (!parseGeoposition(xmlDocument))
502  {
503  if (traceDebug())
504  {
506  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
507  << "\nparseGeoposition failed. Returning false" << std::endl;
508  }
509  return false;
510  }
511 
512  if (!parseProcessingInformation(xmlDocument))
513  {
514  if (traceDebug())
515  {
517  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
518  << "\nparseProcessingInformation failed. Returning false" << std::endl;
519  }
520  return false;
521  }
522 
523  if (!parseRasterData(xmlDocument))
524  {
525  if (traceDebug())
526  {
528  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
529  << "\nparseRasterData failed. Returning false" << std::endl;
530  }
531  return false;
532  }
533 
534  if (!parseRadiometricData(xmlDocument))
535  {
537  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
538  << "\nparseRadiometricData failed. Returning false" << std::endl;
539  return false;
540  }
541 
542  if (!parseGeometricData(xmlDocument))
543  {
545  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
546  << "\nparseGeometricData failed. Returning false" << std::endl;
547  return false;
548  }
549 
550  if (!parseQualityAssessment(xmlDocument))
551  {
553  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
554  << "\nparseQualityAssessment failed. Returning false" << std::endl;
555  return false;
556  }
557 
558  if (!parseDatasetSources(xmlDocument))
559  {
561  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
562  << "\nparseDatasetSources failed. Returning false" << std::endl;
563  return false;
564  }
565 
566  theProductIsOk = true;
567  }
568 
571  {
572  // Parse RPC file
573  if (theProcessingLevelString == "SENSOR")
574  {
575  if (parseRPCMetadata(xmlDocument) == false)
576  {
578  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
579  << "\nparseRPCMetadata initialization failed. Returning false" << std::endl;
580  return false;
581  }
582  theRpcIsOk = true;
583  }
584  else
585  theRpcIsOk = true;
586  }
587 
588  if (theProcessingLevelString != "SENSOR")
589  theRpcIsOk = true;
590 
591  if (traceDebug() && allMetadataRead())
592  {
594  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: exited..." << std::endl;
595  }
596 
597  return true;
598  }
599 
601  {
603  }
604 
606  {
607  return theSensorID;
608  }
609 
611  {
612  return theAcquisitionDate;
613  }
614 
616  {
617  return theProductionDate;
618  }
619 
621  {
622  return theImageID;
623  }
624 
626  {
627  return theInstrument;
628  }
629 
631  {
632  return theInstrumentIndex;
633  }
634 
635  void ossimPleiadesDimapSupportData::getSunAzimuth(std::vector<ossim_float64>& az) const
636  {
637  az = theSunAzimuth;
638  }
639 
640  void ossimPleiadesDimapSupportData::getSunElevation(std::vector<ossim_float64>& el) const
641  {
642  el = theSunElevation;
643  }
644 
646  {
647  sz = theImageSize;
648  }
649 
651  {
652  return theNumBands;
653  }
654 
655  void ossimPleiadesDimapSupportData::getIncidenceAngle(std::vector<ossim_float64>& ia) const
656  {
657  ia = theIncidenceAngle;
658  }
659 
660  void ossimPleiadesDimapSupportData::getViewingAngle(std::vector<ossim_float64>& va) const
661  {
662  va = theViewingAngle;
663  }
664 
665  void ossimPleiadesDimapSupportData::getAcrossTrackIncidenceAngle(std::vector<ossim_float64>& act) const
666  {
668  }
669 
670  void ossimPleiadesDimapSupportData::getAlongTrackIncidenceAngle(std::vector<ossim_float64>& alt) const
671  {
673  }
674 
675 
677  {
678  gp = theRefGroundPoint;
679  }
680 
682  {
683  rp = theRefImagePoint;
684  }
685 
687  {
688  pt = theUlCorner;
689  }
690 
692  {
693  pt = theUrCorner;
694  }
695 
697  {
698  pt = theLrCorner;
699  }
700 
702  {
703  pt = theLlCorner;
704  }
705 
707  {
708  rect = ossimDrect(0.0, 0.0, theImageSize.x-1.0, theImageSize.y-1.0);
709  }
710 
711 
713  const char* prefix)const
714  {
715  ossimString tempString;
716  ossim_uint32 idx = 0;
717 
718  kwl.add(prefix,
720  "ossimPleiadesDimapSupportData",
721  true);
722 
723  tempString = "";
724  for(idx = 0; idx < theSunAzimuth.size(); ++idx)
725  {
726  tempString += (ossimString::toString(theSunAzimuth[idx]) + " ");
727  }
728 
729  kwl.add(prefix,
731  tempString,
732  true);
733 
734  kwl.add(prefix,
735  "number_of_azimuth_angle",
736  static_cast<ossim_uint32>(theSunAzimuth.size()),
737  true);
738 
739  tempString = "";
740  for(idx = 0; idx < theSunElevation.size(); ++idx)
741  {
742  tempString += (ossimString::toString(theSunElevation[idx]) + " ");
743  }
744 
745  kwl.add(prefix,
747  tempString,
748  true);
749 
750  kwl.add(prefix,
751  "number_of_elevation_angle",
752  static_cast<ossim_uint32>(theSunElevation.size()),
753  true);
754 
755  //---
756  // Note: since this is a new keyword, use the point.toString as there is
757  // no backwards compatibility issues.
758  //---
759 
760  kwl.add(prefix,
761  "image_size",
764  true);
765 
766  kwl.add(prefix,
767  "reference_ground_point",
772  true);
773 
774  kwl.add(prefix,
775  "reference_image_point",
778  true);
779 
780  kwl.add(prefix,
782  theNumBands,
783  true);
784 
785  tempString = "";
786  for(idx = 0; idx < theBandOrder.size(); ++idx)
787  {
788  tempString += (theBandOrder[idx] + " ");
789  }
790 
791  kwl.add(prefix,
792  "band_name_list",
793  tempString,
794  true);
795 
796  kwl.add(prefix,
797  "image_id",
798  theImageID,
799  true);
800 
801  kwl.add(prefix,
802  "processing_level",
804  true);
805 
806  kwl.add(prefix,
807  "instrument",
809  true);
810 
811  kwl.add(prefix,
812  "instrument_index",
814  true);
815 
816  kwl.add(prefix,
819  true);
820 
821  kwl.add(prefix,
822  "production_date",
824  true);
825 
826  tempString = "";
827  for(idx = 0; idx < theIncidenceAngle.size(); ++idx)
828  {
829  tempString += (ossimString::toString(theIncidenceAngle[idx]) + " ");
830  }
831 
832  kwl.add(prefix,
833  "incident_angle",
834  tempString,
835  true);
836 
837  kwl.add(prefix,
838  "number_of_incident_angle",
839  static_cast<ossim_uint32>(theIncidenceAngle.size()),
840  true);
841 
842  tempString = "";
843  for(idx = 0; idx < theViewingAngle.size(); ++idx)
844  {
845  tempString += (ossimString::toString(theViewingAngle[idx]) + " ");
846  }
847 
848  kwl.add(prefix,
849  "viewing_angle",
850  tempString,
851  true);
852 
853  kwl.add(prefix,
854  "number_of_viewing_angle",
855  static_cast<ossim_uint32>(theViewingAngle.size()),
856  true);
857 
858  tempString = "";
859  for(idx = 0; idx < theAzimuthAngle.size(); ++idx)
860  {
861  tempString += (ossimString::toString(theAzimuthAngle[idx]) + " ");
862  }
863 
864  kwl.add(prefix,
865  "scene_orientation",
866  tempString,
867  true);
868 
869  kwl.add(prefix,
870  "number_of_scene_orientation",
871  static_cast<ossim_uint32>(theAzimuthAngle.size()),
872  true);
873 
874 
875  tempString = "";
876  for(idx = 0; idx < theAlongTrackIncidenceAngle.size(); ++idx)
877  {
878  tempString += (ossimString::toString(theAlongTrackIncidenceAngle[idx]) + " ");
879  }
880  kwl.add(prefix,
881  "along_track_incidence_angle",
882  tempString,
883  true);
884 
885  kwl.add(prefix,
886  "number_of_along_track_incidence_angle",
887  static_cast<ossim_uint32>(theAlongTrackIncidenceAngle.size()),
888  true);
889 
890 
891  tempString = "";
892  for(idx = 0; idx < theAcrossTrackIncidenceAngle.size(); ++idx)
893  {
894  tempString += (ossimString::toString(theAcrossTrackIncidenceAngle[idx]) + " ");
895  }
896  kwl.add(prefix,
897  "across_track_incidence_angle",
898  tempString,
899  true);
900 
901  kwl.add(prefix,
902  "number_of_across_track_incidence_angle",
903  static_cast<ossim_uint32>(theAcrossTrackIncidenceAngle.size()),
904  true);
905 
906  kwl.add(prefix,
907  "ul_ground_point",
911  theUlCorner.datum()->code(),
912  true);
913 
914  kwl.add(prefix,
915  "ur_ground_point",
919  theUrCorner.datum()->code(),
920  true);
921 
922  kwl.add(prefix,
923  "lr_ground_point",
927  theLrCorner.datum()->code(),
928  true);
929 
930  kwl.add(prefix,
931  "ll_ground_point",
935  theLlCorner.datum()->code(),
936  true);
937 
938  kwl.add(prefix,
939  "sensorID",
940  theSensorID,
941  true);
942 
943 
944  tempString = "";
945  for(idx = 0; idx < thePhysicalBias.size(); ++idx)
946  {
947  tempString += (ossimString::toString(thePhysicalBias[idx]) + " ");
948  }
949  kwl.add(prefix,
950  "physical_bias",
951  tempString,
952  true);
953 
954  tempString = "";
955  for(idx = 0; idx < thePhysicalGain.size(); ++idx)
956  {
957  tempString += (ossimString::toString(thePhysicalGain[idx]) + " ");
958  }
959  kwl.add(prefix,
960  "physical_gain",
961  tempString,
962  true);
963 
964  tempString = "";
965  for(idx = 0; idx < theSolarIrradiance.size(); ++idx)
966  {
967  tempString += (ossimString::toString(theSolarIrradiance[idx]) + " ");
968  }
969 
970  kwl.add(prefix,
971  "solar_irradiance",
972  tempString,
973  true);
974 
975  // Some geometric parameters exist only in the case of a SENSOR image
976  if (theProcessingLevelString == "SENSOR")
977  {
978  kwl.add(prefix,
979  "time_range_start",
981  true);
982 
983  kwl.add(prefix,
984  "time_range_end",
986  true);
987 
988  kwl.add(prefix,
989  "line_period",
991  true);
992 
993  kwl.add(prefix,
994  "swath_first_col",
996  true);
997  kwl.add(prefix,
998  "swath_last_col",
1000  true);
1001  }
1002 
1003  return true;
1004  }
1005 
1007  const char* prefix)
1008  {
1009  ossim_uint32 idx = 0;
1010  ossim_uint32 total;
1011  ossimString tempString;
1012 
1013  clearFields();
1014 
1015 
1016  ossimString type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
1017 
1018  if(type != "ossimPleiadesDimapSupportData")
1019  {
1020  return false;
1021  }
1022 
1023  total = ossimString(kwl.find(prefix,"number_of_azimuth_angle")).toUInt32();
1024  theSunAzimuth.resize(total);
1025  tempString = kwl.find(prefix,ossimKeywordNames::AZIMUTH_ANGLE_KW);
1026  if(tempString != "")
1027  {
1028  std::istringstream in(tempString.string());
1029  ossimString tempValue;
1030  for(idx = 0; idx < theSunAzimuth.size();++idx)
1031  {
1032  in >> tempValue.string();
1033  theSunAzimuth[idx] = tempValue.toDouble();
1034  }
1035  }
1036 
1037  total = ossimString(kwl.find(prefix,"number_of_elevation_angle")).toUInt32();
1038  theSunElevation.resize(total);
1039  tempString = kwl.find(prefix,ossimKeywordNames::ELEVATION_ANGLE_KW);
1040  if(tempString != "")
1041  {
1042  std::istringstream in(tempString.string());
1043  ossimString tempValue;
1044  for(idx = 0; idx < theSunElevation.size();++idx)
1045  {
1046  in >> tempValue.string();
1047  theSunElevation[idx] = tempValue.toDouble();
1048  }
1049  }
1050 
1051  // const char* lookup;
1052 
1053  theImageSize = createIpt(kwl.find(prefix, "image_size"));
1054  theRefGroundPoint = createGround(kwl.find(prefix, "reference_ground_point"));
1055  theRefImagePoint = createDpt(kwl.find(prefix, "reference_image_point"));
1056 
1058 
1059  theBandOrder.resize(theNumBands);
1060  tempString = kwl.find(prefix,"band_name_list");
1061  if(tempString != "")
1062  {
1063  std::istringstream in(tempString.string());
1064  ossimString tempValue;
1065  for(idx = 0; idx < theBandOrder.size();++idx)
1066  {
1067  in >> tempValue.string();
1068  theBandOrder[idx] = tempValue;
1069  }
1070  }
1071 
1073  theProductionDate = kwl.find(prefix, "production_date");
1074  theImageID = kwl.find(prefix, "image_id");
1075  theInstrument = kwl.find(prefix, "instrument");
1076  theInstrumentIndex = kwl.find(prefix, "instrument_index");
1077 
1078  total = ossimString(kwl.find(prefix,"number_of_incident_angle")).toUInt32();
1079  theIncidenceAngle.resize(total);
1080  tempString = kwl.find(prefix,"incident_angle");
1081  if(tempString != "")
1082  {
1083  std::istringstream in(tempString.string());
1084  ossimString tempValue;
1085  for(idx = 0; idx < theIncidenceAngle.size();++idx)
1086  {
1087  in >> tempValue.string();
1088  theIncidenceAngle[idx] = tempValue.toDouble();
1089  }
1090  }
1091 
1092  total = ossimString(kwl.find(prefix,"number_of_viewing_angle")).toUInt32();
1093  theViewingAngle.resize(total);
1094  tempString = kwl.find(prefix,"viewing_angle");
1095  if(tempString != "")
1096  {
1097  std::istringstream in(tempString.string());
1098  ossimString tempValue;
1099  for(idx = 0; idx < theViewingAngle.size();++idx)
1100  {
1101  in >> tempValue.string();
1102  theViewingAngle[idx] = tempValue.toDouble();
1103  }
1104  }
1105 
1106  total = ossimString(kwl.find(prefix,"number_of_scene_orientation")).toUInt32();
1107  theAzimuthAngle.resize(total);
1108  tempString = kwl.find(prefix,"scene_orientation");
1109  if(tempString != "")
1110  {
1111  std::istringstream in(tempString.string());
1112  ossimString tempValue;
1113  for(idx = 0; idx < theAzimuthAngle.size();++idx)
1114  {
1115  in >> tempValue.string();
1116  theAzimuthAngle[idx] = tempValue.toDouble();
1117  }
1118  }
1119 
1120  total = ossimString(kwl.find(prefix,"number_of_along_track_incidence_angle")).toUInt32();
1121  theAlongTrackIncidenceAngle.resize(total);
1122  tempString = kwl.find(prefix,"along_track_incidence_angle");
1123  if(tempString != "")
1124  {
1125  std::istringstream in(tempString.string());
1126  ossimString tempValue;
1127  for(idx = 0; idx < theAlongTrackIncidenceAngle.size();++idx)
1128  {
1129  in >> tempValue.string();
1130  theAlongTrackIncidenceAngle[idx] = tempValue.toDouble();
1131  }
1132  }
1133 
1134  total = ossimString(kwl.find(prefix,"number_of_across_track_incidence_angle")).toUInt32();
1135  theAcrossTrackIncidenceAngle.resize(total);
1136  tempString = kwl.find(prefix,"across_track_incidence_angle");
1137  if(tempString != "")
1138  {
1139  std::istringstream in(tempString.string());
1140  ossimString tempValue;
1141  for(idx = 0; idx < theAcrossTrackIncidenceAngle.size();++idx)
1142  {
1143  in >> tempValue.string();
1144  theAcrossTrackIncidenceAngle[idx] = tempValue.toDouble();
1145  }
1146  }
1147 
1148  theUlCorner =createGround( kwl.find(prefix, "ul_ground_point"));
1149  theUrCorner =createGround( kwl.find(prefix, "ur_ground_point"));
1150  theLrCorner =createGround( kwl.find(prefix, "lr_ground_point"));
1151  theLlCorner =createGround( kwl.find(prefix, "ll_ground_point"));
1152 
1153  theSensorID = ossimString(kwl.find(prefix, "sensorID"));
1154 
1155  theProcessingLevelString = ossimString(kwl.find(prefix, "processing_level"));
1156 
1157  thePhysicalBias.resize(theNumBands);
1158  tempString = kwl.find(prefix,"physical_bias");
1159  if(tempString != "")
1160  {
1161  std::istringstream in(tempString.string());
1162  ossimString tempValue;
1163  for(idx = 0; idx < thePhysicalBias.size();++idx)
1164  {
1165  in >> tempValue.string();
1166  thePhysicalBias[idx] = tempValue.toDouble();
1167  }
1168  }
1169 
1170  thePhysicalGain.resize(theNumBands);
1171  tempString = kwl.find(prefix,"physical_gain");
1172  if(tempString != "")
1173  {
1174  std::istringstream in(tempString.string());
1175  ossimString tempValue;
1176  for(idx = 0; idx < thePhysicalGain.size();++idx)
1177  {
1178  in >> tempValue.string();
1179  thePhysicalGain[idx] = tempValue.toDouble();
1180  }
1181  }
1182 
1184  tempString = kwl.find(prefix,"solar_irradiance");
1185  if(tempString != "")
1186  {
1187  std::istringstream in(tempString.string());
1188  ossimString tempValue;
1189  for(idx = 0; idx < theSolarIrradiance.size();++idx)
1190  {
1191  in >> tempValue.string();
1192  theSolarIrradiance[idx] = tempValue.toDouble();
1193  }
1194  }
1195 
1196  // Some geometric parameters exist only in the case of a SENSOR image
1197  if (theProcessingLevelString == "SENSOR")
1198  {
1199  theTimeRangeStart = ossimString(kwl.find(prefix,"time_range_start"));
1200  theTimeRangeEnd = ossimString(kwl.find(prefix,"time_range_end"));
1201  theLinePeriod = ossimString(kwl.find(prefix,"line_period")).toDouble();
1202  theSwathFirstCol = ossimString(kwl.find(prefix,"swath_first_col")).toInt32();
1203  theSwathLastCol = ossimString(kwl.find(prefix,"swath_last_col")).toInt32();
1204  }
1205 
1206  return true;
1207  }
1208 
1210  {
1211  std::istringstream in(s.string());
1212  ossimString lat, lon, height;
1213  ossimString code;
1214 
1215  in >> lat.string() >> lon.string() >> height.string() >> code.string();
1216 
1217  return ossimGpt(lat.toDouble(),
1218  lon.toDouble(),
1219  height.toDouble(),
1221 
1222  }
1223 
1225  {
1226  std::istringstream in(s.string());
1227  ossimString x, y;
1228  ossimString code;
1229 
1230  in >> x.string() >> y.string();
1231 
1232  return ossimDpt(x.toDouble(), y.toDouble());
1233 
1234  }
1235 
1237  {
1238  std::istringstream in(s.string());
1239  ossimString x, y;
1240  ossimString code;
1241 
1242  in >> x.string() >> y.string();
1243 
1244  return ossimIpt(x.toInt(), y.toInt());
1245 
1246  }
1247 
1249  ossimRefPtr<ossimXmlDocument> xmlDocument)
1250  {
1251  ossimString xpath;
1252  vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
1253 
1254  //---
1255  // Fetch the Image ID:
1256  //---
1258  {
1259  xpath = "/Production/JOB_ID";
1260  }
1261  else
1262  {
1263  xpath = "/Product_Information/Delivery_Identification/JOB_ID";
1264  }
1265  xpath = theXmlDocumentRoot + xpath;
1266  if (!readOneXmlNode(xmlDocument, xpath, theImageID))
1267  {
1268  return false;
1269  }
1270 
1271  //---
1272  // Fetch the ProductionDate:
1273  //---
1275  {
1276  xpath = "/Production/DATASET_PRODUCTION_DATE";
1277  }
1278  else
1279  {
1280  xpath = "/Product_Information/Delivery_Identification/PRODUCTION_DATE";
1281  }
1282  xpath = theXmlDocumentRoot + xpath;
1283  if (!readOneXmlNode(xmlDocument, xpath, theProductionDate))
1284  {
1285  return false;
1286  }
1287 
1288  return true;
1289  }
1290 
1292  ossimRefPtr<ossimXmlDocument> xmlDocument)
1293  {
1294  ossimString xpath, nodeValue;
1295  vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
1296 
1297  //---
1298  // Corner points:
1299  //---
1300  xml_nodes.clear();
1302  {
1303  xpath = "/Product_Frame/Dataset_Frame/Vertex";
1304  }
1305  else
1306  {
1307  xpath = "/Dataset_Content/Dataset_Extent/Vertex";
1308  }
1309 
1310  xpath = theXmlDocumentRoot + xpath;
1311  xmlDocument->findNodes(xpath, xml_nodes);
1312  if (xml_nodes.size() != 4)
1313  {
1314  setErrorStatus();
1315  return false;
1316  }
1317  std::vector<ossimRefPtr<ossimXmlNode> >::iterator node = xml_nodes.begin();
1318  while (node != xml_nodes.end())
1319  {
1320  ossimGpt gpt;
1321  ossimDpt ipt;
1322 
1323  std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
1324  xpath = "LAT";
1325  (*node)->findChildNodes(xpath, sub_nodes);
1326  if (sub_nodes.size() == 0)
1327  {
1328  setErrorStatus();
1329  return false;
1330  }
1331  gpt.lat = sub_nodes[0]->getText().toDouble();
1332 
1333  sub_nodes.clear();
1334  xpath = "LON";
1335  (*node)->findChildNodes(xpath, sub_nodes);
1336  if (sub_nodes.size() == 0)
1337  {
1338  setErrorStatus();
1339  return false;
1340  }
1341  gpt.lon = sub_nodes[0]->getText().toDouble();
1342  gpt.hgt = 0.0; // assumed
1343 
1344  sub_nodes.clear();
1345  xpath = "ROW";
1346  (*node)->findChildNodes(xpath, sub_nodes);
1347  if (sub_nodes.size() == 0)
1348  {
1349  setErrorStatus();
1350  return false;
1351  }
1352  ipt.line = sub_nodes[0]->getText().toDouble() - 1.0;
1353 
1354  sub_nodes.clear();
1355  xpath = "COL";
1356  (*node)->findChildNodes(xpath, sub_nodes);
1357  if (sub_nodes.size() == 0)
1358  {
1359  setErrorStatus();
1360  return false;
1361  }
1362  ipt.samp = sub_nodes[0]->getText().toDouble() - 1.0;
1363 
1364  if (ipt.line < 1.0)
1365  if (ipt.samp < 1.0)
1366  theUlCorner = gpt;
1367  else
1368  theUrCorner = gpt;
1369  else
1370  if (ipt.samp < 1.0)
1371  theLlCorner = gpt;
1372  else
1373  theLrCorner = gpt;
1374 
1375  ++node;
1376  }
1377 
1378 
1379 
1380  //---
1381  // Center of frame.
1382  //---
1383  theRefGroundPoint.hgt = 0.0; // TODO needs to be looked up
1384 
1385  if (!readOneXmlNode(xmlDocument,
1386  theXmlDocumentRoot + "/Product_Frame/Dataset_Frame/Center/LON", // DIMAPv1
1387  nodeValue))
1388  {
1389  if (!readOneXmlNode(xmlDocument,
1390  theXmlDocumentRoot + "/Dataset_Content/Dataset_Extent/Center/LON", // DIMAPv2
1391  nodeValue))
1392  {
1393  return false;
1394  }
1395  }
1396  theRefGroundPoint.lon = nodeValue.toDouble();
1397 
1398  if (!readOneXmlNode(xmlDocument, theXmlDocumentRoot + "/Dataset_Content/Dataset_Extent/Center/LAT", nodeValue))
1399  {
1400  if (!readOneXmlNode(xmlDocument, theXmlDocumentRoot + "/Product_Frame/Dataset_Frame/Center/LAT", nodeValue))
1401  {
1402  return false;
1403  }
1404  }
1405  theRefGroundPoint.lat = nodeValue.toDouble();
1406 
1407  return true;
1408  }
1409 
1411  ossimRefPtr<ossimXmlDocument> xmlDocument)
1412  {
1413  ossimString xpath;
1414  std::vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
1415  std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
1416  std::vector<ossimRefPtr<ossimXmlNode> >::iterator node;
1417 
1418  //---
1419  // Fetch the gain and bias for each spectral band:
1420  //---
1421  thePhysicalGain.assign(theNumBands, 1.000);
1422  thePhysicalBias.assign(theNumBands, 0.000);
1423 
1424  xml_nodes.clear();
1426  {
1427  xpath = "/Image_Interpretation/Spectral_Band_Info";
1428  }
1429  else
1430  {
1431  xpath = "/Radiometric_Data/Radiometric_Calibration/Instrument_Calibration/Band_Measurement_List/Band_Radiance";
1432  }
1433  xpath = theXmlDocumentRoot + xpath;
1434  xmlDocument->findNodes(xpath, xml_nodes);
1435 
1436  node = xml_nodes.begin();
1437  while (node != xml_nodes.end())
1438  {
1439  sub_nodes.clear();
1440  xpath = "BAND_ID";
1441  (*node)->findChildNodes(xpath, sub_nodes);
1442  if (sub_nodes.size() == 0)
1443  {
1444  setErrorStatus();
1445  return false;
1446  }
1447 
1448  ossimString bandName = sub_nodes[0]->getText();
1449  ossim_uint32 bandIndex = 99999; // Bogus index...
1450  if ( (bandName == "B0") || (bandName == "P") ||
1451  (bandName == "PA") || (theNumBands == 1) )
1452  {
1453  bandIndex = 0;
1454  }
1455  else if ( (bandName == "B1") && (theNumBands > 1) )
1456  {
1457  bandIndex = 1;
1458  }
1459  else if ( (bandName == "B2") && (theNumBands > 2) )
1460  {
1461  bandIndex = 2;
1462  }
1463  else if ( (bandName == "B3") && (theNumBands > 3) )
1464  {
1465  bandIndex = 3;
1466  }
1467  else
1468  {
1470  << "ossimPleiadesDimapSupportData::parseRadiometricMetadata ERROR: Band ID is incorrect\n";
1471  }
1472 
1473  if (bandIndex >= theNumBands )
1474  {
1476  << "ossimPleiadesDimapSupportData::parseRadiometricMetadata ERROR: Band index outside of range\n";
1477  return false;
1478  }
1479 
1480  sub_nodes.clear();
1481  xpath = (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1 ? "PHYSICAL_BIAS" : "BIAS");
1482  (*node)->findChildNodes(xpath, sub_nodes);
1483  if (sub_nodes.size() == 0)
1484  {
1485  setErrorStatus();
1486  return false;
1487  }
1488  thePhysicalBias[bandIndex] = sub_nodes[0]->getText().toDouble();
1489 
1490  sub_nodes.clear();
1491  xpath = (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1 ? "PHYSICAL_GAIN" : "GAIN");
1492  (*node)->findChildNodes(xpath, sub_nodes);
1493  if (sub_nodes.size() == 0)
1494  {
1495  setErrorStatus();
1496  return false;
1497  }
1498  thePhysicalGain[bandIndex] = sub_nodes[0]->getText().toDouble();
1499 
1500  ++node;
1501  }
1502 
1503  // Initialize to 999 : we find this value in some DIMAPv2 file
1504  // and there is no such tag in DIMAPv1 file
1505  theSolarIrradiance.assign(theNumBands, 999.000);
1506 
1507  xml_nodes.clear();
1508  xpath = "/Radiometric_Data/Radiometric_Calibration/Instrument_Calibration/Band_Measurement_List/Band_Solar_Irradiance";
1509  xpath = theXmlDocumentRoot + xpath;
1510  xmlDocument->findNodes(xpath, xml_nodes);
1511 
1512  node = xml_nodes.begin();
1513  while (node != xml_nodes.end())
1514  {
1515  sub_nodes.clear();
1516  xpath = "BAND_ID";
1517  (*node)->findChildNodes(xpath, sub_nodes);
1518  if (sub_nodes.size() == 0)
1519  {
1520  setErrorStatus();
1521  return false;
1522  }
1523 
1524  ossimString bandName = sub_nodes[0]->getText();
1525  ossim_uint32 bandIndex = 99999; // Bogus index...
1526  if ( (bandName == "B0") || (bandName == "P") ||
1527  (bandName == "PA") || (theNumBands == 1) )
1528  {
1529  bandIndex = 0;
1530  }
1531  else if ( (bandName == "B1") && (theNumBands > 1) )
1532  {
1533  bandIndex = 1;
1534  }
1535  else if ( (bandName == "B2") && (theNumBands > 2) )
1536  {
1537  bandIndex = 2;
1538  }
1539  else if ( (bandName == "B3") && (theNumBands > 3) )
1540  {
1541  bandIndex = 3;
1542  }
1543  else
1544  {
1546  << "ossimPleiadesDimapSupportData::parseRadiometricMetadata ERROR: Band ID is incorrect\n";
1547  }
1548 
1549  if ((bandIndex >= theNumBands))
1550  {
1552  << "ossimPleiadesDimapSupportData::parseRadiometricMetadata ERROR: Band index outside of range 2\n";
1553  return false;
1554  }
1555 
1556  sub_nodes.clear();
1557  xpath = "VALUE";
1558  (*node)->findChildNodes(xpath, sub_nodes);
1559  if (sub_nodes.size() == 0)
1560  {
1561  setErrorStatus();
1562  return false;
1563  }
1564  theSolarIrradiance[bandIndex] = sub_nodes[0]->getText().toDouble();
1565 
1566  ++node;
1567  }
1568 
1569  return true;
1570  }
1571 
1573  ossimRefPtr<ossimXmlDocument> xmlDocument)
1574  {
1575  static const char MODULE[] = "ossimPleiadesDimapSupportData::parseRPCMetadata";
1576  ossimString xpath, nodeValue;
1577  vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
1578 
1579  //---
1580  // Fetch the Global RFM - Direct Model - Bias:
1581  //---
1582 
1583  // RESOURCE_ID does not exists in DIMAPv1 file
1585  {
1586  xpath = "/Rational_Function_Model/Resource_Reference/RESOURCE_ID";
1587  xpath = theXmlDocumentRoot + xpath;
1588  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
1589  {
1590  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: Could not find: " << xpath << std::endl;
1591  return false;
1592  }
1593  theSpecId = nodeValue;
1594  }
1595 
1596  //---
1597  // Fetch the Global RFM - Inverse Model:
1598  //---
1599  xml_nodes.clear();
1601  {
1602  xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/Inverse_Model";
1603  }
1604  else
1605  {
1606  xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model";
1607  }
1608  xpath = theXmlDocumentRoot + xpath;
1609  xmlDocument->findNodes(xpath, xml_nodes);
1610  if (xml_nodes.empty())
1611  {
1612  setErrorStatus();
1613  if(traceDebug())
1614  {
1615  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: Could not find: " << xpath << std::endl;
1616  }
1617  return false;
1618  }
1619 
1621  {
1622  std::vector<ossimString> coeffs;
1623 
1624  xml_nodes.clear();
1625  xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/Inverse_Model/F_ROW";
1626  xpath = theXmlDocumentRoot + xpath;
1627  xmlDocument->findNodes(xpath, xml_nodes);
1628  coeffs = xml_nodes[0]->getText().split(" ", true);
1629 
1630  const size_t nRow = coeffs.size() / 2;
1631  for (size_t i = 0; i < nRow; i++)
1632  {
1633  theLineNumCoeff.push_back(coeffs[i].toDouble());
1634  theLineDenCoeff.push_back(coeffs[i + nRow].toDouble());
1635  }
1636 
1637  xml_nodes.clear();
1638  xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/Inverse_Model/F_COL";
1639  xpath = theXmlDocumentRoot + xpath;
1640  xmlDocument->findNodes(xpath, xml_nodes);
1641  coeffs = xml_nodes[0]->getText().split(" ", true);
1642 
1643  const size_t nCol = coeffs.size() / 2;
1644  for (size_t i = 0; i < nCol; i++)
1645  {
1646  theSampNumCoeff.push_back(coeffs[i].toDouble());
1647  theSampDenCoeff.push_back(coeffs[i + nCol].toDouble());
1648  }
1649 
1650  }
1651  else
1652  {
1653  for (ossim_uint32 it = 1; it < 21; it ++)
1654  {
1655  std::ostringstream valueStr;
1656  valueStr << it;
1657 
1658  xml_nodes.clear();
1659  xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/LINE_NUM_COEFF_";
1660  xpath = theXmlDocumentRoot + xpath;
1661  xpath = xpath + valueStr.str();
1662  xmlDocument->findNodes(xpath, xml_nodes);
1663  if (xml_nodes.size() == 0)
1664  {
1665  setErrorStatus();
1666  if(traceDebug())
1667  {
1668  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
1669  }
1670  return false;
1671  }
1672  theLineNumCoeff.push_back(xml_nodes[0]->getText().toDouble());
1673 
1674  xml_nodes.clear();
1675  xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/LINE_DEN_COEFF_";
1676  xpath = theXmlDocumentRoot + xpath;
1677  xpath = xpath + valueStr.str();
1678  xmlDocument->findNodes(xpath, xml_nodes);
1679  if (xml_nodes.size() == 0)
1680  {
1681  setErrorStatus();
1682  if(traceDebug())
1683  {
1684  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
1685  }
1686  return false;
1687  }
1688  theLineDenCoeff.push_back(xml_nodes[0]->getText().toDouble());
1689 
1690  xml_nodes.clear();
1691  xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/SAMP_NUM_COEFF_";
1692  xpath = theXmlDocumentRoot + xpath;
1693  xpath = xpath + valueStr.str();
1694  xmlDocument->findNodes(xpath, xml_nodes);
1695  if (xml_nodes.size() == 0)
1696  {
1697  setErrorStatus();
1698  if(traceDebug())
1699  {
1700  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
1701  }
1702  return false;
1703  }
1704  theSampNumCoeff.push_back(xml_nodes[0]->getText().toDouble());
1705 
1706  xml_nodes.clear();
1707  xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/SAMP_DEN_COEFF_";
1708  xpath = theXmlDocumentRoot + xpath;
1709  xpath = xpath + valueStr.str();
1710  xmlDocument->findNodes(xpath, xml_nodes);
1711  if (xml_nodes.size() == 0)
1712  {
1713  setErrorStatus();
1714  if(traceDebug())
1715  {
1716  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
1717  }
1718  return false;
1719  }
1720  theSampDenCoeff.push_back(xml_nodes[0]->getText().toDouble());
1721  }
1722  }
1723  //---
1724  // Fetch the Global RFM - Inverse Model - Bias:
1725  //---
1727  {
1728  xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/Inverse_Model/MODEL_PRECISION_ROW";
1729  }
1730  else
1731  {
1732  xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/ERR_BIAS_ROW";
1733  }
1734  xpath = theXmlDocumentRoot + xpath;
1735  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
1736  {
1737  return false;
1738  }
1739  theErrBiasX = nodeValue.toDouble();
1740 
1742  {
1743  xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/Inverse_Model/MODEL_PRECISION_COL";
1744  }
1745  else
1746  {
1747  xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/ERR_BIAS_COL";
1748  }
1749  xpath = theXmlDocumentRoot + xpath;
1750  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
1751  {
1752  return false;
1753  }
1754  theErrBiasY = nodeValue.toDouble();
1755 
1756  //---
1757  // Fetch the Global RFM validity parameters :
1758  //---
1760  {
1761  xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Lon/A";
1762  }
1763  else
1764  {
1765  xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LONG_SCALE";
1766  }
1767  xpath = theXmlDocumentRoot + xpath;
1768  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
1769  {
1770  return false;
1771  }
1772  theLonScale = nodeValue.toDouble();
1773 
1775  {
1776  xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Lon/B";
1777  }
1778  else
1779  {
1780  xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LONG_OFF";
1781  }
1782  xpath = theXmlDocumentRoot + xpath;
1783  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
1784  {
1785  return false;
1786  }
1787  theLonOffset = nodeValue.toDouble();
1788 
1790  {
1791  xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Lat/A";
1792  }
1793  else
1794  {
1795  xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LAT_SCALE";
1796  }
1797  xpath = theXmlDocumentRoot + xpath;
1798  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
1799  {
1800  return false;
1801  }
1802  theLatScale = nodeValue.toDouble();
1803 
1805  {
1806  xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Lat/B";
1807  }
1808  else
1809  {
1810  xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LAT_OFF";
1811  }
1812  xpath = theXmlDocumentRoot + xpath;
1813  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
1814  {
1815  return false;
1816  }
1817  theLatOffset = nodeValue.toDouble();
1818 
1820  {
1821  xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Alt/A";
1822  }
1823  else
1824  {
1825  xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/HEIGHT_SCALE";
1826  }
1827  xpath = theXmlDocumentRoot + xpath;
1828  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
1829  {
1830  return false;
1831  }
1832  theHeightScale = nodeValue.toDouble();
1833 
1835  {
1836  xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Alt/B";
1837  }
1838  else
1839  {
1840  xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/HEIGHT_OFF";
1841  }
1842  xpath = theXmlDocumentRoot + xpath;
1843  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
1844  {
1845  return false;
1846  }
1847  theHeightOffset = nodeValue.toDouble();
1848 
1850  {
1851  xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Col/A";
1852  }
1853  else
1854  {
1855  xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/SAMP_SCALE";
1856  }
1857  xpath = theXmlDocumentRoot + xpath;
1858  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
1859  {
1860  return false;
1861  }
1862  theSampScale = nodeValue.toDouble();
1863 
1865  {
1866  xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Col/B";
1867  }
1868  else
1869  {
1870  xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/SAMP_OFF";
1871  }
1872  xpath = theXmlDocumentRoot + xpath;
1873  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
1874  {
1875  return false;
1876  }
1877  // Pleiades metadata assume that the coordinate of the center of
1878  // the upper-left pixel is (1,1), so we remove 1 to get back to
1879  // OSSIM convention.
1880  theSampOffset = nodeValue.toDouble()-1;
1881 
1883  {
1884  xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Row/A";
1885  }
1886  else
1887  {
1888  xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LINE_SCALE";
1889  }
1890  xpath = theXmlDocumentRoot + xpath;
1891  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
1892  {
1893  return false;
1894  }
1895  theLineScale = nodeValue.toDouble();
1896 
1898  {
1899  xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Row/B";
1900  }
1901  else
1902  {
1903  xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LINE_OFF";
1904  }
1905  xpath = theXmlDocumentRoot + xpath;
1906  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
1907  {
1908  return false;
1909  }
1910  // Pleiades metadata assume that the coordinate of the center of
1911  // the upper-left pixel is (1,1), so we remove 1 to get back to
1912  // OSSIM convention.
1913  theLineOffset = nodeValue.toDouble()-1;
1914 
1915  return true;
1916  }
1917 
1919  {
1920  // static const char MODULE[] = "ossimPleiadesDimapSupportData::parseMetadataIdentification";
1921 
1922  vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
1923  ossimString xpath, nodeValue;
1924  theXmlDocumentRoot = "/PHR_Dimap_Document";
1925 
1926  //---
1927  // Get the version string which can be used as a key for parsing.
1928  //---
1929  xml_nodes.clear();
1930  xpath = "/Metadata_Identification/METADATA_FORMAT";
1931  xpath = theXmlDocumentRoot + xpath;
1932 
1933  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
1934  {
1935  return false;
1936  }
1937  if (nodeValue != "DIMAP_PHR")
1938  {
1939  return false;
1940  }
1941 
1942  //---
1943  // Check that it is a valid PHR DIMAPv2 file
1944  //---
1945  xpath = "/Metadata_Identification/METADATA_PROFILE";
1946  xpath = theXmlDocumentRoot + xpath;
1947  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
1948  {
1949  return false;
1950  }
1951 
1952  ossimString metadataProfile;
1953  if ( nodeValue != "PHR_SYSTEM_RECTIFIED_PRODUCT" )
1954  {
1955  if (traceDebug())
1956  {
1958  << "DEBUG:\n Not a PLEIADES DIMAPv1 file: METADATA_PROFILE is incorrect!" << std::endl;
1959  }
1960  return false;
1961  }
1962 
1963  // DIMAPv1 -> no subprofile
1965 
1967 
1968  return true;
1969  }
1971  {
1972  // static const char MODULE[] = "ossimPleiadesDimapSupportData::parseMetadataIdentification";
1973 
1974  vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
1975  ossimString xpath, nodeValue;
1976  theXmlDocumentRoot = "/DIMAP_Document";
1977 
1978  //---
1979  // Get the version string which can be used as a key for parsing.
1980  //---
1981  xml_nodes.clear();
1982  xpath = "/Metadata_Identification/METADATA_FORMAT";
1983  xpath = theXmlDocumentRoot + xpath;
1984  xmlDocument->findNodes(xpath, xml_nodes);
1985  if (xml_nodes.size() == 0)
1986  {
1987  // FIXME MSD: used to support Pleiades samples from SPOT-IMAGES website which are not coherent
1988  // with the specification (28/09/2012). Should be remove when first data will be available and sample
1989  // replaced.
1990  theXmlDocumentRoot = "/PHR_DIMAP_Document";
1991  if (traceDebug())
1992  {
1993  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nTry to use the old root: " << theXmlDocumentRoot << endl;
1994  }
1995 
1996  xml_nodes.clear();
1997  xpath = "/Metadata_Identification/METADATA_FORMAT";
1998  xpath = theXmlDocumentRoot + xpath;
1999  xmlDocument->findNodes(xpath, xml_nodes);
2000  if (xml_nodes.size() == 0)
2001  {
2002  // FIXME MSD: used to support peiades samples from SPOT-IMAGES website which are not coherent
2003  // with the specification (28/09/2012). Should be remove when first data will be available and sample
2004  // replaced.
2005  theXmlDocumentRoot = "/Dimap_Document";
2006  if (traceDebug())
2007  {
2008  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nTry to use the new root: " << theXmlDocumentRoot << endl;
2009  }
2010 
2011  xml_nodes.clear();
2012  xpath = "/Metadata_Identification/METADATA_FORMAT";
2013  xpath = theXmlDocumentRoot + xpath;
2014  xmlDocument->findNodes(xpath, xml_nodes);
2015  if (xml_nodes.size() == 0)
2016  {
2017  setErrorStatus();
2018  if (traceDebug())
2019  {
2020  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << endl;
2021  }
2022  return false;
2023  }
2024  }
2025  }
2026 
2027  ossimString attribute = "version";
2028  ossimString value;
2029  xml_nodes[0]->getAttributeValue(value, attribute);
2030  if (value != "2.0")
2031  {
2032  setErrorStatus();
2033  if (traceDebug())
2034  {
2036  << "WARNING: DIMAP metadata version is not correct!" << std::endl;
2037  }
2038  return false;
2039  }
2040 
2041  //---
2042  // Check that it is a valid PHR DIMAPv2 file
2043  //---
2044  xpath = "/Metadata_Identification/METADATA_PROFILE";
2045  xpath = theXmlDocumentRoot + xpath;
2046  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
2047  {
2048  return false;
2049  }
2050 
2051  ossimString metadataProfile;
2052  if ( (nodeValue != "PHR_SENSOR")
2053  && (nodeValue != "PHR_ORTHO")
2054  && (nodeValue != "PHR_MOSAIC") )
2055  {
2056  if (traceDebug())
2057  {
2059  << "DEBUG:\n Not a PLEIADES DIMAPv2 file: metadata profile is incorrect!" << std::endl;
2060  }
2061  return false;
2062  }
2063  else
2064  metadataProfile = nodeValue;
2065 
2066  //---
2067  // Get the subprofile
2068  //---
2069  xpath = "/Metadata_Identification/METADATA_SUBPROFILE";
2070  xpath = theXmlDocumentRoot + xpath;
2071  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
2072  {
2073  return false;
2074  }
2075 
2076  if ((nodeValue == "PRODUCT"))
2078  else if ( (nodeValue == "RPC") && (metadataProfile == "PHR_SENSOR") )
2080  else
2081  {
2083  if (traceDebug())
2084  {
2086  << "DEBUG:\n Not a PLEIADES DIMAPv2 file: metadata subprofile is incorrect !" << std::endl;
2087  }
2088  return false;
2089  }
2090 
2092 
2093  return true;
2094  }
2095 
2097  {
2098  return true;
2099  }
2100 
2102  {
2103  return true;
2104  }
2105 
2107  {
2108  return true;
2109  }
2110 
2112  {
2113  // static const char MODULE[] = "ossimPleiadesDimapSupportData::parseProcessingInformation";
2114 
2115  vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
2116  ossimString xpath, nodeValue;
2117 
2118  //---
2119  // Fetch the Processing Level:
2120  //---
2122  {
2123  xpath = "/Product_Characteristics/PROCESSING_LEVEL";
2124  }
2125  else
2126  {
2127  xpath = "/Processing_Information/Product_Settings/PROCESSING_LEVEL";
2128  }
2129  xpath = theXmlDocumentRoot + xpath;
2130  if (!readOneXmlNode(xmlDocument, xpath, theProcessingLevelString))
2131  {
2132  return false;
2133  }
2134 
2135  //---
2136  // Fetch the Spectral Processing:
2137  //---
2139  {
2140  xpath = "/Product_Characteristics/Product_Image_Characteristics/SPECTRAL_PROCESSING";
2141  }
2142  else
2143  {
2144  xpath = "/Processing_Information/Product_Settings/SPECTRAL_PROCESSING";
2145  }
2146  xpath = theXmlDocumentRoot + xpath;
2147  if (!readOneXmlNode(xmlDocument, xpath, theSpectralProcessingString))
2148  {
2149  return false;
2150  }
2151 
2152  return true;
2153  }
2154 
2156  {
2157  static const char MODULE[] = "ossimPleiadesDimapSupportData::parseRasterData";
2158  vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
2159  ossimString xpath, nodeValue;
2160  //---
2161  // Fetch if the product file is linked to one or many JP2 files:
2162  //---
2164  {
2165  xpath = "/Product_Characteristics/Product_Image_Characteristics/Data_Access/Data_File/DATA_FILE_PATH";
2166  xpath = theXmlDocumentRoot + xpath;
2167  xmlDocument->findNodes(xpath, xml_nodes);
2168 
2169  if (xml_nodes.size() > 1)
2170  {
2171  theMultiDataFile.setValue(true);
2172  }
2173  }
2174  else
2175  {
2176  xpath = "/Raster_Data/Data_Access/DATA_FILE_TILES";
2177  xpath = theXmlDocumentRoot + xpath;
2178  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
2179  {
2180  return false;
2181  }
2182  theMultiDataFile.setValue(nodeValue);
2183  }
2184 
2185  //---
2186  // Fetch the MegaImageSize:
2187  //---
2189  {
2190  xpath = "/Raster_Dimensions/NCOLS";
2191  }
2192  else
2193  {
2194  xpath = "/Raster_Data/Raster_Dimensions/NCOLS";
2195  }
2196  xpath = theXmlDocumentRoot + xpath;
2197  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
2198  {
2199  return false;
2200  }
2201  theImageSize.samp = nodeValue.toInt();
2202 
2204  {
2205  xpath = "/Raster_Dimensions/NROWS";
2206  }
2207  else
2208  {
2209  xpath = "/Raster_Data/Raster_Dimensions/NROWS";
2210  }
2211  xpath = theXmlDocumentRoot + xpath;
2212  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
2213  {
2214  return false;
2215  }
2216  theImageSize.line = nodeValue.toInt();
2217 
2219  {
2220  //---
2221  // Fetch the Number of MegaTiles:
2222  //---
2224  {
2225  xpath = "/Raster_Dimensions/Raster_Tiles/NTILES";
2226  }
2227  else
2228  {
2229  xpath = "/Raster_Data/Raster_Dimensions/Tile_Set/NTILES";
2230  }
2231  xpath = theXmlDocumentRoot + xpath;
2232  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
2233  {
2234  return false;
2235  }
2236  theNumberOfMegaTiles = nodeValue.toUInt32();
2237 
2238  //---
2239  // Fetch the Number of MegaTiles in X and Y:
2240  //---
2242  {
2243  xpath = "/Raster_Dimensions/Raster_Tiles/RX_NB_OF_TILES";
2244  xpath = theXmlDocumentRoot + xpath;
2245  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
2246  {
2247  return false;
2248  }
2249  theNumberOfMegaTilesInRow = nodeValue.toUInt32();
2250 
2251  xpath = "/Raster_Dimensions/Raster_Tiles/CY_NB_OF_TILES";
2252  xpath = theXmlDocumentRoot + xpath;
2253  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
2254  {
2255  return false;
2256  }
2257  theNumberOfMegaTilesInCol = nodeValue.toUInt32();
2258  }
2259  else
2260  {
2261  xml_nodes.clear();
2262  xpath = "/Raster_Data/Raster_Dimensions/Tile_Set/Regular_Tiling/NTILES_COUNT";
2263  xpath = theXmlDocumentRoot + xpath;
2264  xmlDocument->findNodes(xpath, xml_nodes);
2265  if (xml_nodes.size() == 0)
2266  {
2267  setErrorStatus();
2268  if (traceDebug())
2269  {
2270  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: \nCould not find: " << xpath << std::endl;
2271  }
2272  return false;
2273  }
2274 
2275  ossimString value;
2276  ossimString attribute = "ntiles_x";
2277  if (!xml_nodes[0]->getAttributeValue(value, attribute))
2278  {
2279  attribute = "ntiles_R";
2280  xml_nodes[0]->getAttributeValue(value, attribute);
2281  }
2283 
2284  attribute = "ntiles_y";
2285  if (!xml_nodes[0]->getAttributeValue(value, attribute))
2286  {
2287  attribute = "ntiles_C";
2288  xml_nodes[0]->getAttributeValue(value, attribute);
2289  }
2291  }
2292 
2294  {
2295  setErrorStatus();
2296  if (traceDebug())
2297  {
2298  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: \nIncoherent number of tiles: " << xpath << std::endl;
2299  }
2300  return false;
2301  }
2302 
2304  {
2305  //---
2306  // Fetch the size of MegaTiles:
2307  //---
2308  xml_nodes.clear();
2309  xpath = "/Raster_Data/Raster_Dimensions/Tile_Set/Regular_Tiling/NTILES_SIZE";
2310  xpath = theXmlDocumentRoot + xpath;
2311  xmlDocument->findNodes(xpath, xml_nodes);
2312  if (xml_nodes.size() == 0)
2313  {
2314  setErrorStatus();
2315  if (traceDebug())
2316  {
2317  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
2318  }
2319  return false;
2320  }
2321 
2322  ossimString attribute;
2323  ossimString value;
2324 
2325  attribute = "nrows";
2326  xml_nodes[0]->getAttributeValue(value, attribute);
2327  theTileSize.line = value.toUInt32();
2328 
2329  attribute = "ncols";
2330  xml_nodes[0]->getAttributeValue(value, attribute);
2331  theTileSize.samp = value.toUInt32();
2332  }
2333 
2334  }
2335 
2336  //--- TODO_MSD is it useful in the case of RPC model ???
2337  // We will make the RefImagePoint the zero base center of the image. This
2338  // is used by the ossimSensorModel::worldToLineSample iterative loop as
2339  // the starting point. Since the ossimSensorModel does not know of the
2340  // sub image we make it zero base. (comments from spot)
2341  //---
2344 
2345  //---
2346  // Fetch number of bands
2347  //---
2348 
2350  {
2351  xpath = "/Raster_Dimensions/NBANDS";
2352  }
2353  else
2354  {
2355  xpath = "/Raster_Data/Raster_Dimensions/NBANDS";
2356  }
2357  xpath = theXmlDocumentRoot + xpath;
2358  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
2359  {
2360  return false;
2361  }
2362  theNumBands = nodeValue.toUInt32();
2363 
2364  if (traceDebug())
2365  {
2366  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nNumber of bands: " << theNumBands << std::endl;
2367  }
2368 
2369  //---
2370  // Fetch Band Display Order
2371  //---
2372  xml_nodes.clear();
2374  {
2375  xpath = "/Product_Characteristics/Product_Image_Characteristics/Image_Display_Order/RED_CHANNEL";
2376  }
2377  else
2378  {
2379  xpath = "/Raster_Data/Raster_Display/Band_Display_Order/RED_CHANNEL";
2380  }
2381  xpath = theXmlDocumentRoot + xpath;
2382  xmlDocument->findNodes(xpath, xml_nodes);
2383  if (xml_nodes.size() == 0)
2384  {
2385  setErrorStatus();
2386  if (traceDebug())
2387  {
2388  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
2389  }
2390  return false;
2391  }
2392  theBandOrder.push_back(xml_nodes[0]->getText());
2393 
2394  if (theNumBands > 1)
2395  {
2396  xml_nodes.clear();
2398  {
2399  xpath = "/Product_Characteristics/Product_Image_Characteristics/Image_Display_Order/GREEN_CHANNEL";
2400  }
2401  else
2402  {
2403  xpath = "/Raster_Data/Raster_Display/Band_Display_Order/GREEN_CHANNEL";
2404  }
2405  xpath = theXmlDocumentRoot + xpath;
2406  xmlDocument->findNodes(xpath, xml_nodes);
2407  if (xml_nodes.size() == 0)
2408  {
2409  setErrorStatus();
2410  if (traceDebug())
2411  {
2412  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
2413  }
2414  return false;
2415  }
2416  theBandOrder.push_back(xml_nodes[0]->getText());
2417 
2418  xml_nodes.clear();
2420  {
2421  xpath = "/Product_Characteristics/Product_Image_Characteristics/Image_Display_Order/BLUE_CHANNEL";
2422  }
2423  else
2424  {
2425  xpath = "/Raster_Data/Raster_Display/Band_Display_Order/BLUE_CHANNEL";
2426  }
2427  xpath = theXmlDocumentRoot + xpath;
2428  xmlDocument->findNodes(xpath, xml_nodes);
2429  if (xml_nodes.size() == 0)
2430  {
2431  setErrorStatus();
2432  if (traceDebug())
2433  {
2434  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
2435  }
2436  return false;
2437  }
2438  theBandOrder.push_back(xml_nodes[0]->getText());
2439 
2440  if (theNumBands > 3)
2441  {
2442  xml_nodes.clear();
2444  {
2445  xpath = "/Product_Characteristics/Product_Image_Characteristics/Image_Display_Order/ALPHA_CHANNEL";
2446  }
2447  else
2448  {
2449  xpath = "/Raster_Data/Raster_Display/Band_Display_Order/ALPHA_CHANNEL";
2450  }
2451  xpath = theXmlDocumentRoot + xpath;
2452  xmlDocument->findNodes(xpath, xml_nodes);
2453  if (xml_nodes.size() == 0)
2454  {
2455  setErrorStatus();
2456  if (traceDebug())
2457  {
2458  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
2459  }
2460  return false;
2461  }
2462 
2463  theBandOrder.push_back(xml_nodes[0]->getText());
2464  }
2465  }
2466 
2467  return true;
2468  }
2469 
2471  {
2472  ossimString xpath, nodeValue;
2473  vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
2474 
2475  xml_nodes.clear();
2477  {
2478  xpath = "/Data_Strip/Geometric_Header_List/Located_Geometric_Header";
2479  }
2480  else
2481  {
2482  xpath = "/Geometric_Data/Use_Area/Located_Geometric_Values";
2483  }
2484  xpath = theXmlDocumentRoot + xpath;
2485  xmlDocument->findNodes(xpath, xml_nodes);
2486  if (xml_nodes.size() != 3 )
2487  {
2488  setErrorStatus();
2489  if(traceDebug())
2490  {
2491  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
2492  }
2493  return false;
2494  }
2495 
2496  std::vector<ossimRefPtr<ossimXmlNode> >::iterator node = xml_nodes.begin();
2497  while (node != xml_nodes.end())
2498  {
2499  std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
2500 
2501  //---
2502  // Fetch the Sun Azimuth:
2503  //---
2504  xpath = "Solar_Incidences/SUN_AZIMUTH";
2505  (*node)->findChildNodes(xpath, sub_nodes);
2506  if (sub_nodes.size() == 0)
2507  {
2508  setErrorStatus();
2509  if(traceDebug())
2510  {
2511  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
2512  }
2513  return false;
2514  }
2515  theSunAzimuth.push_back(sub_nodes[0]->getText().toDouble());
2516 
2517  //---
2518  // Fetch the Sun Elevation:
2519  //---
2520  sub_nodes.clear();
2521  xpath = "Solar_Incidences/SUN_ELEVATION";
2522  (*node)->findChildNodes(xpath, sub_nodes);
2523  if (sub_nodes.size() == 0)
2524  {
2525  setErrorStatus();
2526  if(traceDebug())
2527  {
2528  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
2529  }
2530  return false;
2531  }
2532  theSunElevation.push_back(sub_nodes[0]->getText().toDouble());
2533 
2534  //---
2535  // Fetch the Incidence Angle:
2536  //---
2537  sub_nodes.clear();
2538 
2540  {
2541  xpath = "Incidences/GLOBAL_INCIDENCE";
2542  }
2543  else
2544  {
2545  xpath = "Acquisition_Angles/INCIDENCE_ANGLE";
2546  }
2547  (*node)->findChildNodes(xpath, sub_nodes);
2548  if (sub_nodes.size() == 0)
2549  {
2550  setErrorStatus();
2551  if(traceDebug())
2552  {
2553  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
2554  }
2555  return false;
2556  }
2557  theIncidenceAngle.push_back(sub_nodes[0]->getText().toDouble());
2558 
2559  //---
2560  // Fetch the Viewing Angle:
2561  //---
2562  sub_nodes.clear();
2564  {
2565  xpath = "Pointing_Angles/PSI_XY";
2566  }
2567  else
2568  {
2569  xpath = "Acquisition_Angles/VIEWING_ANGLE";
2570  }
2571  (*node)->findChildNodes(xpath, sub_nodes);
2572  if (sub_nodes.size() == 0)
2573  {
2574  setErrorStatus();
2575  if(traceDebug())
2576  {
2577  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
2578  }
2579  return false;
2580  }
2581  theViewingAngle.push_back(sub_nodes[0]->getText().toDouble());
2582 
2583  //---
2584  // Fetch the Azimuth Angle:
2585  //---
2586  sub_nodes.clear();
2588  {
2589  xpath = "ORIENTATION";
2590  }
2591  else
2592  {
2593  xpath = "Acquisition_Angles/AZIMUTH_ANGLE";
2594  }
2595  (*node)->findChildNodes(xpath, sub_nodes);
2596  if (sub_nodes.size() == 0)
2597  {
2598  setErrorStatus();
2599  if(traceDebug())
2600  {
2601  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
2602  }
2603  return false;
2604  }
2605  theAzimuthAngle.push_back(sub_nodes[0]->getText().toDouble());
2606 
2607  //---
2608  // Fetch the along track incidence angle :
2609  //---
2610  sub_nodes.clear();
2612  {
2613  xpath = "Incidences/ALONG_TRACK_INCIDENCE";
2614  }
2615  else
2616  {
2617  xpath = "Acquisition_Angles/INCIDENCE_ANGLE_ALONG_TRACK";
2618  }
2619  (*node)->findChildNodes(xpath, sub_nodes);
2620  if (sub_nodes.size() == 0)
2621  {
2622  setErrorStatus();
2623  if(traceDebug())
2624  {
2625  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
2626  }
2627  return false;
2628  }
2629  theAlongTrackIncidenceAngle.push_back(sub_nodes[0]->getText().toDouble());
2630 
2631  //---
2632  // Fetch the across track incidence angle :
2633  //---
2634  sub_nodes.clear();
2636  {
2637  xpath = "Incidences/ORTHO_TRACK_INCIDENCE";
2638  }
2639  else
2640  {
2641  xpath = "Acquisition_Angles/INCIDENCE_ANGLE_ACROSS_TRACK";
2642  }
2643  (*node)->findChildNodes(xpath, sub_nodes);
2644  if (sub_nodes.size() == 0)
2645  {
2646  setErrorStatus();
2647  if(traceDebug())
2648  {
2649  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
2650  }
2651  return false;
2652  }
2653  theAcrossTrackIncidenceAngle.push_back(sub_nodes[0]->getText().toDouble());
2654 
2655  ++node;
2656  }
2657 
2658  if (theProcessingLevelString == "SENSOR")
2659  {
2660  // check that this product is SENSOR (some tags are not present in ORTHO)
2661  //---
2662  // Fetch the time stamp of the first line:
2663  //---
2665  {
2666  xpath = "/Geometric_Data/Sensor_Model_Characteristics/UTC_Sensor_Model_Range/START";
2667  }
2668  else
2669  {
2670  xpath = "/Geometric_Data/Refined_Model/Time/Time_Range/START";
2671  }
2672  xpath = theXmlDocumentRoot + xpath;
2673  if (!readOneXmlNode(xmlDocument, xpath, theTimeRangeStart))
2674  {
2675  return false;
2676  }
2677 
2678  //---
2679  // Fetch the time stamp of the last line:
2680  //---
2682  {
2683  xpath = "/Geometric_Data/Sensor_Model_Characteristics/UTC_Sensor_Model_Range/END";
2684  }
2685  else
2686  {
2687  xpath = "/Geometric_Data/Refined_Model/Time/Time_Range/END";
2688  }
2689  xpath = theXmlDocumentRoot + xpath;
2690  if (!readOneXmlNode(xmlDocument, xpath, theTimeRangeEnd))
2691  {
2692  return false;
2693  }
2694 
2695  //---
2696  // Fetch the line period:
2697  //---
2699  {
2700  xpath = "/Geometric_Data/Sensor_Model_Characteristics/SENSOR_LINE_PERIOD";
2701  }
2702  else
2703  {
2704  xpath = "/Geometric_Data/Refined_Model/Time/Time_Stamp/LINE_PERIOD";
2705  }
2706  xpath = theXmlDocumentRoot + xpath;
2707  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
2708  {
2709  return false;
2710  }
2711  theLinePeriod = nodeValue.toDouble();
2712 
2713  //---
2714  // Fetch the swath first col:
2715  //---
2717  {
2718  xpath = "/Geometric_Data/Sensor_Model_Characteristics/Sensor_Viewing_Model/Position_In_Retina/FIRST_COL";
2719  }
2720  else
2721  {
2722  xpath = "/Geometric_Data/Refined_Model/Geometric_Calibration/Instrument_Calibration/Swath_Range/FIRST_COL";
2723  }
2724  xpath = theXmlDocumentRoot + xpath;
2725  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
2726  {
2727  return false;
2728  }
2729  theSwathFirstCol = nodeValue.toInt32();
2730 
2731  //---
2732  // Fetch the swath last col:
2733  //---
2735  {
2736  xpath = "/Geometric_Data/Sensor_Model_Characteristics/Sensor_Viewing_Model/Position_In_Retina/LAST_COL";
2737  }
2738  else
2739  {
2740  xpath = "/Geometric_Data/Refined_Model/Geometric_Calibration/Instrument_Calibration/Swath_Range/LAST_COL";
2741  }
2742  xpath = theXmlDocumentRoot + xpath;
2743  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
2744  {
2745  return false;
2746  }
2747  theSwathLastCol = nodeValue.toInt32();
2748  }
2749 
2750  return true;
2751  }
2752 
2754  {
2755  return true;
2756  }
2757 
2759  {
2760  // static const char MODULE[] = "ossimPleiadesDimapSupportData::parseDatasetSources";
2761  ossimString xpath, nodeValue;
2762  vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
2763 
2764  //---
2765  // Fetch the mission index (1A ou 1B) ?
2766  // and generate theSensorID
2767  //---
2769  {
2770  xpath = "/Data_Strip/Data_Strip_Identification/PLATFORM_NAME";
2771  }
2772  else
2773  {
2774  xpath = "/Dataset_Sources/Source_Identification/Strip_Source/MISSION";
2775  }
2776  xpath = theXmlDocumentRoot + xpath;
2777  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
2778  {
2779  return false;
2780  }
2781 
2782  if (nodeValue != "PHR")
2783  {
2784  setErrorStatus();
2785  if (traceDebug())
2786  {
2787  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nNot a PHR mission!"<< std::endl;
2788  }
2789  return false;
2790  }
2791 
2792  //---
2793  // Fetch the mission index (1A ou 1B) ?
2794  // and generate theSensorID
2795  //---
2797  {
2798  xpath = "/Data_Strip/Data_Strip_Identification/PLATFORM_SERIAL_NUMBER";
2799  }
2800  else
2801  {
2802  xpath = "/Dataset_Sources/Source_Identification/Strip_Source/MISSION_INDEX";
2803  }
2804  xpath = theXmlDocumentRoot + xpath;
2805  if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
2806  {
2807  return false;
2808  }
2809 
2810  if (nodeValue == "1A")
2811  theSensorID = "PHR 1A";
2812  else if (nodeValue == "1B")
2813  theSensorID = "PHR 1B";
2814  else
2815  {
2816  setErrorStatus();
2817  if (traceDebug())
2818  {
2819  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nNot a valid sensorID!"<< std::endl;
2820  }
2821  return false;
2822  }
2823 
2824  //---
2825  // Fetch the Instrument:
2826  //---
2828  {
2829  xpath = "/Data_Strip/Data_Strip_Identification/PLATFORM_NAME";
2830  }
2831  else
2832  {
2833  xpath = "/Dataset_Sources/Source_Identification/Strip_Source/INSTRUMENT";
2834  }
2835  xpath = theXmlDocumentRoot + xpath;
2836  if (!readOneXmlNode(xmlDocument, xpath, theInstrument))
2837  {
2838  return false;
2839  }
2840 
2841  //---
2842  // Fetch the Instrument Index:
2843  //---
2845  {
2846  xpath = "/Data_Strip/Data_Strip_Identification/PLATFORM_SERIAL_NUMBER";
2847  }
2848  else
2849  {
2850  xpath = "/Dataset_Sources/Source_Identification/Strip_Source/INSTRUMENT_INDEX";
2851  }
2852  xpath = theXmlDocumentRoot + xpath;
2853  if (!readOneXmlNode(xmlDocument, xpath, theInstrumentIndex))
2854  {
2855  return false;
2856  }
2857 
2859  {
2860  //---
2861  // Fetch the Imaging Date:
2862  //---
2863  xpath = "/Data_Strip/UTC_Acquisition_Range/START";
2864  xpath = theXmlDocumentRoot + xpath;
2865  if (!readOneXmlNode(xmlDocument, xpath, theAcquisitionDate))
2866  {
2867  return false;
2868  }
2869 
2870  // TODO : fetch (if any in v1) the other acquisition time parameters
2871 
2872  }
2873  else
2874  {
2875  //---
2876  // Fetch the Imaging Date:
2877  //---
2878  ossimString firstLineImagingDate;
2879  xpath = "/Dataset_Sources/Source_Identification/Strip_Source/IMAGING_DATE";
2880  xpath = theXmlDocumentRoot + xpath;
2881  if (!readOneXmlNode(xmlDocument, xpath, firstLineImagingDate))
2882  {
2883  return false;
2884  }
2885 
2886  //---
2887  // Fetch the Imaging Time:
2888  //---
2889  ossimString firstLineImagingTime;
2890  xpath = "/Dataset_Sources/Source_Identification/Strip_Source/IMAGING_TIME";
2891  xpath = theXmlDocumentRoot + xpath;
2892  if (!readOneXmlNode(xmlDocument, xpath, firstLineImagingTime))
2893  {
2894  return false;
2895  }
2896 
2897  theAcquisitionDate = firstLineImagingDate + "T" + firstLineImagingTime;
2898 
2899  }
2900 
2901  return true;
2902  }
2903 
2904 }
2905 
virtual const ossimDatum * create(const ossimString &code) const
create method
void clear()
Erases the entire container.
Definition: ossimString.h:432
ossim_uint32 x
std::vector< ossim_float64 > thePhysicalBias
Calibration information for radiometric corrections.
virtual bool setValue(const ossimString &value)
void makeNan()
Definition: ossimIpt.h:56
std::basic_ostringstream< char > ostringstream
Class for char output memory streams.
Definition: ossimIosFwd.h:35
std::basic_stringstream< char > stringstream
Class for char mixed input and output memory streams.
Definition: ossimIosFwd.h:38
static const char * IMAGE_DATE_KW
double lond() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:97
Represents serializable keyword/value map.
ossim_uint32 y
std::basic_ifstream< char > ifstream
Class for char input file streams.
Definition: ossimIosFwd.h:44
const char * find(const char *key) const
ossim_int64 fileSize() const
double samp
Definition: ossimDpt.h:164
double y
Definition: ossimDpt.h:165
bool contains(char aChar) const
Definition: ossimString.h:58
virtual const ossimString & code() const
Definition: ossimDatum.h:57
void makeNan()
Definition: ossimGpt.h:130
static ossimString toString(bool aValue)
Numeric to string methods.
ossimDpt theRefImagePoint
Zero based center of frame.
bool parseQualityAssessment(ossimRefPtr< ossimXmlDocument > xmlDocument)
QualityAssessment:
ossim_float64 hgt
Height in meters above the ellipsiod.
Definition: ossimGpt.h:274
ossim_uint32 toUInt32() const
double latd() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:87
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of the object from a keyword list.
void getRefImagePoint(ossimDpt &rp) const
zero base center point
bool parseRadiometricData(ossimRefPtr< ossimXmlDocument > xmlDocument)
static const char * TYPE_KW
const ossimDatum * datum() const
datum().
Definition: ossimGpt.h:196
bool parseProductInformation(ossimRefPtr< ossimXmlDocument > xmlDocument)
Product Information:
ossim_int32 toInt32() const
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
double line
Definition: ossimDpt.h:165
void getViewingAngle(std::vector< ossim_float64 > &va) const
ossim_float64 lon
Definition: ossimGpt.h:266
unsigned int ossim_uint32
double height() const
Definition: ossimGpt.h:107
bool parseMetadataIdentificationDIMAPv1(ossimRefPtr< ossimXmlDocument > xmlDocument)
double toDouble() const
static ossimDatumFactory * instance()
static const char * NUMBER_BANDS_KW
bool parseDatasetIdentification(ossimRefPtr< ossimXmlDocument > xmlDocument)
Dataset Identification:
bool parseRPCMetadata(ossimRefPtr< ossimXmlDocument > xmlDocument)
static const char * AZIMUTH_ANGLE_KW
void getAlongTrackIncidenceAngle(std::vector< ossim_float64 > &alt) const
void getImageRect(ossimDrect &rect) const
Zero based image rectangle, sub image if there is one.
bool setBooleanValue(bool value, ossimString &msg)
bool parseRasterData(ossimRefPtr< ossimXmlDocument > xmlDocument)
bool parseDatasetContent(ossimRefPtr< ossimXmlDocument > xmlDocument)
Dataset Content:
ossim_int32 samp
Definition: ossimIpt.h:141
virtual ossimErrorCode getErrorStatus() const
ossim_int32 y
Definition: ossimIpt.h:142
bool parseCoordinateReferenceSystem(ossimRefPtr< ossimXmlDocument > xmlDocument)
Coordinate Reference System:
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of the object to a keyword list.
double x
Definition: ossimDpt.h:164
void getRefGroundPoint(ossimGpt &gp) const
Center of frame, sub image if there is one.
long long ossim_int64
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
bool empty() const
Definition: ossimString.h:411
ossimGpt theRefGroundPoint
Center of frame on ground, if sub image it&#39;s the center of that.
bool parseGeometricData(ossimRefPtr< ossimXmlDocument > xmlDocument)
bool read(std::istream &in)
ossim_int32 line
Definition: ossimIpt.h:142
ossim_int32 x
Definition: ossimIpt.h:141
ossim_float64 lat
Definition: ossimGpt.h:265
void getSunElevation(std::vector< ossim_float64 > &el) const
void findNodes(const ossimString &xpath, std::vector< ossimRefPtr< ossimXmlNode > > &nodelist) const
Appends any matching nodes to the list supplied (should be empty):
std::basic_istringstream< char > istringstream
Class for char input memory streams.
Definition: ossimIosFwd.h:32
static const char * ELEVATION_ANGLE_KW
bool parseDatasetSources(ossimRefPtr< ossimXmlDocument > xmlDocument)
void getAcrossTrackIncidenceAngle(std::vector< ossim_float64 > &act) const
int toInt() const
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
void makeNan()
Definition: ossimDpt.h:65
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
bool parseMetadataIdentificationDIMAPv2(ossimRefPtr< ossimXmlDocument > xmlDocument)
bool parseProcessingInformation(ossimRefPtr< ossimXmlDocument > xmlDocument)
Processing Information:
void getSunAzimuth(std::vector< ossim_float64 > &az) const
void getIncidenceAngle(std::vector< ossim_float64 > &ia) const
#define min(a, b)
Definition: auxiliary.h:75
bool parseGeoposition(ossimRefPtr< ossimXmlDocument > xmlDocument)
Geoposition:
const std::string & string() const
Definition: ossimString.h:414