vpgl_nitf_rational_camera.cxx
Go to the documentation of this file.
1 // This is core/vpgl/file_formats/vpgl_nitf_rational_camera.cxx
2 #include <cstdlib>
3 #include <cmath>
4 #include <cstring>
5 #include <cctype>
7 //:
8 // \file
9 // \brief instance a nitf_rational camera from nitf header information.
10 // \author Jim Green
11 // \date Dec 2006
12 
13 #ifdef _MSC_VER
14 # include <vcl_msvc_warnings.h>
15 #endif
16 #include <vil/vil_load.h>
17 // for calls to get nitf_rational parameters from vil
18 #include <vil/file_formats/vil_nitf2_image.h>
19 
20 // Conversion from igeolo string format to doubles
21 static int to_int (const char* in_string,int size)
22 {
23  int value = 0;
24  while (size--)
25  value = (value*10) + (*in_string++ - '0');
26  return value;
27 }
28 
29 //: converts one of lat or lon string to a double
30 static int geostr_to_double(const char* in_string, double* val, vpgl_nitf_rational_camera::geopt_coord c)
31 {
32  // int invalid = 1;
33  int length;
34  int deg, min;
35  float fsec;
36  const char* orig = in_string;
37 
38  //here are lat/lon dependent variables
39  char sposdir, cposdir, snegdir, cnegdir;
40  int maxval;
41 
43  {
44  sposdir='n';
45  cposdir='N';
46  snegdir='s';
47  cnegdir='S';
48  maxval=90;
49  }
50  else
51  {
52  sposdir='e';
53  cposdir='E';
54  snegdir='w';
55  cnegdir='W';
56  maxval=180;
57  }
58 
59  while ((*in_string == ' ') || (*in_string == '\t'))
60  ++in_string;
61 
62  for (length=0; std::isdigit (*in_string) && length<15; ++length)
63  ++in_string;
64  if (length>14) return 0;
65 
66  //three different formats accepted
67  //DDDMMSS.S[d] where [d]=nNsSeEwW
68  if (length>3)
69  {
70  if (length < 5)
71  return 0;
72 
73  //get the minutes
74  if ((min = to_int (in_string-4, 2)) >= 60 || min<0)
75  return 0;
76 
77  //get the degrees
78  if ((deg = to_int (in_string-length, length-4)) > maxval || deg<0)
79  return 0;
80 
81  //get the seconds (float)
82  in_string-=2;
83  char* temp = new char[2];
84  for (length=0;
85  (*in_string=='.' || std::isdigit (*in_string)) && length<15;
86  ++length)
87  ++in_string;
88  if (length>14) return 0;
89 
90  std::strncpy(temp,in_string-length,length);
91  if ( (fsec = (float)std::atof(temp)) >= 60.0f || fsec<0.0f)
92  return 0;
93  delete [] temp;
94 
95  //skip to the direction
96  while ((*in_string == ' ') || (*in_string == '\t'))
97  ++in_string;
98 
99  //calculate the value
100  *val = deg;
101  *val += ((double)(min))/(60.0);
102  *val += ((double)(fsec))/(3600.0);
103 
104  //adjust for the direction
105  if ( *in_string==sposdir || *in_string==cposdir) {}
106  else if ( *in_string==snegdir || *in_string==cnegdir) {*val = -(*val);}
107  else return 0;
108 
109  ++in_string;
110 
111  return static_cast<int>(in_string - orig);
112  }
113  else //DDDdMM'SS"[d] where [d]=nNsSeEwW
114  if (*in_string == 'd')
115  {
116  //get the degrees
117  if (length > 3)
118  return 0;
119  if ((deg = to_int (in_string-length, length)) > maxval || deg<0)
120  return 0;
121 
122  //go past 'd' and spaces
123  ++in_string;
124  while ((*in_string == ' ') || (*in_string == '\t'))
125  ++in_string;
126 
127  //get the minutes
128  for (length=0; std::isdigit (*in_string) && length<15; ++in_string, ++length) /*nothing*/;
129  if (length>14) return 0;
130  if (length > 2)
131  return 0;
132  if ((min = to_int (in_string-length, length)) >= 60 || min<0)
133  return 0;
134 
135  //go past ''' and spaces
136  ++in_string;
137  while ((*in_string == ' ') || (*in_string == '\t'))
138  ++in_string;
139 
140  //get the seconds (float)
141  char* temp= new char[2];
142  for (length=0;
143  (*in_string=='.' || std::isdigit (*in_string)) && length<15;
144  ++length)
145  ++in_string;
146  if (length>14) return 0;
147 
148  std::strncpy(temp,in_string-length,length);
149  if ( (fsec = (float)std::atof(temp)) >= 60.0f || fsec<0.0f)
150  return 0;
151  delete [] temp;
152 
153  //go past '"' and any spaces to the direction
154  ++in_string;
155  while ((*in_string == ' ') || (*in_string == '\t'))
156  ++in_string;
157 
158  //calculate value
159  *val = deg;
160  *val += ((double)(min))/(60.0);
161  *val += ((double)(fsec))/(3600.0);
162 
163  //adjust for the direction
164  if ( *in_string==sposdir || *in_string==cposdir) {}
165  else if ( *in_string==snegdir || *in_string==cnegdir) {*val = -(*val);}
166  else return 0;
167 
168  ++in_string;
169 
170  return static_cast<int>(in_string - orig);
171  }
172  else //DDD.DDDD
173  if (*in_string == ' ' || *in_string == '-' || *in_string == '+'
174  || *in_string == '.' || *in_string == '\0')
175  {
176  char* temp= new char[2];
177  in_string=orig;
178 
179  //go past any spaces
180  while ((*in_string == ' ') || (*in_string == '\t'))
181  ++in_string;
182 
183  //calculate length of float
184  for (length=0;
185  (*in_string=='+' ||*in_string=='-' || *in_string=='.' ||
186  std::isdigit (*in_string)) && length<15;
187  ++length)
188  ++in_string;
189  if (length>14) return 0;
190 
191  //calculate value of float
192  std::strncpy(temp,in_string-length,length);
193  *val = std::atof(temp);
194  if (std::fabs(*val)>float(maxval)) return 0;
195  delete [] temp;
196 
197  ++in_string;
198 
199  return static_cast<int>(in_string - orig);
200  }
201  else
202  return 0;
203 }
204 
205 //: converts a latlon in_string to doubles
206 static int geostr_to_latlon(const char* str, double* lat, double* lon)
207 {
208  int latstrlen=geostr_to_double(str,lat,vpgl_nitf_rational_camera::LAT);
209  if (latstrlen == 0) return 0;
210  str += latstrlen;
211  int lonstrlen=geostr_to_double(str,lon,vpgl_nitf_rational_camera::LON);
212  if ( lonstrlen == 0) return 0;
213 
214  return latstrlen+lonstrlen;
215 }
216 
217 // Coefficient ordering possibilities
218 // NITF_RATIONAL00B - commercial + airborne
220 {
221  ord[0] = 11; // 0, xxx);
222  ord[1] = 14; // 1, xxy);
223  ord[2] = 17; // 2, xxz);
224  ord[3] = 7; // 3, xx );
225  ord[4] = 12; // 4, xyy);
226  ord[5] = 10; // 5, xyz);
227  ord[6] = 4; // 6, xy );
228  ord[7] = 13; // 7, xzz);
229  ord[8] = 5; // 8, xz );
230  ord[9] = 1; // 9, x );
231  ord[10] = 15; // 10, yyy);
232  ord[11] = 18; // 11, yyz);
233  ord[12] = 8; // 12, yy );
234  ord[13] = 16; // 13, yzz);
235  ord[14] = 6; // 14, yz );
236  ord[15] = 2; // 15, y );
237  ord[16] = 19; // 16, zzz);
238  ord[17] = 9; // 17, zz );
239  ord[18] = 3; // 18, z );
240  ord[19] = 0; // 19, 1 );
241 }
242 
244 init(vil_nitf2_image* nitf_image, bool verbose)
245 {
246  std::vector< vil_nitf2_image_subheader* > headers = nitf_image->get_image_headers();
247  vil_nitf2_image_subheader* hdr = headers[0];
248 
249  double tre_data[90];
250  // initialize the array
251  for (double & i : tre_data) i = 0;
252 
253 
254  bool success =
255  hdr->get_rpc_params(nitf_rational_type_, image_id_, image_igeolo_, tre_data);
256  if (!success)
257  {
258  std::cout << "Failed to get rational camera parameters from nitf image in"
259  << " vgpl_nitf_rational_camera\n";
260  return false;
261  }
262 
263  if (verbose)
264  std::cout << " nitf_rational type " << nitf_rational_type_ << '\n'
265  << " Image Id " << image_id_ << '\n'
266  << " IGEOLO " << image_igeolo_ << '\n';
267  // example 324158N1171117W324506N1171031W324428N1170648W324120N1170734W
268  double ULlat, ULlon;
269  double URlat, URlon;
270  double LLlat, LLlon;
271  double LRlat, LRlon;
272 
273  // Extract them from the image_igeolo field
274  geostr_to_latlon (image_igeolo_.c_str(), &ULlat, &ULlon);
275  geostr_to_latlon (image_igeolo_.c_str()+15, &URlat, &URlon);
276  geostr_to_latlon (image_igeolo_.c_str()+30, &LRlat, &LRlon);
277  geostr_to_latlon (image_igeolo_.c_str()+45, &LLlat, &LLlon);
278 
279  ul_[LAT]=ULlat; ul_[LON]=ULlon;
280  ur_[LAT]=URlat; ur_[LON]=URlon;
281  ll_[LAT]=LLlat; ll_[LON]=LLlon;
282  lr_[LAT]=LRlat; lr_[LON]=LRlon;
283 
284  if (verbose)
285  std::cout << "ULlon " << ULlon << " ULlat " << ULlat << '\n'
286  << "URlon " << URlon << " URlat " << URlat << '\n'
287  << "LRlon " << LRlon << " LRlat " << LRlat << '\n'
288  << "LLlon " << LLlon << " lLlat " << LLlat << '\n';
289  int ord[20];
290  // set order of coefficients depending on call parameter "coef_ordering" = coefficient order
291  if (nitf_rational_type_ == "RPC00A")
292  set_order_b(ord);
293  else if (nitf_rational_type_ == "RPC00B")
294  set_order_b(ord);
295  else
296  {
297  std::cout << "Unknown rational type from nitf image in"
298  << " vgpl_nitf_rational_camera\n";
299  return false;
300  }
301 
302 
303  // apply the 80 coefficients to the std::vectors to instance the vpgl_rational_camera
304  for (int i=0; i<20; i++)
305  {
306  rational_coeffs_[2][i] = tre_data[ord[i]];
307  rational_coeffs_[3][i] = tre_data[ord[i] + 20];
308  rational_coeffs_[0][i] = tre_data[ord[i] + 40];
309  rational_coeffs_[1][i] = tre_data[ord[i] + 60];
310  }
311  // also fill in the scale & offset normalization parameters
312  scale_offsets_[X_INDX].set_scale(tre_data[88]);
313  scale_offsets_[X_INDX].set_offset(tre_data[83]);
314  scale_offsets_[Y_INDX].set_scale(tre_data[87]);
315  scale_offsets_[Y_INDX].set_offset(tre_data[82]);
316  scale_offsets_[Z_INDX].set_scale(tre_data[89]);
317  scale_offsets_[Z_INDX].set_offset(tre_data[84]);
318  scale_offsets_[U_INDX].set_scale(tre_data[86]);
319  scale_offsets_[U_INDX].set_offset(tre_data[81]);
320  scale_offsets_[V_INDX].set_scale(tre_data[85]);
321  scale_offsets_[V_INDX].set_offset(tre_data[80]);
322 
323  double correction_u_off,correction_v_off;
324  success=hdr->get_correction_offset(correction_u_off,correction_v_off);
325 
326  if (success)
327  {
328  scale_offsets_[U_INDX].set_offset(scale_offsets_[U_INDX].offset()-correction_u_off);
329  scale_offsets_[V_INDX].set_offset(scale_offsets_[V_INDX].offset()-correction_v_off);
330  }
331  return true;
332 }
333 
335 
336 
338 vpgl_nitf_rational_camera(std::string const& nitf_image_path,
339  bool verbose)
340 {
341  //first open the nitf image
342  vil_image_resource_sptr image =
343  vil_load_image_resource(nitf_image_path.c_str());
344  if (!image)
345  {
346  std::cout << "Image load failed in vpgl_nitf_rational_camera_constructor\n";
347  return ;
348  }
349  std::string format = image->file_format();
350  std::string prefix = format.substr(0,4);
351  if (prefix != "nitf")
352  {
353  std::cout << "not a nitf image in vpgl_nitf_rational_camera_constructor\n";
354  return;
355  }
356  //cast to an nitf2_image
357  auto* nitf_image = (vil_nitf2_image*)image.ptr();
358  //Get and set the information
359  if (!this->init(nitf_image, verbose))
360  return;
362  double z_off = z.offset();
363  if (verbose)
364  {
365  double ul_u=0, ul_v=0, ur_u=0, ur_v=0, ll_u=0, ll_v=0, lr_u=0, lr_v=0;
366  // Project upper left corner
367  this->project(ul_[LON], ul_[LAT], z_off, ul_u, ul_v);
368  std::cout << "Upper left image corner(" << ul_u << ' ' << ul_v << ")\n";
369  // Project upper right corner
370  this->project(ur_[LON], ur_[LAT], z_off, ur_u, ur_v);
371  std::cout << "Upper right image corner(" << ur_u << ' ' << ur_v << ")\n";
372  // Project lower left corner
373  this->project(ll_[LON], ll_[LAT], z_off, ll_u, ll_v);
374  std::cout << "Lower left image corner(" << ll_u << ' ' << ll_v << ")\n";
375  // Project lower right corner
376  this->project(lr_[LON], lr_[LAT], z_off, lr_u, lr_v);
377  std::cout << "Lower right image corner(" << lr_u << ' ' << lr_v << ")\n";
378  }
379 }
380 
382 vpgl_nitf_rational_camera(vil_nitf2_image* nitf_image, bool verbose)
383 {
384  //Get and set the information
385  if (!this->init(nitf_image, verbose))
386  return;
387 
388  if (verbose)
389  std::cout << *this;
391  double z_off = z.offset();
392  if (verbose)
393  {
394  double ul_u=0, ul_v=0, ur_u=0, ur_v=0, ll_u=0, ll_v=0, lr_u=0, lr_v=0;
395  // Project upper left corner
396  this->project(ul_[LON], ul_[LAT], z_off, ul_u, ul_v);
397  std::cout << "Upper left image corner(" << ul_u << ' ' << ul_v << ")\n";
398  // Project upper right corner
399  this->project(ur_[LON], ur_[LAT], z_off, ur_u, ur_v);
400  std::cout << "Upper right image corner(" << ur_u << ' ' << ur_v << ")\n";
401  // Project lower left corner
402  this->project(ll_[LON], ll_[LAT], z_off, ll_u, ll_v);
403  std::cout << "Lower left image corner(" << ll_u << ' ' << ll_v << ")\n";
404  // Project lower right corner
405  this->project(lr_[LON], lr_[LAT], z_off, lr_u, lr_v);
406  std::cout << "Lower right image corner(" << lr_u << ' ' << lr_v << ")\n";
407  }
408 }
vnl_matrix_fixed< double, 4, 20 > rational_coeffs_
bool init(vil_nitf2_image *nitf_image, bool verbose)
std::vector< vpgl_scale_offset< double > > scale_offsets_
T maxval(vbl_array_1d< T > const &in)
vnl_double_2 ul_
geo-coordinates of image corners.
vnl_decnum min(vnl_decnum const &x, vnl_decnum const &y)
double offset(const coor_index coor_index) const
get a specific offset value.
double length(v const &a)
: instance a nitf_rational camera from nitf header information.
void project(const double x, const double y, const double z, double &u, double &v) const override
The generic camera interface. u represents image column, v image row.