core/vpgl/vpgl_rational_camera.txx
Go to the documentation of this file.
00001 // This is core/vpgl/vpgl_rational_camera.txx
00002 #ifndef vpgl_rational_camera_txx_
00003 #define vpgl_rational_camera_txx_
00004 //:
00005 // \file
00006 
00007 #include "vpgl_rational_camera.h"
00008 #include <vcl_vector.txx>
00009 #include <vcl_fstream.h>
00010 #include <vsl/vsl_binary_io.h>
00011 //#include <vnl/io/vnl_io_matrix_fixed.h>
00012 #include <vgl/vgl_point_2d.h>
00013 #include <vgl/vgl_point_3d.h>
00014 //--------------------------------------
00015 // Constructors
00016 //
00017 
00018 // Create an identity projection, i.e. (x,y) identically maps to (u,v)
00019 template <class T>
00020 vpgl_rational_camera<T>::vpgl_rational_camera()
00021 {
00022   rational_coeffs_.fill(0);
00023   rational_coeffs_[DEN_U][19]=1;
00024   rational_coeffs_[DEN_V][19]=1;
00025   rational_coeffs_[NEU_U][9]=1; // x coefficient
00026   rational_coeffs_[NEU_V][15]=1;// y coefficient
00027   vpgl_scale_offset<T> soff;
00028   scale_offsets_.resize(5, soff);
00029 }
00030 
00031 //: Constructor with an array encoding of the coefficients
00032 template <class T>
00033 vpgl_rational_camera<T>::
00034 vpgl_rational_camera(vcl_vector<vcl_vector<T> > const& rational_coeffs,
00035                      vcl_vector<vpgl_scale_offset<T> > const& scale_offsets)
00036 {
00037   this->set_coefficients(rational_coeffs);
00038   this->set_scale_offsets(scale_offsets);
00039 }
00040 
00041 template <class T>
00042 vpgl_rational_camera<T>::
00043 vpgl_rational_camera(vcl_vector<T> const& neu_u,
00044                      vcl_vector<T> const& den_u,
00045                      vcl_vector<T> const& neu_v,
00046                      vcl_vector<T> const& den_v,
00047                      const T x_scale, const T x_off,
00048                      const T y_scale, const T y_off,
00049                      const T z_scale, const T z_off,
00050                      const T u_scale, const T u_off,
00051                      const T v_scale, const T v_off
00052                     )
00053 {
00054   for (unsigned i = 0; i<20; ++i)
00055   {
00056     rational_coeffs_[NEU_U][i] = neu_u[i];
00057     rational_coeffs_[DEN_U][i] = den_u[i];
00058     rational_coeffs_[NEU_V][i] = neu_v[i];
00059     rational_coeffs_[DEN_V][i] = den_v[i];
00060   }
00061   scale_offsets_.resize(5);
00062   scale_offsets_[X_INDX] = vpgl_scale_offset<T>(x_scale, x_off);
00063   scale_offsets_[Y_INDX] = vpgl_scale_offset<T>(y_scale, y_off);
00064   scale_offsets_[Z_INDX] = vpgl_scale_offset<T>(z_scale, z_off);
00065   scale_offsets_[U_INDX] = vpgl_scale_offset<T>(u_scale, u_off);
00066   scale_offsets_[V_INDX] = vpgl_scale_offset<T>(v_scale, v_off);
00067 }
00068 
00069 //: Constructor from 4 coefficient arrays and 5 scale, offset pairs.
00070 template <class T>
00071 vpgl_rational_camera<T>::
00072 vpgl_rational_camera(const double*  neu_u,
00073                      const double* den_u,
00074                      const double* neu_v,
00075                      const double* den_v,
00076                      const T x_scale, const T x_off,
00077                      const T y_scale, const T y_off,
00078                      const T z_scale, const T z_off,
00079                      const T u_scale, const T u_off,
00080                      const T v_scale, const T v_off
00081                     )
00082 {
00083   for (unsigned i = 0; i<20; ++i)
00084   {
00085     rational_coeffs_[NEU_U][i] = T(neu_u[i]);
00086     rational_coeffs_[DEN_U][i] = T(den_u[i]);
00087     rational_coeffs_[NEU_V][i] = T(neu_v[i]);
00088     rational_coeffs_[DEN_V][i] = T(den_v[i]);
00089   }
00090   scale_offsets_.resize(5);
00091   scale_offsets_[X_INDX] = vpgl_scale_offset<T>(x_scale, x_off);
00092   scale_offsets_[Y_INDX] = vpgl_scale_offset<T>(y_scale, y_off);
00093   scale_offsets_[Z_INDX] = vpgl_scale_offset<T>(z_scale, z_off);
00094   scale_offsets_[U_INDX] = vpgl_scale_offset<T>(u_scale, u_off);
00095   scale_offsets_[V_INDX] = vpgl_scale_offset<T>(v_scale, v_off);
00096 }
00097 
00098 template <class T>
00099 vpgl_rational_camera<T>* vpgl_rational_camera<T>::clone(void) const
00100 {
00101   return new vpgl_rational_camera<T>(*this);
00102 }
00103 
00104 template <class T>
00105 void vpgl_rational_camera<T>::
00106 set_coefficients(vcl_vector<vcl_vector<T> > const& rational_coeffs)
00107 {
00108   for (unsigned j = 0; j<4; ++j)
00109     for (unsigned i = 0; i<20; ++i)
00110       rational_coeffs_[j][i] = rational_coeffs[j][i];
00111 }
00112 
00113 template <class T>
00114 void vpgl_rational_camera<T>::
00115 set_scale_offsets(vcl_vector<vpgl_scale_offset<T> > const& scale_offsets)
00116 {
00117   scale_offsets_=scale_offsets;
00118 }
00119 
00120 template <class T>
00121 vcl_vector<vcl_vector<T> > vpgl_rational_camera<T>::coefficients() const
00122 {
00123   vcl_vector<vcl_vector<T> > result(4);
00124   for (unsigned j = 0; j<4; ++j)
00125   {
00126     result[j].resize(20);
00127     for (unsigned i = 0; i<20; ++i)
00128       result[j][i]=rational_coeffs_[j][i];
00129   }
00130   return result;
00131 }
00132 
00133 //: Create a vector with the standard order of monomial terms
00134 template <class T>
00135 vnl_vector_fixed<T, 20>
00136 vpgl_rational_camera<T>::power_vector(const T x, const T y, const T z) const
00137 {
00138   // Form the monomials in homogeneous form
00139   double w  = 1;
00140   double xx = x*x;
00141   double xy = x*y;
00142   double xz = x*z;
00143   double yy = y*y;
00144   double yz = y*z;
00145   double zz = z*z;
00146   double xxx = x*xx;
00147   double xxy = x*xy;
00148   double xxz = x*xz;
00149   double xyy = x*yy;
00150   double xyz = x*yz;
00151   double xzz = x*zz;
00152   double yyy = y*yy;
00153   double yyz = y*yz;
00154   double yzz = y*zz;
00155   double zzz = z*zz;
00156   double xww = x*w*w;
00157   double yww = y*w*w;
00158   double zww = z*w*w;
00159   double www = w*w*w;
00160   double xxw = xx*w;
00161   double xyw = xy*w;
00162   double xzw = xz*w;
00163   double yyw = yy*w;
00164   double yzw = yz*w;
00165   double zzw = zz*w;
00166 
00167   //fill the vector
00168   vnl_vector_fixed<T, 20> pv;
00169   pv.put( 0, T(xxx));
00170   pv.put( 1, T(xxy));
00171   pv.put( 2, T(xxz));
00172   pv.put( 3, T(xxw));
00173   pv.put( 4, T(xyy));
00174   pv.put( 5, T(xyz));
00175   pv.put( 6, T(xyw));
00176   pv.put( 7, T(xzz));
00177   pv.put( 8, T(xzw));
00178   pv.put( 9, T(xww));
00179   pv.put(10, T(yyy));
00180   pv.put(11, T(yyz));
00181   pv.put(12, T(yyw));
00182   pv.put(13, T(yzz));
00183   pv.put(14, T(yzw));
00184   pv.put(15, T(yww));
00185   pv.put(16, T(zzz));
00186   pv.put(17, T(zzw));
00187   pv.put(18, T(zww));
00188   pv.put(19, T(www));
00189   return pv;
00190 }
00191 
00192 // Base projection method
00193 template <class T>
00194 void vpgl_rational_camera<T>::project(const T x, const T y, const T z,
00195                                       T& u, T& v) const
00196 {
00197   // scale, offset the world point before projection
00198   T sx = scale_offsets_[X_INDX].normalize(x);
00199   T sy = scale_offsets_[Y_INDX].normalize(y);
00200   T sz = scale_offsets_[Z_INDX].normalize(z);
00201   vnl_vector_fixed<T, 4> polys = rational_coeffs_*power_vector(sx, sy, sz);
00202   T su = polys[NEU_U]/polys[DEN_U];
00203   T sv = polys[NEU_V]/polys[DEN_V];
00204   // unscale the resulting image coordinates
00205   u = scale_offsets_[U_INDX].un_normalize(su);
00206   v = scale_offsets_[V_INDX].un_normalize(sv);
00207 }
00208 
00209 //vnl interface methods
00210 template <class T>
00211 vnl_vector_fixed<T, 2>
00212 vpgl_rational_camera<T>::project(vnl_vector_fixed<T, 3> const& world_point)const
00213 {
00214   vnl_vector_fixed<T, 2> image_point;
00215   this->project(world_point[0], world_point[1], world_point[2],
00216                 image_point[0], image_point[1]);
00217   return image_point;
00218 }
00219 
00220 //vgl interface methods
00221 template <class T>
00222 vgl_point_2d<T> vpgl_rational_camera<T>::project(vgl_point_3d<T> world_point)const
00223 {
00224   T u = 0, v = 0;
00225   this->project(world_point.x(), world_point.y(), world_point.z(), u, v);
00226   return vgl_point_2d<T>(u, v);
00227 }
00228 
00229 //: print the camera parameters
00230 template <class T>
00231 void vpgl_rational_camera<T>::print(vcl_ostream& s) const
00232 {
00233   vpgl_scale_offset<T> sox = scale_offsets_[X_INDX];
00234   vpgl_scale_offset<T> soy = scale_offsets_[Y_INDX];
00235   vpgl_scale_offset<T> soz = scale_offsets_[Z_INDX];
00236   vpgl_scale_offset<T> sou = scale_offsets_[U_INDX];
00237   vpgl_scale_offset<T> sov = scale_offsets_[V_INDX];
00238 
00239   s << "vpgl_rational_camera:\n"
00240     << "------------------------\n"
00241     << "xoff = " << sox.offset()
00242     << "  yoff = " << soy.offset()
00243     << "  zoff = " << soz.offset() << '\n'
00244     << "xscale = " << sox.scale()
00245     << "  yscale = " << soy.scale()
00246     << "  zscale = " << soz.scale() << '\n'
00247 
00248     << "uoff = " << sou.offset()
00249     << "  voff = " << sov.offset() << '\n'
00250     << "uscale = " << sou.scale()
00251     << "  vscale = " << sov.scale() << "\n\n"
00252 
00253     << "U Numerator\n"
00254     << "[0] " << rational_coeffs_[0][0]
00255     << " [1] " << rational_coeffs_[0][1]
00256     << " [2] " << rational_coeffs_[0][2]
00257     << " [3] " << rational_coeffs_[0][3] <<'\n'
00258     << "[4] " << rational_coeffs_[0][4]
00259     << " [5] " << rational_coeffs_[0][5]
00260     << " [6] " << rational_coeffs_[0][6]
00261     << " [7] " << rational_coeffs_[0][7] <<'\n'
00262     << "[8] "  << rational_coeffs_[0][8]
00263     << " [9] " << rational_coeffs_[0][9]
00264     << " [10] " << rational_coeffs_[0][10]
00265     << " [11] " << rational_coeffs_[0][11] <<'\n'
00266     << "[12] " << rational_coeffs_[0][12]
00267     << " [13] " << rational_coeffs_[0][13]
00268     << " [14] " << rational_coeffs_[0][14]
00269     << " [15] "  << rational_coeffs_[0][15] <<'\n'
00270     << "[16] " << rational_coeffs_[0][16]
00271     << " [17] " << rational_coeffs_[0][17]
00272     << " [18] " << rational_coeffs_[0][18]
00273     << " [19] " << rational_coeffs_[0][19] <<"\n\n"
00274 
00275     << "U Denominator\n"
00276     << "[0] " << rational_coeffs_[1][0]
00277     << " [1] " << rational_coeffs_[1][1]
00278     << " [2] " << rational_coeffs_[1][2]
00279     << " [3] " << rational_coeffs_[1][3] <<'\n'
00280     << "[4] " << rational_coeffs_[1][4]
00281     << " [5] " << rational_coeffs_[1][5]
00282     << " [6] " << rational_coeffs_[1][6]
00283     << " [7] " << rational_coeffs_[1][7]  <<'\n'
00284     << "[8] " << rational_coeffs_[1][8]
00285     << " [9] " << rational_coeffs_[1][9]
00286     << " [10] " << rational_coeffs_[1][10]
00287     << " [11] " << rational_coeffs_[1][11] <<'\n'
00288     << "[12] " << rational_coeffs_[1][12]
00289     << " [13] " << rational_coeffs_[1][13]
00290     << " [14] " << rational_coeffs_[1][14]
00291     << " [15] " << rational_coeffs_[1][15] <<'\n'
00292     << "[16] " << rational_coeffs_[1][16]
00293     << " [17] " << rational_coeffs_[1][17]
00294     << " [18] " << rational_coeffs_[1][18]
00295     << " [19] " << rational_coeffs_[1][19] <<"\n\n"
00296 
00297     << "V Numerator\n"
00298     << "[0] " << rational_coeffs_[2][0]
00299     << " [1] " << rational_coeffs_[2][1]
00300     << " [2] " << rational_coeffs_[2][2]
00301     << " [3] " << rational_coeffs_[2][3]<<'\n'
00302     << "[4] " << rational_coeffs_[2][4]
00303     << " [5] " << rational_coeffs_[2][5]
00304     << " [6] " << rational_coeffs_[2][6]
00305     << " [7] " << rational_coeffs_[2][7] <<'\n'
00306     << "[8] " << rational_coeffs_[2][8]
00307     << " [9] " << rational_coeffs_[2][9]
00308     << " [10] " << rational_coeffs_[2][10]
00309     << " [11] " << rational_coeffs_[2][11] <<'\n'
00310     << "[12] " << rational_coeffs_[2][12]
00311     << " [13] " << rational_coeffs_[2][13]
00312     << " [14] " << rational_coeffs_[2][14]
00313     << " [15] " << rational_coeffs_[2][15]<<'\n'
00314     << "[16] " << rational_coeffs_[2][16]
00315     << " [17] " << rational_coeffs_[2][17]
00316     << " [18] " << rational_coeffs_[2][18]
00317     << " [19] " << rational_coeffs_[2][19] <<"\n\n"
00318 
00319     << "V Denominator\n"
00320     << "[0] " << rational_coeffs_[3][0]
00321     << " [1] " << rational_coeffs_[3][1]
00322     << " [2] " << rational_coeffs_[3][2]
00323     << " [3] " << rational_coeffs_[3][3]<<'\n'
00324     << "[4] " << rational_coeffs_[3][4]
00325     << " [5] " << rational_coeffs_[3][5]
00326     << " [6] " << rational_coeffs_[3][6]
00327     << " [7] " << rational_coeffs_[3][7] <<'\n'
00328     << "[8] " << rational_coeffs_[3][8]
00329     << " [9] " << rational_coeffs_[3][9]
00330     << " [10] " << rational_coeffs_[3][10]
00331     << " [11] " << rational_coeffs_[3][11] <<'\n'
00332     << "[12] " << rational_coeffs_[3][12]
00333     << " [13] " << rational_coeffs_[3][13]
00334     << " [14] " << rational_coeffs_[3][14]
00335     << " [15] " << rational_coeffs_[3][15]<<'\n'
00336     << "[16] " << rational_coeffs_[3][16]
00337     << " [17] " << rational_coeffs_[3][17]
00338     << " [18] " << rational_coeffs_[3][18]
00339     << " [19] " << rational_coeffs_[3][19] <<'\n'
00340     <<"------------------------------------------------\n\n";
00341 }
00342 
00343 template <class T>
00344 bool vpgl_rational_camera<T>::save(vcl_string cam_path)
00345 {
00346   vcl_ofstream file_out;
00347   file_out.open(cam_path.c_str());
00348   if (!file_out.good()) {
00349     vcl_cerr << "error: bad filename: " << cam_path << vcl_endl;
00350     return false;
00351   }
00352   file_out.precision(12);
00353 
00354   int map[20];
00355   map[0]=19;
00356   map[1]=9;
00357   map[2]=15;
00358   map[3]=18;
00359   map[4]=6;
00360   map[5]=8;
00361   map[6]=14;
00362   map[7]=3;
00363   map[8]=12;
00364   map[9]=17;
00365   map[10]=5;
00366   map[11]=0;
00367   map[12]=4;
00368   map[13]=7;
00369   map[14]=1;
00370   map[15]=10;
00371   map[16]=13;
00372   map[17]=2;
00373   map[18]=11;
00374   map[19]=16;
00375 
00376   file_out << "satId = \"????\";\n"
00377            << "bandId = \"RGB\";\n"
00378            << "SpecId = \"RPC00B\";\n"
00379            << "BEGIN_GROUP = IMAGE\n"
00380            << "\n\n"  // skip errBias and errRand fields
00381            << "  lineOffset = " << offset(V_INDX) << '\n'
00382            << "  sampOffset = " << offset(U_INDX) << '\n'
00383            << "  latOffset = " << offset(Y_INDX) << '\n'
00384            << "  longOffset = " << offset(X_INDX) << '\n'
00385            << "  heightOffset = " << offset(Z_INDX) << '\n'
00386            << "  lineScale = " << scale(V_INDX) << '\n'
00387            << "  sampScale = " << scale(U_INDX) << '\n'
00388            << "  latScale = " << scale(Y_INDX) << '\n'
00389            << "  longScale = " << scale(X_INDX) << '\n'
00390            << "  heightScale = " << scale(Z_INDX) << '\n';
00391   vnl_matrix_fixed<T,4,20> coeffs = this->coefficient_matrix();
00392   file_out << "  lineNumCoef = (";
00393   for (int i=0; i<20; i++) {
00394     file_out << "\n    " << coeffs[NEU_V][map[i]];
00395     if (i < 19)
00396       file_out << ',';
00397   }
00398   file_out << ");\n  lineDenCoef = (";
00399   for (int i=0; i<20; i++) {
00400     file_out << "\n    " << coeffs[DEN_V][map[i]];
00401     if (i < 19)
00402       file_out << ',';
00403   }
00404   file_out << ");\n  sampNumCoef = (";
00405   for (int i=0; i<20; i++) {
00406     file_out << "\n    " << coeffs[NEU_U][map[i]];
00407     if (i < 19)
00408       file_out << ',';
00409   }
00410   file_out << ");\n  sampDenCoef = (";
00411   for (int i=0; i<20; i++) {
00412     file_out << "\n    " << coeffs[DEN_U][map[i]];
00413     if (i < 19)
00414       file_out << ',';
00415   }
00416   file_out << ");\n"
00417            << "END_GROUP = IMAGE\n"
00418            << "END;\n";
00419 
00420   return true;
00421 }
00422 
00423 //: Write to stream
00424 template <class T>
00425 vcl_ostream&  operator<<(vcl_ostream& s, const vpgl_rational_camera<T >& c )
00426 {
00427   c.print(s);
00428   return s;
00429 }
00430 
00431 //: read from a file
00432 template <class T>
00433 vpgl_rational_camera<T>* read_rational_camera(vcl_string cam_path)
00434 {
00435   vcl_ifstream file_inp;
00436   file_inp.open(cam_path.c_str());
00437   if (!file_inp.good()) {
00438     vcl_cout << "error: bad filename: " << cam_path << vcl_endl;
00439     return 0;
00440   }
00441   vpgl_rational_camera<T>* rcam = read_rational_camera<T>(file_inp);
00442   file_inp.close();
00443   return rcam;
00444 }
00445 //: read from an open istream
00446 template <class T>
00447 vpgl_rational_camera<T>* read_rational_camera(vcl_istream& istr)
00448 {
00449   vcl_vector<T> neu_u;
00450   vcl_vector<T> den_u;
00451   vcl_vector<T> neu_v;
00452   vcl_vector<T> den_v;
00453   T x_scale,x_off,y_scale,y_off,z_scale,z_off,u_scale,u_off,v_scale,v_off;
00454 
00455   vcl_string input;
00456   char bulk[100];
00457 
00458   while (!istr.eof()) {
00459     istr >> input;
00460 
00461     if (input=="sampScale") {
00462       istr >> input;
00463       istr >> u_scale;
00464     }
00465     if (input=="sampOffset") {
00466       istr >> input;
00467       istr >> u_off;
00468     }
00469 
00470     if (input=="lineScale") {
00471       istr >> input;
00472       istr >> v_scale;
00473     }
00474     if (input=="lineOffset") {
00475       istr >> input;
00476       istr >> v_off;
00477     }
00478 
00479     if (input=="longScale") {
00480       istr >> input;
00481       istr >> x_scale;
00482     }
00483     if (input=="longOffset") {
00484       istr >> input;
00485       istr >> x_off;
00486     }
00487 
00488     if (input=="latScale") {
00489       istr >> input;
00490       istr >> y_scale;
00491     }
00492     if (input=="latOffset") {
00493       istr >> input;
00494       istr >> y_off;
00495     }
00496 
00497     if (input=="heightScale") {
00498       istr >> input;
00499       istr >> z_scale;
00500     }
00501     if (input=="heightOffset") {
00502       istr >> input;
00503       istr >> z_off;
00504     }
00505 
00506     T temp_dbl;
00507     if (input=="lineNumCoef") {
00508       istr >> input;
00509       istr >> input;
00510       for (int i=0; i<20; i++) {
00511         istr >> temp_dbl;
00512         neu_v.push_back(temp_dbl);
00513         istr.getline(bulk,200);
00514       }
00515     }
00516 
00517     if (input=="lineDenCoef") {
00518       istr >> input;
00519       istr >> input;
00520       for (int i=0; i<20; i++) {
00521         istr >> temp_dbl;
00522         den_v.push_back(temp_dbl);
00523         istr.getline(bulk,200);
00524       }
00525     }
00526 
00527     if (input=="sampNumCoef") {
00528       istr >> input;
00529       istr >> input;
00530       for (int i=0; i<20; i++) {
00531         istr >> temp_dbl;
00532         neu_u.push_back(temp_dbl);
00533         istr.getline(bulk,200);
00534       }
00535     }
00536 
00537     if (input=="sampDenCoef") {
00538       istr >> input;
00539       istr >> input;
00540       for (int i=0; i<20; i++) {
00541         istr >> temp_dbl;
00542         den_u.push_back(temp_dbl);
00543         istr.getline(bulk,200);
00544       }
00545       break;
00546     }
00547   }
00548   istr >> input;
00549   if (input!="END_GROUP")
00550     return 0;
00551   istr >> input;
00552   if (input!="=")
00553     return 0;
00554   istr >> input;
00555   if (input!="IMAGE")
00556     return 0;
00557   istr >> input;
00558   if (input!="END;")
00559     return 0;
00560   int map[20];
00561   map[0]=19;
00562   map[1]=9;
00563   map[2]=15;
00564   map[3]=18;
00565   map[4]=6;
00566   map[5]=8;
00567   map[6]=14;
00568   map[7]=3;
00569   map[8]=12;
00570   map[9]=17;
00571   map[10]=5;
00572   map[11]=0;
00573   map[12]=4;
00574   map[13]=7;
00575   map[14]=1;
00576   map[15]=10;
00577   map[16]=13;
00578   map[17]=2;
00579   map[18]=11;
00580   map[19]=16;
00581 
00582   if ((neu_u.size() != 20) || (den_u.size() != 20)) {
00583     vcl_cerr << "the input is not a valid rational camera\n";
00584     return 0;
00585   }
00586 
00587   T temp_vector[20];
00588   for (int j=0; j<20; j++) {
00589     temp_vector[j] = neu_u[j];
00590   }
00591   for (int j=0; j<20; j++) {
00592     neu_u[map[j]] = temp_vector[j];
00593   }
00594   for (int j=0; j<20; j++) {
00595     temp_vector[j] = den_u[j];
00596   }
00597   for (int j=0; j<20; j++) {
00598     den_u[map[j]] = temp_vector[j];
00599   }
00600   for (int j=0; j<20; j++) {
00601     temp_vector[j] = neu_v[j];
00602   }
00603   for (int j=0; j<20; j++) {
00604     neu_v[map[j]] = temp_vector[j];
00605   }
00606   for (int j=0; j<20; j++) {
00607     temp_vector[j] = den_v[j];
00608   }
00609   for (int j=0; j<20; j++) {
00610     den_v[map[j]] = temp_vector[j];
00611   }
00612 
00613   vpgl_rational_camera<T>* cam = new vpgl_rational_camera<T>(neu_u, den_u, neu_v, den_v,
00614                                                              x_scale, x_off, y_scale, y_off, z_scale, z_off,
00615                                                              u_scale, u_off, v_scale, v_off);
00616   return cam;
00617 }
00618 
00619 //: Read from stream
00620 template <class T>
00621 vcl_istream&  operator >>(vcl_istream& s, vpgl_rational_camera<T >& c )
00622 {
00623   vpgl_rational_camera<T>* cptr = read_rational_camera<T>(s);
00624   c = *cptr;
00625   return s;
00626 }
00627 
00628 // Code for easy instantiation.
00629 #undef vpgl_RATIONAL_CAMERA_INSTANTIATE
00630 #define vpgl_RATIONAL_CAMERA_INSTANTIATE(T) \
00631 template class vpgl_scale_offset<T >; \
00632 template class vpgl_rational_camera<T >; \
00633 template vcl_ostream& operator<<(vcl_ostream&, const vpgl_rational_camera<T >&); \
00634 template vcl_istream& operator>>(vcl_istream&, vpgl_rational_camera<T >&); \
00635 template vpgl_rational_camera<T > * read_rational_camera(vcl_string); \
00636 template vpgl_rational_camera<T > * read_rational_camera(vcl_istream&); \
00637 typedef vpgl_scale_offset<T > soff; \
00638 VCL_VECTOR_INSTANTIATE(soff)
00639 
00640 
00641 #endif // vpgl_rational_camera_txx_