1 //----------------------------------------------------------------------------
2 //
3 // License:  LGPL
4 //
5 // See LICENSE.txt file in the top level directory for more details.
6 //
7 //----------------------------------------------------------------------------
8 // $Id: ossimQuickbirdRpcHeader.cpp 9094 2006-06-13 19:12:40Z dburken $
9 
10 #include <ossim/support_data/ossimQuickbirdRpcHeader.h>
11 #include <ossim/base/ossimRegExp.h>
12 #include <iostream>
13 #include <fstream>
14 #include <algorithm>
15 #include <iterator>
16 #include <ossim/base/ossimXmlDocument.h>
17 
18 using namespace std;
19 
operator <<(std::ostream & out,const ossimQuickbirdRpcHeader & data)20 std::ostream& operator << (std::ostream& out,
21 		      const ossimQuickbirdRpcHeader& data)
22 {
23    out << "theSatId      = " << data.theSatId << std::endl
24        << "theBandId     = " << data.theBandId << std::endl
25        << "theSpecId     = " << data.theSpecId << std::endl
26        << "theErrBias    = " << data.theErrBias << std::endl
27        << "theLineOffset = " << data.theLineOffset << std::endl
28        << "theSampOffset = " << data.theSampOffset << std::endl
29        << "theLatOffset  = " << data.theLatOffset << std::endl
30        << "theLonOffset  = " << data.theLonOffset << std::endl
31        << "theHeightOffset  = " << data.theHeightOffset << std::endl
32        << "theLineScale  = " << data.theLineScale << std::endl
33        << "theSampScale  = " << data.theSampScale << std::endl
34        << "theLatScale  = " << data.theLatScale << std::endl
35        << "theLonScale  = " << data.theLonScale << std::endl
36        << "theHeightScale  = " << data.theHeightScale << std::endl;
37 
38    out << "lineNumCoef = " << std::endl;
39    std::copy(data.theLineNumCoeff.begin(),
40              data.theLineNumCoeff.end(),
41              std::ostream_iterator<double>(out, "\n"));
42    out << "lineDenCoef = " << std::endl;
43    std::copy(data.theLineDenCoeff.begin(),
44              data.theLineDenCoeff.end(),
45              std::ostream_iterator<double>(out, "\n"));
46    out << "sampNumCoef = " << std::endl;
47    std::copy(data.theSampNumCoeff.begin(),
48              data.theSampNumCoeff.end(),
49              std::ostream_iterator<double>(out, "\n"));
50    out << "sampDenCoef = " << std::endl;
51    std::copy(data.theSampDenCoeff.begin(),
52              data.theSampDenCoeff.end(),
53              std::ostream_iterator<double>(out, "\n"));
54 
55    return out;
56 }
57 
58 
ossimQuickbirdRpcHeader()59 ossimQuickbirdRpcHeader::ossimQuickbirdRpcHeader()
60 :  theErrBias(0),
61    theErrRand(0),
62    theLineOffset(0),
63    theSampOffset(0),
64    theLatOffset(0),
65    theLonOffset(0),
66    theHeightOffset(0),
67    theLineScale(0),
68    theSampScale(0),
69    theLatScale(0),
70    theLonScale(0),
71    theHeightScale(0)
72 {
73 }
74 
open(const ossimFilename & file)75 bool ossimQuickbirdRpcHeader::open(const ossimFilename& file)
76 {
77    theFilename = file;
78 
79    if (theFilename.ext().upcase() == "XML")
80       return parseXml();
81 
82    std::ifstream in(file.c_str(), std::ios::in|std::ios::binary);
83 
84    char test[64];
85 
86    in.read((char*)test, 63);
87    test[63] = '\0';
88    in.seekg(0);
89    ossimString line = test;
90    line = line.upcase();
91 
92    if(parseNameValue(line))
93    {
94       theErrorStatus = ossimErrorCodes::OSSIM_OK;
95       getline(in, line);
96       while((in)&&(theErrorStatus == ossimErrorCodes::OSSIM_OK))
97       {
98          line = line.upcase();
99          if(line.contains("LINENUMCOEF"))
100          {
101             if(!readCoeff(in, theLineNumCoeff))
102             {
103                setErrorStatus();
104                break;
105             }
106          }
107          else if(line.contains("LINEDENCOEF"))
108          {
109             if(!readCoeff(in, theLineDenCoeff))
110             {
111                setErrorStatus();
112                break;
113             }
114          }
115          else if(line.contains("SAMPNUMCOEF"))
116          {
117             if(!readCoeff(in, theSampNumCoeff))
118             {
119                setErrorStatus();
120                break;
121             }
122          }
123          else if(line.contains("SAMPDENCOEF"))
124          {
125             if(!readCoeff(in, theSampDenCoeff))
126             {
127                setErrorStatus();
128                break;
129             }
130          }
131          else if(!parseNameValue(line))
132          {
133             setErrorStatus();
134             break;
135          }
136          getline(in,
137                  line);
138       }
139    }
140    else
141    {
142       setErrorStatus();
143    }
144    return (theErrorStatus == ossimErrorCodes::OSSIM_OK);
145 }
146 
parseXml()147 bool ossimQuickbirdRpcHeader::parseXml ()
148 {
149    ossimXmlDocument document;
150    if (!document.openFile(theFilename))
151       return false;
152 
153    ossimRefPtr<ossimXmlNode> root = document.getRoot();
154    ossimRefPtr<ossimXmlNode> rpcNode = root->findFirstNode("RPB");
155    if (!rpcNode)
156       return false;
157 
158    ossimString dataString;
159    bool success = false; // Assume we're gonna screw this up...
160    while (1)
161    {
162       theSatId = rpcNode->getChildTextValue("SATID");
163       if (theSatId.empty())
164          break;
165 
166       theBandId = rpcNode->getChildTextValue("BANDID");
167       if (theBandId.empty())
168          break;
169 
170       theSpecId = rpcNode->getChildTextValue("SPECID");
171       if (theSpecId.empty())
172          break;
173 
174       rpcNode = rpcNode->findFirstNode("IMAGE");
175       if (!rpcNode)
176          break;
177 
178       dataString = rpcNode->getChildTextValue("ERRBIAS");
179       if (dataString.empty())
180          break;
181       theErrBias = dataString.toDouble();
182 
183       dataString = rpcNode->getChildTextValue("ERRRAND");
184       if (dataString.empty())
185          break;
186       theErrRand = dataString.toDouble();
187 
188       dataString = rpcNode->getChildTextValue("LINEOFFSET");
189       if (dataString.empty())
190          break;
191       theLineOffset = dataString.toInt();
192 
193       dataString = rpcNode->getChildTextValue("SAMPOFFSET");
194       if (dataString.empty())
195          break;
196       theSampOffset = dataString.toInt();
197 
198       dataString = rpcNode->getChildTextValue("LATOFFSET");
199       if (dataString.empty())
200          break;
201       theLatOffset = dataString.toDouble();
202 
203       dataString = rpcNode->getChildTextValue("LONGOFFSET");
204       if (dataString.empty())
205          break;
206       theLonOffset = dataString.toDouble();
207 
208       dataString = rpcNode->getChildTextValue("HEIGHTOFFSET");
209       if (dataString.empty())
210          break;
211       theHeightOffset = dataString.toDouble();
212 
213       dataString = rpcNode->getChildTextValue("LINESCALE");
214       if (dataString.empty())
215          break;
216       theLineScale = dataString.toDouble();
217 
218       dataString = rpcNode->getChildTextValue("SAMPSCALE");
219       if (dataString.empty())
220          break;
221       theSampScale = dataString.toDouble();
222 
223       dataString = rpcNode->getChildTextValue("LATSCALE");
224       if (dataString.empty())
225          break;
226       theLatScale = dataString.toDouble();
227 
228       dataString = rpcNode->getChildTextValue("LONGSCALE");
229       if (dataString.empty())
230          break;
231       theLonScale = dataString.toDouble();
232 
233       dataString = rpcNode->getChildTextValue("HEIGHTSCALE");
234       if (dataString.empty())
235          break;
236       theHeightScale = dataString.toDouble();
237 
238       vector<ossimString> ln, ld, sn, sd;
239       rpcNode->getChildTextValue("LINENUMCOEFList/LINENUMCOEF").split(ln, " ", true);
240       rpcNode->getChildTextValue("LINEDENCOEFList/LINEDENCOEF").split(ld, " ", true);
241       rpcNode->getChildTextValue("SAMPNUMCOEFList/SAMPNUMCOEF").split(sn, " ", true);
242       rpcNode->getChildTextValue("SAMPDENCOEFList/SAMPDENCOEF").split(sd, " ", true);
243       if ( (ln.size() != 20) || (ld.size() != 20) || (sn.size() != 20) || (sd.size() != 20))
244          break;
245 
246       for (int i=0; i<20; ++i)
247       {
248          theLineNumCoeff.emplace_back(ln[i].toDouble());
249          theLineDenCoeff.emplace_back(ld[i].toDouble());
250          theSampNumCoeff.emplace_back(sn[i].toDouble());
251          theSampDenCoeff.emplace_back(sd[i].toDouble());
252       }
253       success = true; // Well waddaya know!
254    }
255    return success;
256 }
257 
readCoeff(std::istream & in,std::vector<double> & coeff)258 bool ossimQuickbirdRpcHeader::readCoeff(std::istream& in,
259 					std::vector<double>& coeff)
260 {
261    coeff.clear();
262    bool done = false;
263    ossimString line;
264    while(!in.eof()&&!in.bad()&&!done)
265    {
266       getline(in,
267 	      line);
268       line.trim();
269       line.trim(',');
270       if(line.contains(");"))
271       {
272          done = true;
273          line.trim(';');
274          line.trim(')');
275       }
276       coeff.push_back(line.toDouble());
277    }
278    return done;
279 }
isGlobal() const280 bool ossimQuickbirdRpcHeader::isGlobal() const
281 {
282 	ossimRegExp regex("R[0-9]*C[0-9]*");
283 
284 	return !regex.find(theFilename.c_str());
285 }
286 
parseNameValue(const ossimString & line)287 bool ossimQuickbirdRpcHeader::parseNameValue(const ossimString& line)
288 {
289    bool result = true;
290    ossimString lineCopy = line;
291 
292    if(lineCopy.contains("SATID"))
293    {
294       theSatId = lineCopy.after("\"");
295       theSatId = theSatId.before("\"");
296    }
297    else if(lineCopy.contains("BANDID"))
298    {
299       theBandId = lineCopy.after("\"");
300       theBandId = theBandId.before("\"");
301    }
302    else if(lineCopy.contains("SPECID"))
303    {
304       theSpecId = lineCopy.after("\"");
305       theSpecId = theSpecId.before("\"");
306    }
307    else if(lineCopy.contains("BEGIN_GROUP"))
308    {
309    }
310    else if(lineCopy.contains("ERRBIAS"))
311    {
312       lineCopy = lineCopy.after("=");
313       theErrBias = lineCopy.before(";").toDouble();
314    }
315    else if(lineCopy.contains("ERRRAND"))
316    {
317       lineCopy = lineCopy.after("=");
318       theErrRand = lineCopy.before(";").toDouble();
319    }
320    else if(lineCopy.contains("LINEOFFSET"))
321    {
322       lineCopy = lineCopy.after("=");
323       theLineOffset = lineCopy.before(";").toInt();
324    }
325    else if(lineCopy.contains("SAMPOFFSET"))
326    {
327       lineCopy = lineCopy.after("=");
328       theSampOffset = lineCopy.before(";").toInt();
329    }
330    else if(lineCopy.contains("LATOFFSET"))
331    {
332       lineCopy = lineCopy.after("=");
333       theLatOffset = lineCopy.before(";").toDouble();
334    }
335    else if(lineCopy.contains("LONGOFFSET"))
336    {
337       lineCopy = lineCopy.after("=");
338       theLonOffset = lineCopy.before(";").toDouble();
339    }
340    else if(lineCopy.contains("HEIGHTOFFSET"))
341    {
342       lineCopy = lineCopy.after("=");
343       theHeightOffset = lineCopy.before(";").toDouble();
344    }
345    else if(lineCopy.contains("LINESCALE"))
346    {
347       lineCopy = lineCopy.after("=");
348       theLineScale = lineCopy.before(";").toDouble();
349    }
350    else if(lineCopy.contains("SAMPSCALE"))
351    {
352       lineCopy = lineCopy.after("=");
353       theSampScale = lineCopy.before(";").toDouble();
354    }
355    else if(lineCopy.contains("LATSCALE"))
356    {
357       lineCopy = lineCopy.after("=");
358       theLatScale = lineCopy.before(";").toDouble();
359    }
360    else if(lineCopy.contains("LONGSCALE"))
361    {
362       lineCopy = lineCopy.after("=");
363       theLonScale = lineCopy.before(";").toDouble();
364    }
365    else if(lineCopy.contains("HEIGHTSCALE"))
366    {
367       lineCopy = lineCopy.after("=");
368       theHeightScale = lineCopy.before(";").toDouble();
369    }
370    else if(lineCopy.contains("END_GROUP"))
371    {
372    }
373    else if(lineCopy.contains("END"))
374    {
375    }
376    else
377    {
378       result = false;
379    }
380 
381    return result;
382 }
383