core/vpgl/file_formats/vpgl_nitf_rational_camera.cxx
Go to the documentation of this file.
00001 // This is core/vpgl/file_formats/vpgl_nitf_rational_camera.cxx
00002 #include "vpgl_nitf_rational_camera.h"
00003 //:
00004 // \file
00005 // \brief instance a nitf_rational camera from nitf header information.
00006 // \author Jim Green
00007 // \date Dec 2006
00008 
00009 #include <vcl_cstdlib.h>
00010 #include <vil/vil_load.h>
00011 #include <vcl_cmath.h>
00012 #include <vcl_cstring.h>
00013 #include <vcl_cctype.h>
00014 // for calls to get nitf_rational parameters from vil
00015 #include <vil/file_formats/vil_nitf2_image.h>
00016 
00017 // Conversion from igeolo string format to doubles
00018 static int to_int (const char* in_string,int size)
00019 {
00020   int value = 0;
00021   while (size--)
00022     value = (value*10) + (*in_string++ - '0');
00023   return value;
00024 }
00025 
00026 //: converts one of lat or lon string to a double
00027 static int geostr_to_double(const char* in_string, double* val, vpgl_nitf_rational_camera::geopt_coord c)
00028 {
00029   //  int invalid = 1;
00030   int length;
00031   int deg, min;
00032   float fsec;
00033   const char* orig = in_string;
00034 
00035   //here are lat/lon dependent variables
00036   char sposdir, cposdir, snegdir, cnegdir;
00037   int maxval;
00038 
00039   if (c == vpgl_nitf_rational_camera::LAT)
00040   {
00041     sposdir='n';
00042     cposdir='N';
00043     snegdir='s';
00044     cnegdir='S';
00045     maxval=90;
00046   }
00047   else
00048   {
00049     sposdir='e';
00050     cposdir='E';
00051     snegdir='w';
00052     cnegdir='W';
00053     maxval=180;
00054   }
00055 
00056   while ((*in_string == ' ') || (*in_string == '\t'))
00057     ++in_string;
00058 
00059   for (length=0; vcl_isdigit (*in_string) && length<15; ++length)
00060     ++in_string;
00061   if (length>14) return 0;
00062 
00063   //three different formats accepted
00064   //DDDMMSS.S[d] where [d]=nNsSeEwW
00065   if (length>3)
00066   {
00067     if (length < 5)
00068       return 0;
00069 
00070     //get the minutes
00071     if ((min = to_int (in_string-4, 2)) >= 60 || min<0)
00072       return 0;
00073 
00074     //get the degrees
00075     if ((deg = to_int (in_string-length, length-4)) > maxval || deg<0)
00076       return 0;
00077 
00078     //get the seconds (float)
00079     in_string-=2;
00080     char* temp = new char[2];
00081     for (length=0;
00082          (*in_string=='.' || vcl_isdigit (*in_string)) && length<15;
00083          ++length)
00084       ++in_string;
00085     if (length>14) return 0;
00086 
00087     vcl_strncpy(temp,in_string-length,length);
00088     if ( (fsec = (float)vcl_atof(temp)) >= 60.0f || fsec<0.0f)
00089       return 0;
00090     delete [] temp;
00091 
00092     //skip to the direction
00093     while ((*in_string == ' ') || (*in_string == '\t'))
00094       ++in_string;
00095 
00096     //calculate the value
00097     *val = deg;
00098     *val += ((double)(min))/(60.0);
00099     *val += ((double)(fsec))/(3600.0);
00100 
00101     //adjust for the direction
00102     if ( *in_string==sposdir || *in_string==cposdir) {}
00103     else if ( *in_string==snegdir || *in_string==cnegdir) {*val = -(*val);}
00104     else return 0;
00105 
00106     ++in_string;
00107 
00108     return in_string-orig;
00109   }
00110   else //DDDdMM'SS"[d]  where [d]=nNsSeEwW
00111   if (*in_string == 'd')
00112   {
00113     //get the degrees
00114     if (length > 3)
00115       return 0;
00116     if ((deg = to_int (in_string-length, length)) > maxval || deg<0)
00117       return 0;
00118 
00119     //go past 'd' and spaces
00120     ++in_string;
00121     while ((*in_string == ' ') || (*in_string == '\t'))
00122       ++in_string;
00123 
00124     //get the minutes
00125     for (length=0; vcl_isdigit (*in_string) && length<15; ++in_string, ++length) /*nothing*/;
00126     if (length>14) return 0;
00127     if (length > 2)
00128       return 0;
00129     if ((min = to_int (in_string-length, length)) >= 60 || min<0)
00130       return 0;
00131 
00132     //go past ''' and spaces
00133     ++in_string;
00134     while ((*in_string == ' ') || (*in_string == '\t'))
00135       ++in_string;
00136 
00137     //get the seconds (float)
00138     char* temp= new char[2];
00139     for (length=0;
00140          (*in_string=='.' || vcl_isdigit (*in_string)) && length<15;
00141          ++length)
00142       ++in_string;
00143     if (length>14) return 0;
00144 
00145     vcl_strncpy(temp,in_string-length,length);
00146     if ( (fsec = (float)vcl_atof(temp)) >= 60.0f || fsec<0.0f)
00147       return 0;
00148     delete temp;
00149 
00150     //go past '"' and any spaces to the direction
00151     ++in_string;
00152     while ((*in_string == ' ') || (*in_string == '\t'))
00153       ++in_string;
00154 
00155     //calculate value
00156     *val = deg;
00157     *val += ((double)(min))/(60.0);
00158     *val += ((double)(fsec))/(3600.0);
00159 
00160     //adjust for the direction
00161     if ( *in_string==sposdir || *in_string==cposdir) {}
00162     else if ( *in_string==snegdir || *in_string==cnegdir) {*val = -(*val);}
00163     else return 0;
00164 
00165     ++in_string;
00166 
00167     return in_string-orig;
00168   }
00169   else //DDD.DDDD
00170   if (*in_string == ' ' || *in_string == '-' || *in_string == '+'
00171       || *in_string == '.' || *in_string == '\0')
00172   {
00173     char* temp= new char[2];
00174     in_string=orig;
00175 
00176     //go past any spaces
00177     while ((*in_string == ' ') || (*in_string == '\t'))
00178       ++in_string;
00179 
00180     //calculate length of float
00181     for (length=0;
00182          (*in_string=='+' ||*in_string=='-' || *in_string=='.' ||
00183           vcl_isdigit (*in_string)) && length<15;
00184          ++length)
00185       ++in_string;
00186     if (length>14) return 0;
00187 
00188     //calculate value of float
00189     vcl_strncpy(temp,in_string-length,length);
00190     *val = vcl_atof(temp);
00191     if (vcl_fabs(*val)>float(maxval)) return 0;
00192     delete temp;
00193 
00194     ++in_string;
00195 
00196     return in_string-orig;
00197   }
00198   else
00199     return 0;
00200 }
00201 
00202 //: converts a latlon in_string to doubles
00203 static int geostr_to_latlon(const char* str, double* lat, double* lon)
00204 {
00205   int latstrlen=geostr_to_double(str,lat,vpgl_nitf_rational_camera::LAT);
00206   if (latstrlen == 0) return 0;
00207   str += latstrlen;
00208   int lonstrlen=geostr_to_double(str,lon,vpgl_nitf_rational_camera::LON);
00209   if ( lonstrlen == 0) return 0;
00210 
00211   return latstrlen+lonstrlen;
00212 }
00213 
00214 // Coefficient ordering possibilities
00215 // NITF_RATIONAL00B - commercial + airborne
00216 void vpgl_nitf_rational_camera::set_order_b(int* ord)
00217 {
00218   ord[0]  = 11; //  0, xxx);
00219   ord[1]  = 14; //  1, xxy);
00220   ord[2]  = 17; //  2, xxz);
00221   ord[3]  =  7; //  3, xx );
00222   ord[4]  = 12; //  4, xyy);
00223   ord[5]  = 10; //  5, xyz);
00224   ord[6]  =  4; //  6, xy );
00225   ord[7]  = 13; //  7, xzz);
00226   ord[8]  =  5; //  8, xz );
00227   ord[9]  =  1; //  9, x  );
00228   ord[10] = 15; // 10, yyy);
00229   ord[11] = 18; // 11, yyz);
00230   ord[12] =  8; // 12, yy );
00231   ord[13] = 16; // 13, yzz);
00232   ord[14] =  6; // 14, yz );
00233   ord[15] =  2; // 15, y  );
00234   ord[16] = 19; // 16, zzz);
00235   ord[17] =  9; // 17, zz );
00236   ord[18] =  3; // 18, z  );
00237   ord[19] =  0; // 19, 1  );
00238 }
00239 
00240 bool vpgl_nitf_rational_camera::
00241 init(vil_nitf2_image* nitf_image, bool verbose)
00242 {
00243   vcl_vector< vil_nitf2_image_subheader* > headers = nitf_image->get_image_headers();
00244   vil_nitf2_image_subheader* hdr = headers[0];
00245 
00246   double tre_data[90];
00247   // initialize the array
00248   for (int i=0; i<90; i++) tre_data[i] = 0;
00249 
00250 
00251   bool success =
00252     hdr->get_rpc_params(nitf_rational_type_, image_id_, image_igeolo_,  tre_data);
00253   if (!success)
00254   {
00255     vcl_cout << "Failed to get rational camera parameters from nitf image in"
00256              << " vgpl_nitf_rational_camera\n";
00257     return false;
00258   }
00259 
00260   if (verbose)
00261     vcl_cout << " nitf_rational type " << nitf_rational_type_ << '\n'
00262              << " Image Id " << image_id_ << '\n'
00263              << " IGEOLO " << image_igeolo_ << '\n';
00264   // example 324158N1171117W324506N1171031W324428N1170648W324120N1170734W
00265   double ULlat, ULlon;
00266   double URlat, URlon;
00267   double LLlat, LLlon;
00268   double LRlat, LRlon;
00269 
00270   // Extract them from the image_igeolo field
00271   geostr_to_latlon (image_igeolo_.c_str(),    &ULlat, &ULlon);
00272   geostr_to_latlon (image_igeolo_.c_str()+15, &URlat, &URlon);
00273   geostr_to_latlon (image_igeolo_.c_str()+30, &LRlat, &LRlon);
00274   geostr_to_latlon (image_igeolo_.c_str()+45, &LLlat, &LLlon);
00275 
00276   ul_[LAT]=ULlat;   ul_[LON]=ULlon;
00277   ur_[LAT]=URlat;   ur_[LON]=URlon;
00278   ll_[LAT]=LLlat;   ll_[LON]=LLlon;
00279   lr_[LAT]=LRlat;   lr_[LON]=LRlon;
00280 
00281   if (verbose)
00282     vcl_cout << "ULlon " << ULlon << " ULlat " << ULlat << '\n'
00283              << "URlon " << URlon << " URlat " << URlat << '\n'
00284              << "LRlon " << LRlon << " LRlat " << LRlat << '\n'
00285              << "LLlon " << LLlon << " lLlat " << LLlat << '\n';
00286   int ord[20];
00287   // set order of coefficients depending on call parameter "coef_ordering" = coefficient order
00288   if (nitf_rational_type_ == "RPC00A")
00289     set_order_b(ord);
00290   else if (nitf_rational_type_ == "RPC00B")
00291     set_order_b(ord);
00292   else
00293   {
00294     vcl_cout << "Unknown rational type from nitf image in"
00295              << " vgpl_nitf_rational_camera\n";
00296     return false;
00297   }
00298 
00299 
00300   // apply the 80 coefficients to the vcl_vectors to instance the vpgl_rational_camera
00301   for (int i=0; i<20; i++)
00302   {
00303     rational_coeffs_[2][i] = tre_data[ord[i]];
00304     rational_coeffs_[3][i] = tre_data[ord[i] + 20];
00305     rational_coeffs_[0][i] = tre_data[ord[i] + 40];
00306     rational_coeffs_[1][i] = tre_data[ord[i] + 60];
00307   }
00308   // also fill in the scale & offset normalization parameters
00309   scale_offsets_[X_INDX].set_scale(tre_data[88]);
00310   scale_offsets_[X_INDX].set_offset(tre_data[83]);
00311   scale_offsets_[Y_INDX].set_scale(tre_data[87]);
00312   scale_offsets_[Y_INDX].set_offset(tre_data[82]);
00313   scale_offsets_[Z_INDX].set_scale(tre_data[89]);
00314   scale_offsets_[Z_INDX].set_offset(tre_data[84]);
00315   scale_offsets_[U_INDX].set_scale(tre_data[86]);
00316   scale_offsets_[U_INDX].set_offset(tre_data[81]);
00317   scale_offsets_[V_INDX].set_scale(tre_data[85]);
00318   scale_offsets_[V_INDX].set_offset(tre_data[80]);
00319 
00320   double correction_u_off,correction_v_off;
00321   success=hdr->get_correction_offset(correction_u_off,correction_v_off);
00322 
00323   if (success)
00324   {
00325       scale_offsets_[U_INDX].set_offset(scale_offsets_[U_INDX].offset()-correction_u_off);
00326       scale_offsets_[V_INDX].set_offset(scale_offsets_[V_INDX].offset()-correction_v_off);
00327   }
00328   return true;
00329 }
00330 
00331 vpgl_nitf_rational_camera::vpgl_nitf_rational_camera() {
00332 }
00333 
00334 
00335 vpgl_nitf_rational_camera::
00336 vpgl_nitf_rational_camera(vcl_string const& nitf_image_path,
00337                           bool verbose)
00338 {
00339   //first open the nitf image
00340   vil_image_resource_sptr image =
00341     vil_load_image_resource(nitf_image_path.c_str());
00342   if (!image)
00343   {
00344     vcl_cout << "Image load failed in vpgl_nitf_rational_camera_constructor\n";
00345     return ;
00346   }
00347   vcl_string format = image->file_format();
00348   vcl_string prefix = format.substr(0,4);
00349   if (prefix != "nitf")
00350   {
00351     vcl_cout << "not a nitf image in vpgl_nitf_rational_camera_constructor\n";
00352     return;
00353   }
00354   //cast to an nitf2_image
00355   vil_nitf2_image* nitf_image = (vil_nitf2_image*)image.ptr();
00356   //Get and set the information
00357   if (!this->init(nitf_image, verbose))
00358     return;
00359   vpgl_scale_offset<double> z = scale_offsets_[Z_INDX];
00360   double z_off = z.offset();
00361   if (verbose)
00362   {
00363     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;
00364     // Project upper left corner
00365     this->project(ul_[LON], ul_[LAT], z_off, ul_u, ul_v);
00366     vcl_cout << "Upper left image corner(" << ul_u << ' ' << ul_v << ")\n";
00367     // Project upper right corner
00368     this->project(ur_[LON], ur_[LAT], z_off, ur_u, ur_v);
00369     vcl_cout << "Upper right image corner(" << ur_u << ' ' << ur_v << ")\n";
00370     // Project lower left corner
00371     this->project(ll_[LON], ll_[LAT], z_off, ll_u, ll_v);
00372     vcl_cout << "Lower left image corner(" << ll_u << ' ' << ll_v << ")\n";
00373     // Project lower right corner
00374     this->project(lr_[LON], lr_[LAT], z_off, lr_u, lr_v);
00375     vcl_cout << "Lower right image corner(" << lr_u << ' ' << lr_v << ")\n";
00376   }
00377 }
00378 
00379 vpgl_nitf_rational_camera::
00380 vpgl_nitf_rational_camera(vil_nitf2_image* nitf_image, bool verbose)
00381 {
00382   //Get and set the information
00383   if (!this->init(nitf_image, verbose))
00384     return;
00385 
00386   if (verbose)
00387     vcl_cout << *this;
00388   vpgl_scale_offset<double> z = scale_offsets_[Z_INDX];
00389   double z_off = z.offset();
00390   if (verbose)
00391   {
00392     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;
00393     // Project upper left corner
00394     this->project(ul_[LON], ul_[LAT], z_off, ul_u, ul_v);
00395     vcl_cout << "Upper left image corner(" << ul_u << ' ' << ul_v << ")\n";
00396     // Project upper right corner
00397     this->project(ur_[LON], ur_[LAT], z_off, ur_u, ur_v);
00398     vcl_cout << "Upper right image corner(" << ur_u << ' ' << ur_v << ")\n";
00399     // Project lower left corner
00400     this->project(ll_[LON], ll_[LAT], z_off, ll_u, ll_v);
00401     vcl_cout << "Lower left image corner(" << ll_u << ' ' << ll_v << ")\n";
00402     // Project lower right corner
00403     this->project(lr_[LON], lr_[LAT], z_off, lr_u, lr_v);
00404     vcl_cout << "Lower right image corner(" << lr_u << ' ' << lr_v << ")\n";
00405   }
00406 }
00407 
00408