OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimAuxXmlSupportData.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // License: MIT
4 //
5 // See LICENSE.txt file in the top level directory for more details.
6 //
7 // Author: David Burken
8 //
9 // Description:
10 //
11 // Utility/support data class to extract the projection from a dot aux dot xml
12 // file commonly found with mrsid data.
13 //
14 //----------------------------------------------------------------------------
15 // $Id$
16 
18 #include <ossim/base/ossimDpt.h>
19 #include <ossim/base/ossimGpt.h>
22 #include <ossim/base/ossimNotify.h>
24 #include <ossim/base/ossimString.h>
25 #include <ossim/base/ossimTrace.h>
32 #include <memory>
33 
34 // Static trace for debugging.
35 static const ossimTrace traceDebug( ossimString("ossimAuxXmlSupportData:debug") );
36 
38 {
39 }
40 
42 {
43 }
44 
46 {
48 
49  std::shared_ptr<ossim::istream> is = ossim::StreamFactoryRegistry::instance()->
50  createIstream(file, std::ios_base::in | std::ios_base::binary);
51 
52  if ( is && is->good() )
53  {
54  // Read the xml document:
55  ossimXmlDocument xdoc;
56  if ( xdoc.read( *is ) )
57  {
58  // Get the WKT string
59  ossimString wkt;
60  ossimString path = "/PAMDataset/Metadata/GeodataXform/SpatialReference/WKT";
61  if ( getPath( path, xdoc, wkt ) )
62  {
63  if ( wkt.size() )
64  {
65  // Substitute "&quot;":
66  ossimString tmpWkt = wkt.substitute( ossimString("&quot;"), ossimString(""), true );
67 
68  ossimString name;
69  if ( getProjcsName( tmpWkt.string(), name.string() ) )
70  {
72  if ( result.valid() == false )
73  {
74  // Hack...
75  if ( name.contains("_NAD83_") )
76  {
77  cout << "name1: " << name << endl;
78  name.gsub( ossimString("Georef_NAD83_m"), ossimString("GeoRef_M"), false );
79  name.string() = std::string("NAD_1983_") + name.string();
80  cout << "name2: " << name << endl;
82  createProjection( name );
83  }
84  }
85 
86  if ( result.valid() )
87  {
88  if ( initializeProjection( xdoc, tmpWkt.string(), result.get() ) == false )
89  {
90  // Zero out the result if tie or scale not set.
91  result = 0;
92  }
93  }
94  }
95  }
96  }
97  }
98  }
99 
100  return result;
101 
102 } // End: ossimAuxXmlSupportData::getProjection
103 
105  const std::string& wkt,
106  ossimProjection* proj ) const
107 {
108  bool result = false;
109 
110  ossimRefPtr<ossimMapProjection> mapProj = dynamic_cast<ossimMapProjection*>( proj );
111  if ( mapProj.valid() )
112  {
113  // Find the tie and scale.
114  ossimString path = "/PAMDataset/Metadata/MDI";
115  std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
116  xdoc.findNodes(path, xnodes);
117  if ( xnodes.size() )
118  {
119  ossimDpt tie;
120  ossimDpt scale;
121  tie.makeNan();
122  scale.makeNan();
123 
124  for ( ossim_uint32 i = 0; i < xnodes.size(); ++i )
125  {
126  if ( xnodes[i].valid() )
127  {
128  ossimString value;
129  ossimString attrName = "key";
130 
131  ossimRefPtr<ossimXmlAttribute> attr = xnodes[i]->findAttribute( attrName );
132  if ( attr.valid() )
133  {
134  if (attr->getValue() == "IMAGE__XY_ORIGIN" )
135  {
136  value = xnodes[i]->getText();
137  if ( value.size() )
138  {
139  // Split it:
140  std::vector<ossimString> list;
141  value.split( list, ossimString(","), true );
142  if ( list.size() == 2 )
143  {
144  if ( list[0].size() )
145  {
146  tie.x = list[0].toFloat64();
147  }
148  if ( list[1].size() )
149  {
150  tie.y = list[1].toFloat64();
151  }
152  }
153  }
154  }
155  else if (attr->getValue() == "IMAGE__X_RESOLUTION" )
156  {
157  value = xnodes[i]->getText();
158  if ( value.size() )
159  {
160  scale.x = value.toFloat64();
161  }
162  }
163  else if (attr->getValue() == "IMAGE__Y_RESOLUTION" )
164  {
165  value = xnodes[i]->getText();
166  if ( value.size() )
167  {
168  scale.y = value.toFloat64();
169  }
170  }
171  }
172 
173  } // Matches: if ( xnodes[i].valid() )
174 
175  } // Matches: for ( ossim_uint32 i = 0; i < xnodes.size(); ++i )
176 
177  if ( !tie.hasNans() && !scale.hasNans() )
178  {
179  if ( mapProj->isGeographic() )
180  {
181  // Assuming tie and scale in decimal degrees:
182  mapProj->setDecimalDegreesPerPixel( scale );
183  ossimGpt gpt(tie.y, tie.x, 0.0);
184  mapProj->setUlTiePoints( ossimGpt( gpt ) );
185  result = true;
186  }
187  else
188  {
189  // Get the units:
190  ossimUnitType units = getUnits( wkt );
191 
192  // Convert to meters:
193  result = true;
194  if ( units != OSSIM_METERS )
195  {
196  if ( units == OSSIM_FEET )
197  {
198  tie.x = tie.x * MTRS_PER_FT;
199  tie.y = tie.y * MTRS_PER_FT;
200  scale.x = scale.x * MTRS_PER_FT;
201  scale.y = scale.y * MTRS_PER_FT;
202  }
203  else if ( units == OSSIM_US_SURVEY_FEET)
204  {
205  tie.x = tie.x * US_METERS_PER_FT;
206  tie.y = tie.y * US_METERS_PER_FT;
207  scale.x = scale.x * OSSIM_US_SURVEY_FEET;
208  scale.y = scale.y * OSSIM_US_SURVEY_FEET;
209  }
210  else
211  {
213  << "ossimAuxXmlSupportData::initializeProjection WARNING: "
214  << "Unhandled unit type: " << units << std::endl;
215  result = false;
216  }
217  }
218 
219  if ( result )
220  {
221  mapProj->setMetersPerPixel( scale );
222  mapProj->setUlTiePoints( tie );
223  }
224  }
225  }
226 
227  } // Matches: if ( xnodes.size() )
228  }
229 
230  return result;
231 
232 } // ossimAuxXmlSupportData::initializeProjection
233 
235  const ossimString& path, const ossimXmlDocument& xdoc, ossimString& s) const
236 {
237  bool result = false;
238 
239  std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
240  xdoc.findNodes(path, xnodes);
241  if ( xnodes.size() == 1 ) // Error if more than one.
242  {
243  if ( xnodes[0].valid() )
244  {
245  s = xnodes[0]->getText();
246  result = true;
247  }
248  else if(traceDebug())
249  {
251  << "ossimAuxXmlSupportData::getPath ERROR:\n"
252  << "Node not found: " << path
253  << std::endl;
254  }
255  }
256  else if ( xnodes.size() == 0 )
257  {
258  if(traceDebug())
259  {
261  << "ossimAuxXmlSupportData::getPath ERROR:\n"
262  << "Node not found: " << path
263  << std::endl;
264  }
265  }
266  else
267  {
268  if(traceDebug())
269  {
271  << "ossimAuxXmlSupportData::getPath ERROR:\n"
272  << "Multiple nodes found: " << path
273  << std::endl;
274  }
275  }
276 
277  if (!result)
278  {
279  s.clear();
280  }
281  return result;
282 
283 } // bool ossimAuxXmlSupportData::getPath
284 
285 
286 
287 bool ossimAuxXmlSupportData::getProjcsName( const std::string& wkt,
288  std::string& name ) const
289 {
290  bool result = false;
291 
292  if ( wkt.size() )
293  {
294  // Find "PROJCS":
295  std::string::size_type startPos = wkt.find( std::string("PROJCS[") );
296  if ( startPos != std::string::npos )
297  {
298  startPos += 7; // Move to end of projcs[ string.
299 
300  // Find first comma ',':
301  std::string::size_type endPos = wkt.find( ',', startPos+1 );
302  if ( endPos != std::string::npos )
303  {
304  if ( startPos < endPos )
305  {
306  name = wkt.substr( startPos, endPos-startPos );
307  if ( name.size() )
308  {
309  result = true;
310  }
311  }
312  }
313  }
314  }
315 
316  return result;
317 
318 } // End: ossimAuxXmlSupportData::getProgcsName
319 
320 ossimUnitType ossimAuxXmlSupportData::getUnits( const std::string& wkt ) const
321 {
323  if ( wkt.size() )
324  {
325  // Note this is order dependent, i.e. you have to look for "Foot_US" before "Foot".
326  ossimString os = wkt;
327  os.downcase();
328  if ( os.contains("feet_intl") )
329  {
330  units = OSSIM_FEET;
331  }
332  else if ( os.contains("foot_us") )
333  {
334  units = OSSIM_US_SURVEY_FEET;
335  }
336  else if ( os.contains("feet") || os.contains("foot") )
337  {
338  units = OSSIM_FEET;
339  }
340  //---
341  // There can be two "unit" blocks. One for PROJCS and one for GEOGCS.
342  // Do this last as the GEOGCS block will have Degree in it. May need to split
343  // the two blocks and then search if this doesn't work.
344  //---
345  else if ( os.contains("degree") )
346  {
347  units = OSSIM_DEGREES;
348  }
349  }
350 
351  return units;
352 
353 } // End: ossimAuxXmlSupportData::getUnits
void clear()
Erases the entire container.
Definition: ossimString.h:432
ossimString substitute(const ossimString &searchKey, const ossimString &replacementValue, bool replaceAll=false) const
Substitutes searchKey string with replacementValue and returns a string.
ossimUnitType
bool valid() const
Definition: ossimRefPtr.h:75
double y
Definition: ossimDpt.h:165
bool contains(char aChar) const
Definition: ossimString.h:58
virtual bool isGeographic() const
void split(std::vector< ossimString > &result, const ossimString &separatorList, bool skipBlankFields=false) const
Splits this string into a vector of strings (fields) using the delimiter list specified.
virtual void setDecimalDegreesPerPixel(const ossimDpt &gsd)
static StreamFactoryRegistry * instance()
const ossimString & getValue() const
bool getPath(const ossimString &path, const ossimXmlDocument &xdoc, ossimString &s) const
Gets path from doc and initializes string.
virtual void setMetersPerPixel(const ossimDpt &gsd)
#define US_METERS_PER_FT
ossimProjection * createProjection(const ossimFilename &filename, ossim_uint32 entryIdx) const
virtual ~ossimAuxXmlSupportData()
virtual destructor
yy_size_t size
std::string::size_type size() const
Definition: ossimString.h:405
unsigned int ossim_uint32
ossim_float64 toFloat64() const
static ossimString downcase(const ossimString &aString)
Definition: ossimString.cpp:48
bool initializeProjection(const ossimXmlDocument xdoc, const std::string &wkt, ossimProjection *proj) const
Sets tie and scale.
bool hasNans() const
Definition: ossimDpt.h:67
static ossimProjectionFactoryRegistry * instance()
#define MTRS_PER_FT
double x
Definition: ossimDpt.h:164
bool read(std::istream &in)
virtual void setUlTiePoints(const ossimGpt &gpt)
void findNodes(const ossimString &xpath, std::vector< ossimRefPtr< ossimXmlNode > > &nodelist) const
Appends any matching nodes to the list supplied (should be empty):
ossimString & gsub(const ossimString &searchKey, const ossimString &replacementValue, bool replaceAll=false)
Substitutes searchKey string with replacementValue and returns a reference to *this.
ossimUnitType getUnits(const std::string &wkt) const
Gets units of Projected Coordinate System.
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
void makeNan()
Definition: ossimDpt.h:65
ossimRefPtr< ossimProjection > getProjection(const ossimFilename &file) const
Method to get a projection if possible.
ossimAuxXmlSupportData()
default constructor
const std::string & string() const
Definition: ossimString.h:414
bool getProjcsName(const std::string &wkt, std::string &name) const
Get first parameter from PROJCS[ ...