OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimFgdcXmlDoc.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // License: LGPL
4 //
5 // See LICENSE.txt file in the top level directory for more details.
6 //
7 // Description: Utility class to encapsulate parsing projection info in the xml file.
8 //
9 //----------------------------------------------------------------------------
10 // $Id: ossimFgdcXmlDoc.cpp 2063 2011-01-19 19:38:12Z ming.su $
11 
13 #include <ossim/base/ossimDatum.h>
15 #include <ossim/base/ossimDrect.h>
17 #include <ossim/base/ossimTrace.h>
24 
25 #include <cmath> /* for std::fabs */
26 
27 // Static trace for debugging
28 static ossimTrace traceDebug("ossimFgdcXmlDoc:debug");
29 
31  : m_xmlFilename(ossimFilename::NIL),
32  m_xmlDocument(0),
33  m_projection(0),
34  m_boundInDegree(false)
35 {
36 }
37 
39 {
40 }
41 
42 bool ossimFgdcXmlDoc::open(const ossimFilename& xmlFileName)
43 {
44  bool result = false;
45  if ( isOpen() )
46  {
47  close();
48  }
49 
50  if (xmlFileName.size())
51  {
52  m_xmlDocument = new ossimXmlDocument(xmlFileName);
53  if ( m_xmlDocument.valid() )
54  {
55  // May want to add a test for valid FGDC here??? (drb)
56  m_xmlFilename = xmlFileName;
57  result = true;
58  }
59  }
60  return result;
61 }
62 
64 {
66  m_xmlDocument = 0;
67  m_projection = 0;
68 }
69 
71 {
72  if ( (m_projection.valid() == false) && isOpen() )
73  {
74  ossimString projName;
75  if ( getProjCsn(projName) )
76  {
77  if (!projName.empty())
78  {
80 
81  if ( m_projection.valid() )
82  {
83  ossimDpt gsd;
84  gsd.makeNan();
85  ossim_float64 d;
86  if ( getXRes(d) )
87  {
88  gsd.x = std::fabs(d);
89  }
90  if ( getYRes(d) )
91  {
92  gsd.y = std::fabs(d);
93  }
94  ossimMapProjection* mapProj = dynamic_cast<ossimMapProjection*>(m_projection.get());
95  if (mapProj)
96  {
97  ossimDrect rect;
98  getBoundingBox(rect);
99  if (mapProj->isGeographic())
100  {
101  ossimGpt tie(rect.ul().lat, rect.ul().lon);
102  mapProj->setUlTiePoints(tie);
103  mapProj->setDecimalDegreesPerPixel(gsd);
104  }
105  else
106  {
107  ossimDpt tie(rect.ul().x, rect.ul().y);
108  ossimUnitType unitType = getUnitType();
109  if ( unitType == OSSIM_US_SURVEY_FEET)
110  {
111  gsd = gsd * US_METERS_PER_FT;
112  tie = tie * US_METERS_PER_FT;
113  }
114  else if ( unitType == OSSIM_FEET )
115  {
116  gsd = gsd * MTRS_PER_FT;
117  tie = tie * MTRS_PER_FT;
118  }
119 
120  mapProj->setUlTiePoints(tie);
121  mapProj->setMetersPerPixel(gsd);
122  }
123  }
124  }
125  }
126  }
127  }
128  return m_projection;
129 }
130 
132 {
133  ossimUnitType result = OSSIM_METERS; // default
134  ossimString units;
135  if ( getPlanarDistantUnits(units) )
136  {
137  units.downcase();
138  if ( units.contains("feet") )
139  {
140  if ( units.contains("international") )
141  {
142  result = OSSIM_FEET;
143  }
144  else
145  {
146  result = OSSIM_US_SURVEY_FEET; // Default for feet.
147  }
148  }
149  }
150  return result;
151 }
152 
154 {
155  return m_xmlDocument.valid();
156 }
157 
159 {
160  ossimString xpath = "/metadata/spref/horizsys/cordsysn/geogcsn";
161  return getPath(xpath, s);
162 }
163 
165 {
166  ossimString xpath = "/metadata/spref/horizsys/cordsysn/projcsn";
167  return getPath(xpath, s);
168 }
169 
171 {
172  ossimString xpath = "/metadata/spref/vertdef/altsys/altunits";
173  return getPath(xpath, s);
174 }
175 
177 {
178  ossimString xpath = "/metadata/spref/horizsys/planar/gridsys/gridsysn";
179  return getPath(xpath, s);
180 }
181 
183 {
184  static const char M[] = "ossimFgdcXmlDoc::getGridCoordSysProjection";
185  if ( traceDebug() )
186  {
187  ossimNotify(ossimNotifyLevel_DEBUG) << M << " entered...\n";
188  }
189 
190  if ( m_projection.valid() == false )
191  {
192  ossimString s;
193  if ( getGridCoordinateSystem(s) )
194  {
195  ossimString gridsysn = s.downcase();
196  if ( getHorizontalDatum(s) )
197  {
198  ossimString horizdn = s.downcase();
199  const ossimDatum* datum = createOssimDatum(s); // throws exception
200 
201  if ( gridsysn == "universal transverse mercator" )
202  {
203  // Get the zone:
204  if ( getUtmZone(s) )
205  {
206  ossim_int32 zone = s.toInt32();
207 
208  //---
209  // Note: Contruct with an origin with our datum.
210  // "proj->setDatum" does not change the origin's datum.
211  // This ensures theossimEpsgProjectionDatabase::findProjectionCode
212  // sets the psc code correctly down the line.
213  //---
215  new ossimUtmProjection( *(datum->ellipsoid()), ossimGpt(0.0,0.0,0.0,datum) );
216  utmProj->setDatum(datum);
217  utmProj->setZone(zone);
218 
219  // Hemisphere( North false easting = 0.0, South = 10000000):
220  bool tmpResult = getUtmFalseNorthing(s);
221  if ( tmpResult && ( s != "0.0" ) )
222  {
223  utmProj->setHemisphere('S');
224  }
225  else
226  {
227  utmProj->setHemisphere('N');
228  }
229  utmProj->setPcsCode(0);
230 
231  ossim_float64 xRes = 0.0;
232  ossim_float64 yRes = 0.0;
233  if (getXRes(xRes) && getYRes(yRes))
234  {
235  ossimDrect rect;
236  getBoundingBox(rect);
237 
238  ossimDpt gsd(std::fabs(xRes), std::fabs(yRes));
239  ossimUnitType unitType = getUnitType();
240 
241  if (m_boundInDegree)
242  {
243  ossimGpt tieg(rect.ul().lat, rect.ul().lon);
244  utmProj->setUlTiePoints(tieg);
245  }
246  else
247  {
248  ossimDpt tie(rect.ul().x, rect.ul().y);
249  if ( unitType == OSSIM_US_SURVEY_FEET)
250  {
251  tie = tie * US_METERS_PER_FT;
252  }
253  else if ( unitType == OSSIM_FEET )
254  {
255  tie = tie * MTRS_PER_FT;
256  }
257  utmProj->setUlTiePoints(tie);
258  }
259 
260  if ( unitType == OSSIM_US_SURVEY_FEET)
261  {
262  gsd = gsd * US_METERS_PER_FT;
263  }
264  else if ( unitType == OSSIM_FEET )
265  {
266  gsd = gsd * MTRS_PER_FT;
267  }
268  utmProj->setMetersPerPixel(gsd);
269  }
270  m_projection = utmProj.get(); // Capture projection.
271  }
272  else
273  {
274  std::string errMsg = M;
275  errMsg += " ERROR: Could not determine utm zone!";
276  throw ossimException(errMsg);
277  }
278  }
279  }
280  }
281  }
282 
283  if ( traceDebug() )
284  {
285  if ( m_projection.valid() )
286  {
288  }
289  ossimNotify(ossimNotifyLevel_DEBUG) << M << " exiting...\n";
290  }
291  return m_projection;
292 }
293 
294 
296 {
297  ossimString xpath = "/metadata/spref/horizsys/geodetic/horizdn";
298  return getPath(xpath, s);
299 }
300 
302 {
303  ossimString xpath = "/metadata/spref/horizsys/planar/planci/plandu";
304  return getPath(xpath, s);
305 }
306 
308 {
309  ossimString xpath = "/metadata/spref/horizsys/planar/gridsys/utm/transmer/fnorth";
310  return getPath(xpath, s);
311 }
312 
314 {
315  ossimString xpath = "/metadata/spref/horizsys/planar/gridsys/utm/utmzone";
316  return getPath(xpath, s);
317 }
318 
320 {
321  ossimString xpath = "/metadata/spdoinfo/rastinfo/rastxsz";
322  if (getPath(xpath, v) == false)
323  {
324  xpath = "/metadata/spref/horizsys/planar/planci/coordrep/absres";
325  }
326  return getPath(xpath, v);
327 }
328 
330 {
331  ossimString xpath = "/metadata/spdoinfo/rastinfo/rastysz";
332  if (getPath(xpath, v) == false)
333  {
334  xpath = "/metadata/spref/horizsys/planar/planci/coordrep/ordres";
335  }
336  return getPath(xpath, v);
337 }
338 
340 {
341  bool result = false;
342  if ( m_xmlDocument.valid() )
343  {
344  ossimString xpath = "/metadata/spatRepInfo/GridSpatRep/axDimProps/Dimen/dimSize";
345  vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
346  m_xmlDocument->findNodes(xpath, xml_nodes);
347  if (xml_nodes.size() > 1)
348  {
349  size.x = xml_nodes[0]->getText().toInt32();
350  size.y = xml_nodes[1]->getText().toInt32();
351  result = true;
352  }
353 
354  if (result == false)
355  {
356  xpath = "/metadata/spdoinfo/rastinfo/colcount";
357  ossim_float64 x = 0.0;
358  result = getPath(xpath, x);
359  if (result)
360  {
361  size.x = (ossim_int32)x;
362  }
363  xpath = "/metadata/spdoinfo/rastinfo/rowcount";
364  ossim_float64 y = 0.0;
365  result = getPath(xpath, y);
366  if (result)
367  {
368  size.y = (ossim_int32)y;
369  }
370  }
371  }
372  return result;
373 }
374 
376 {
377  rect.makeNan();
378 
379  if (isOpen())
380  {
381  double ll_lat = 0.0;
382  double ll_lon = 0.0;
383  double lr_lat = 0.0;
384  double lr_lon = 0.0;
385  double ul_lat = 0.0;
386  double ul_lon = 0.0;
387  double ur_lat = 0.0;
388  double ur_lon = 0.0;
389 
390  ossimString xpath = "/metadata/idinfo/spdom/lboundng/leftbc";
391  bool result = getPath(xpath, ul_lon);
392  if (!result)
393  {
394  xpath = "/metadata/idinfo/spdom/bounding/westbc";
395  result = getPath(xpath, ul_lon);
396  m_boundInDegree = true;
397  }
398  if (result)
399  {
400  ll_lon = ul_lon;
401  }
402 
403  xpath = "/metadata/idinfo/spdom/lboundng/rightbc";
404  result = getPath(xpath, ur_lon);
405  if (!result)
406  {
407  xpath = "/metadata/idinfo/spdom/bounding/eastbc";
408  result = getPath(xpath, ur_lon);
409  m_boundInDegree = true;
410  }
411  if (result)
412  {
413  lr_lon = ur_lon;
414  }
415 
416  xpath = "/metadata/idinfo/spdom/lboundng/bottombc";
417  result = getPath(xpath, ll_lat);
418  if (!result)
419  {
420  xpath = "/metadata/idinfo/spdom/bounding/southbc";
421  result = getPath(xpath, ll_lat);
422  m_boundInDegree = true;
423  }
424  if (result)
425  {
426  lr_lat = ll_lat;
427  }
428 
429  xpath = "/metadata/idinfo/spdom/lboundng/topbc";
430  result = getPath(xpath, ul_lat);
431  if (!result)
432  {
433  xpath = "/metadata/idinfo/spdom/bounding/northbc";
434  result = getPath(xpath, ul_lat);
435  m_boundInDegree = true;
436  }
437  if (result)
438  {
439  ur_lat = ul_lat;
440  }
441 
442  rect = ossimDrect(ossimDpt(ul_lon, ul_lat),
443  ossimDpt(ur_lon, ur_lat),
444  ossimDpt(lr_lon, lr_lat),
445  ossimDpt(ll_lon, ll_lat), OSSIM_RIGHT_HANDED);
446  }
447 }
448 
450 {
451  ossim_uint32 numOfBands = 0;
452  ossimString s;
453  ossimString xpath = "/metadata/spdoinfo/rastinfo/vrtcount";
454  if (getPath(xpath, s))
455  {
456  numOfBands = s.toInt();
457  }
458  return numOfBands;
459 }
460 
462 {
463  static const char M[] = "ossimFgdcXmlDoc::getPath";
464 
465  bool result = false;
466  if ( m_xmlDocument.valid() )
467  {
468  std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
469  m_xmlDocument->findNodes(path, xnodes);
470  if ( xnodes.size() == 1 ) // Error if more than one.
471  {
472  if ( xnodes[0].valid() )
473  {
474  s = xnodes[0]->getText();
475  result = true;
476  }
477  else
478  {
479  if(traceDebug())
480  {
481 
483  << M << " ERROR:\n"
484  << "Node not found: " << path
485  << std::endl;
486  }
487  }
488  }
489  else if ( xnodes.size() == 0 )
490  {
491  if(traceDebug())
492  {
493  ossimNotify(ossimNotifyLevel_WARN) << M << " ERROR:\nNode not found: " << path
494  << std::endl;
495  }
496  }
497  else
498  {
499  if(traceDebug())
500  {
501 
503  << M << " ERROR:\nMultiple nodes found: " << path << std::endl;
504  }
505  }
506  }
507  if (!result)
508  {
509  s.clear();
510  }
511  return result;
512 }
513 
515 {
516  ossimString s;
517  bool result = getPath(path, s);
518  if ( result )
519  {
520  v = s.toFloat64();
521  }
522  return result;
523 }
524 
526 {
527  ossimString horizdn = s.downcase();
528  ossimString datumCode;
529  if ( horizdn == "north american datum of 1983" )
530  {
531  datumCode = "NAR-C";
532  }
533  else if ( horizdn == "north american datum of 1927" )
534  {
535  datumCode = "NAS-C";
536  }
537  else if ( horizdn == "wgs84")
538  {
539  datumCode = "WGE";
540  }
541  else
542  {
543  std::string errMsg = "ossimFgdcXmlDoc::createOssimDatum ERROR: Unhandled datum: ";
544  errMsg += horizdn.string();
545  throw ossimException(errMsg);
546  }
547  return ossimDatumFactoryRegistry::instance()->create(datumCode);
548 }
~ossimFgdcXmlDoc()
destructor
void clear()
Erases the entire container.
Definition: ossimString.h:432
void makeNan()
Definition: ossimDrect.h:388
ossim_uint32 x
ossimRefPtr< ossimProjection > m_projection
bool getAltitudeDistantUnits(ossimString &s) const
Get the Altitude Distance Units.
bool isOpen() const
static const ossimFilename NIL
This was taken from Wx widgets for performing touch and access date stamps.
Definition: ossimFilename.h:40
const ossimDatum * createOssimDatum(const ossimString &s) const
Gets the ossimDatum from string.
ossimUnitType
static ossimDatumFactoryRegistry * instance()
instance method
ossim_uint32 y
bool valid() const
Definition: ossimRefPtr.h:75
virtual std::ostream & print(std::ostream &out) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
ossim_uint32 getNumberOfBands()
Get Bands.
const ossimDpt & ul() const
Definition: ossimDrect.h:339
bool getYRes(ossim_float64 &v) const
double y
Definition: ossimDpt.h:165
bool contains(char aChar) const
Definition: ossimString.h:58
ossimRefPtr< ossimProjection > getGridCoordSysProjection()
Gets projection from Grid Coordinate system node.
bool getPath(const ossimString &path, ossimString &s) const
Gets path from doc and initializes string.
virtual bool isGeographic() const
virtual void setDecimalDegreesPerPixel(const ossimDpt &gsd)
bool getGeoCsn(ossimString &s) const
ossimRefPtr< ossimXmlDocument > m_xmlDocument
bool getProjCsn(ossimString &s) const
virtual void setMetersPerPixel(const ossimDpt &gsd)
ossim_int32 toInt32() const
double ossim_float64
#define US_METERS_PER_FT
bool getUtmFalseNorthing(ossimString &s) const
Get UTM false Northing.
double lat
Definition: ossimDpt.h:165
yy_size_t size
virtual void setPcsCode(ossim_uint32 pcsCode)
std::string::size_type size() const
Definition: ossimString.h:405
unsigned int ossim_uint32
virtual const ossimDatum * create(const ossimString &code) const
create method
virtual const ossimEllipsoid * ellipsoid() const
Definition: ossimDatum.h:60
ossim_float64 toFloat64() const
bool getXRes(ossim_float64 &v) const
bool getImageSize(ossimIpt &size) const
static ossimString downcase(const ossimString &aString)
Definition: ossimString.cpp:48
bool getPlanarDistantUnits(ossimString &s) const
Get the Planar Distant Units.
double lon
Definition: ossimDpt.h:164
void getBoundingBox(ossimDrect &rect) const
ossimFilename m_xmlFilename
void setZone(const ossimGpt &ground)
#define MTRS_PER_FT
ossimRefPtr< ossimProjection > getProjection()
Gets projection from document.
bool getHorizontalDatum(ossimString &s) const
Get the Grid Coordinate system.
double x
Definition: ossimDpt.h:164
bool empty() const
Definition: ossimString.h:411
virtual ossimProjection * createProjection(const ossimFilename &filename, ossim_uint32 entryIdx) const
STUB. Not implemented.
ossimFgdcXmlDoc()
default constructor
bool getUtmZone(ossimString &s) const
Get UTM zone.
virtual void setUlTiePoints(const ossimGpt &gpt)
bool open(const ossimFilename &xmlFileName)
Open method.
void findNodes(const ossimString &xpath, std::vector< ossimRefPtr< ossimXmlNode > > &nodelist) const
Appends any matching nodes to the list supplied (should be empty):
virtual void setDatum(const ossimDatum *datum)
Sets theDatum to datum.
ossimUnitType getUnitType() const
bool getGridCoordinateSystem(ossimString &s) const
Get the Grid Coordinate system.
void setHemisphere(const ossimGpt &ground)
static ossimEpsgProjectionFactory * instance()
Implements singleton pattern.
int toInt() const
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
void makeNan()
Definition: ossimDpt.h:65
int ossim_int32
const std::string & string() const
Definition: ossimString.h:414
void close()
close method.