00001
00002 #include "vpgl_geo_camera.h"
00003
00004
00005
00006 #include <vcl_vector.h>
00007 #include <vcl_cassert.h>
00008
00009 #include <vnl/vnl_vector.h>
00010 #include <vnl/vnl_inverse.h>
00011
00012 #include <vpgl/bgeo/bgeo_lvcs.h>
00013 #include <vpgl/bgeo/bgeo_utm.h>
00014
00015 vpgl_geo_camera::vpgl_geo_camera()
00016 {
00017 trans_matrix_.set_size(4,4);
00018 trans_matrix_.fill(0);
00019 trans_matrix_.fill_diagonal(1);
00020 is_utm = false;
00021 scale_tag_ = false;
00022 }
00023
00024 vpgl_geo_camera::vpgl_geo_camera(vpgl_geo_camera const& rhs)
00025 {
00026 this->trans_matrix_ = rhs.trans_matrix_;
00027 this->lvcs_ = new bgeo_lvcs(*(rhs.lvcs_));
00028 this->is_utm = rhs.is_utm;
00029 this->utm_zone_ = rhs.utm_zone_;
00030 this->scale_tag_ = rhs.scale_tag_;
00031 }
00032
00033 bool vpgl_geo_camera::init_geo_camera(vil_tiff_image* const& gtif_img,
00034 bgeo_lvcs_sptr lvcs,
00035 vpgl_geo_camera*& camera)
00036 {
00037
00038 if (!gtif_img->is_GEOTIFF()) {
00039 vcl_cout << "vpgl_geo_camera::init_geo_camera -- The image should be a GEOTIFF!\n";
00040 return false;
00041 }
00042
00043 vil_geotiff_header* gtif = gtif_img->get_geotiff_header();
00044 int utm_zone;
00045 vil_geotiff_header::GTIF_HEMISPH h;
00046
00047
00048
00049
00050
00051 bool is_utm = false;
00052 if (gtif->PCS_WGS84_UTM_zone(utm_zone, h))
00053 {
00054 vcl_vector<vcl_vector<double> > tiepoints;
00055 gtif->gtif_tiepoints(tiepoints);
00056 is_utm = true;
00057 #if 0 // I, J, K should not be transformed
00058
00059 bgeo_utm utm;
00060
00061 bool south_flag = (h == 1);
00062 for (unsigned i=0; i< tiepoints.size(); i++) {
00063 assert (tiepoints[i].size() == 6);
00064 double I = tiepoints[i][0];
00065 double J = tiepoints[i][1];
00066 double K = tiepoints[i][2];
00067 double X = tiepoints[i][3];
00068 double Y = tiepoints[i][4];
00069 double Z = tiepoints[i][5];
00070
00071 utm.transform(utm_zone, X, Y, Z, I, J, K, south_flag );
00072 if (!lvcs) {
00073 lvcs = new bgeo_lvcs(I,J,K);
00074 tiepoints[i][0] = I;
00075 tiepoints[i][1] = J;
00076 tiepoints[i][2] = K;
00077 }
00078 }
00079 #endif
00080
00081
00082 vnl_matrix<double> trans_matrix;
00083 double* trans_matrix_values;
00084 double sx1, sy1, sz1;
00085 bool scale_tag=false;
00086 if (gtif->gtif_trans_matrix(trans_matrix_values)){
00087 vcl_cout << "Transfer matrix is given, using that...." << vcl_endl;
00088 trans_matrix.copy_in(trans_matrix_values);
00089 vcl_cout << "Warning LIDAR sample spacing different than 1 meter will not be handled correctly!\n";
00090 } else if (gtif->gtif_pixelscale(sx1, sy1, sz1)) {
00091 scale_tag = true;
00092 vpgl_geo_camera::comp_trans_matrix(sx1, sy1, sz1, tiepoints,
00093 trans_matrix, scale_tag);
00094 } else {
00095 vcl_cout << "vpgl_geo_camera::init_geo_camera comp_trans_matrix -- Transform matrix cannot be formed..\n";
00096 return false;
00097 }
00098
00099
00100
00101 camera = new vpgl_geo_camera(trans_matrix, lvcs, tiepoints);
00102 if (is_utm)
00103 camera->set_utm(utm_zone, h);
00104 camera->set_scale_format(scale_tag);
00105 return true;
00106 } else {
00107 vcl_cout << "bmdl_lidar_roi_process::lidar_init()-- Only ProjectedCSTypeGeoKey=PCS_WGS84_UTM_zoneXX_X is defined rigth now, please define yours!!" << vcl_endl;
00108 return false;
00109 }
00110 }
00111
00112
00113 void vpgl_geo_camera::project(const double x, const double y, const double z,
00114 double& u, double& v) const
00115 {
00116 vnl_vector<double> vec(4), res(4);
00117 double lat, lon, gz;
00118
00119 if (lvcs_)
00120 lvcs_->local_to_global(x, y, z, bgeo_lvcs::wgs84, lon, lat, gz);
00121 else {
00122 lat = y;
00123 lon = x;
00124 }
00125
00126 double x1=lon, y1=lat, z1=gz;
00127 if (is_utm) {
00128 bgeo_utm utm;
00129 int utm_zone;
00130 utm.transform(lat, lon, x1, y1, utm_zone);
00131 z1 = 0;
00132 }
00133 vec[0] = x1;
00134 vec[1] = y1;
00135 vec[2] = z1;
00136 vec[3] = 1;
00137
00138
00139 vnl_matrix<double> tm(trans_matrix_);
00140 tm[2][2] = 1;
00141
00142 vnl_matrix<double> trans_matrix_inv = vnl_inverse(tm);
00143 res = trans_matrix_inv*vec;
00144 u = res[0];
00145 v = res[1];
00146 }
00147
00148
00149 void vpgl_geo_camera::backproject(const double u, const double v,
00150 double& x, double& y, double& z)
00151 {
00152 vnl_vector<double> vec(4), res(4);
00153 vec[0] = trans_matrix_[0][3] + u;
00154 vec[1] = trans_matrix_[1][3] - v;
00155 vec[2] = 0;
00156 vec[3] = 1;
00157
00158 double lat, lon, elev;
00159 if (is_utm) {
00160
00161 bgeo_utm utm;
00162 utm.transform(utm_zone_, vec[0], vec[1], vec[2], lat, lon, elev);
00163 } else {
00164 lat = vec[0];
00165 lon = vec[1];
00166 elev = vec[2];
00167 }
00168
00169 if (lvcs_)
00170 lvcs_->global_to_local(lon, lat, elev, bgeo_lvcs::wgs84, x, y, z);
00171 }
00172
00173 void vpgl_geo_camera::translate(double tx, double ty, double z)
00174 {
00175
00176 if (scale_tag_) {
00177 trans_matrix_[0][3] += tx*trans_matrix_[0][0];
00178 trans_matrix_[1][3] -= ty*(-1.0*trans_matrix_[1][1]);
00179 } else {
00180 vcl_cout << "Warning! Translation offset will only be computed correctly for lidar pixel spacing = 1 meter\n";
00181 trans_matrix_[0][3] += tx;
00182 trans_matrix_[1][3] -= ty;
00183 }
00184 }
00185
00186 void vpgl_geo_camera::img_to_wgs(const unsigned i, const unsigned j, const unsigned z,
00187 double& lon, double& lat, double& elev)
00188 {
00189 vnl_vector<double> v(4), res(4);
00190 v[0] = trans_matrix_[0][3] + i;
00191 v[1] = trans_matrix_[1][3] - j;
00192 v[2] = z;
00193 v[3] = 1;
00194
00195 bgeo_utm utm;
00196 utm.transform(utm_zone_, v[0], v[1], v[2], lat, lon, elev);
00197 }
00198
00199 bool vpgl_geo_camera::operator==(vpgl_geo_camera const& rhs) const
00200 {
00201 return this->trans_matrix_ == rhs.trans_matrix_ &&
00202 *(this->lvcs_) == *(rhs.lvcs_);
00203 }
00204
00205
00206 vcl_ostream& operator<<(vcl_ostream& s,
00207 vpgl_geo_camera const& p)
00208 {
00209 s << p.trans_matrix_ << '\n'<< *(p.lvcs_) << '\n';
00210
00211 return s ;
00212 }
00213
00214
00215 vcl_istream& operator>>(vcl_istream& s,
00216 vpgl_geo_camera& p)
00217 {
00218 vnl_matrix_fixed<double,4,4> tr_matrix;
00219 s >> tr_matrix;
00220
00221
00222 vcl_vector<vcl_vector<double> > tiepoints(1);
00223 double t0, t1, t2, t3, t4, t5;
00224 s >> t0 >> t1 >> t2 >> t3 >> t4 >> t5;
00225 tiepoints[0].resize(6);
00226 tiepoints[0][0] = t0;
00227 tiepoints[0][1] = t1;
00228 tiepoints[0][2] = t2;
00229 tiepoints[0][3] = t3;
00230 tiepoints[0][4] = t4;
00231 tiepoints[0][5] = t5;
00232
00233 bgeo_lvcs_sptr lvcs = new bgeo_lvcs();
00234 s >> (*lvcs);
00235 p = vpgl_geo_camera(tr_matrix, lvcs, tiepoints);
00236 return s ;
00237 }
00238
00239 bool vpgl_geo_camera::comp_trans_matrix(double sx1, double sy1, double sz1,
00240 vcl_vector<vcl_vector<double> > tiepoints,
00241 vnl_matrix<double>& trans_matrix,
00242 bool scale_tag)
00243 {
00244
00245
00246 assert (tiepoints.size() > 0);
00247 assert (tiepoints[0].size() == 6);
00248 double I = tiepoints[0][0];
00249 double J = tiepoints[0][1];
00250 double K = tiepoints[0][2];
00251 double X = tiepoints[0][3];
00252 double Y = tiepoints[0][4];
00253 double Z = tiepoints[0][5];
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 double sx = 1.0, sy = 1.0, sz = 1.0;
00267 if (scale_tag){
00268 sx = sx1; sy = sy1; sz = sz1;
00269 }
00270 double Tx = X - I*sx;
00271 double Ty = Y + J*sy;
00272 double Tz = Z - K*sz;
00273
00274 vnl_matrix<double> m(4,4);
00275 m.fill(0.0);
00276 m[0][0] = sx;
00277 m[1][1] = -1*sy;
00278 m[2][2] = sz;
00279 m[3][3] = 1.0;
00280 m[0][3] = Tx;
00281 m[1][3] = Ty;
00282 m[2][3] = Tz;
00283 trans_matrix = m;
00284 vcl_cout << trans_matrix << vcl_endl;
00285 return true;
00286 }
00287
00288
00289
00290
00291 void vpgl_geo_camera::b_read(vsl_b_istream &is)
00292 {
00293
00294 unsigned r,c;
00295 double v;
00296 vsl_b_read(is,r);
00297 vsl_b_read(is,c);
00298 trans_matrix_.set_size(r,c);
00299 for (unsigned i=0;r; i++) {
00300 for (unsigned j=0;c; i++) {
00301 vsl_b_read(is,v);
00302 trans_matrix_.put(i,j,v);
00303 }
00304 }
00305
00306
00307 lvcs_->b_read(is);
00308 vsl_b_read(is,is_utm);
00309 vsl_b_read(is,utm_zone_);
00310 vsl_b_read(is,northing_);
00311
00312 return;
00313 }
00314
00315
00316
00317 void vpgl_geo_camera::b_write(vsl_b_ostream &os) const
00318 {
00319
00320 vsl_b_write(os,trans_matrix_.rows());
00321 vsl_b_write(os,trans_matrix_.cols());
00322 for (unsigned i=0; trans_matrix_.rows(); i++)
00323 for (unsigned j=0; trans_matrix_.cols(); i++)
00324 vsl_b_write(os,trans_matrix_(i,j));
00325
00326 vsl_b_write(os,is_utm);
00327 vsl_b_write(os,utm_zone_);
00328 vsl_b_write(os,northing_);
00329 return;
00330 }
00331