vpgl_geo_camera.cxx
Go to the documentation of this file.
1 // This is core/vpgl/file_formats/vpgl_geo_camera.cxx
2 #include <vector>
3 #include "vpgl_geo_camera.h"
4 //:
5 // \file
6 
7 #ifdef _MSC_VER
8 # include <vcl_msvc_warnings.h>
9 #endif
10 #include <cassert>
11 
12 #include <vnl/vnl_vector.h>
13 #include <vnl/vnl_inverse.h>
14 
15 #include <vpgl/vpgl_lvcs.h>
16 #include <vpgl/vpgl_utm.h>
17 #include <vul/vul_file.h>
18 
19 #include <vil/file_formats/vil_geotiff_header.h>
20 #include <vil/file_formats/vil_tiff.h>
21 #include <vil/file_formats/vil_nitf2_image.h>
22 
24 {
28  is_utm = false;
29  scale_tag_ = false;
30 }
31 
33 : vpgl_camera<double>(rhs),
34  trans_matrix_(rhs.trans_matrix_),
35  lvcs_(new vpgl_lvcs(*(rhs.lvcs_))),
36  is_utm(rhs.is_utm),
37  utm_zone_(rhs.utm_zone_),
38  scale_tag_(rhs.scale_tag_)
39 {}
40 
41 bool vpgl_geo_camera::init_geo_camera(vil_image_resource_sptr const& geotiff_img,
42  const vpgl_lvcs_sptr& lvcs,
43  vpgl_geo_camera*& camera)
44 {
45  // check if the image is tiff
46  auto* geotiff_tiff = dynamic_cast<vil_tiff_image*> (geotiff_img.ptr());
47  if (!geotiff_tiff) {
48  std::cerr << "vpgl_geo_camera::init_geo_camera : Error casting vil_image_resource to a tiff image.\n";
49  return false;
50  }
51  if (!geotiff_tiff->get_geotiff_header()) {
52  std::cerr << "no geotiff header!\n";
53  return false;
54  }
55 
56  // check if the tiff file is geotiff
57  if (!geotiff_tiff->is_GEOTIFF()) {
58  std::cerr << "vpgl_geo_camera::init_geo_camera -- The image should be a GEOTIFF!\n";
59  return false;
60  }
61 
62  vil_geotiff_header* gtif = geotiff_tiff->get_geotiff_header();
63  int utm_zone;
64  vil_geotiff_header::GTIF_HEMISPH h;
65 
66  std::vector<std::vector<double> > tiepoints;
67  gtif->gtif_tiepoints(tiepoints);
68 
69  // create a transformation matrix
70  // if there is a transformation matrix in GEOTIFF, use that
72  double* trans_matrix_values;
73  double sx1, sy1, sz1;
74  bool scale_tag=false;
75  if (gtif->gtif_trans_matrix(trans_matrix_values)) {
76  std::cout << "Transfer matrix is given, using that...." << std::endl;
77  trans_matrix.copy_in(trans_matrix_values);
78  std::cout << "Warning LIDAR sample spacing different than 1 meter will not be handled correctly!\n";
79  }
80  else if (gtif->gtif_pixelscale(sx1, sy1, sz1)) {
81  scale_tag = true;
82  vpgl_geo_camera::comp_trans_matrix(sx1, sy1, sz1, tiepoints,
83  trans_matrix, scale_tag);
84  }
85  else {
86  std::cout << "vpgl_geo_camera::init_geo_camera comp_trans_matrix -- Transform matrix cannot be formed..\n";
87  return false;
88  }
89 
90  // create the camera
91  camera = new vpgl_geo_camera(trans_matrix, lvcs);
92  camera->set_scale_format(scale_tag);
93 
94  // check if the model type is geographic and also the units
95  if (gtif->GCS_WGS84_MET_DEG())
96  return true;
97 
98  // otherwise check if it is projected to UTM and figure out the zone
99  if (gtif->PCS_WGS84_UTM_zone(utm_zone, h) || gtif->PCS_NAD83_UTM_zone(utm_zone, h))
100  {
101  camera->set_utm(utm_zone, h);
102  return true;
103  }
104  else {
105  std::cout << "vpgl_geo_camera::init_geo_camera()-- if UTM only PCS_WGS84_UTM and PCS_NAD83_UTM, if geographic (GCS_WGS_84) only linear units in meters, angular units in degrees are supported, please define otherwise!" << std::endl;
106  return false;
107  }
108 }
109 
110 //: define a geo_camera by the image file name (filename should have format such as xxx_N35W73_S0.6x0.6_xxx.tif)
111 bool vpgl_geo_camera::init_geo_camera(const std::string& img_name, unsigned ni, unsigned nj, const vpgl_lvcs_sptr& lvcs, vpgl_geo_camera*& camera)
112 {
113  // determine the translation matrix from the image file name and construct a geo camera
114  std::string name = vul_file::strip_directory(img_name);
115  name = name.substr(name.find_first_of('_')+1, name.size());
116 
117  std::string n_coords = name.substr(0, name.find_first_of('_'));
118  std::string n_scale = name.substr(name.find_first_of('_')+1, name.find_last_of('_')-name.find_first_of('_')-1);
119  std::cout << "will determine transformation matrix from the file name: " << name << std::endl;
120 
121  // determine the lat, lon, hemisphere (North or South) and direction (East or West)
122  std::string hemisphere, direction;
123  float lon, lat, scale_lat, scale_lon;
124  std::size_t n = n_coords.find('N');
125  if (n < n_coords.size())
126  hemisphere = "N";
127  else
128  hemisphere = "S";
129  n = n_coords.find('E');
130  if (n < n_coords.size())
131  direction = "E";
132  else
133  direction = "W";
134 
135  std::string n_str = n_coords.substr(n_coords.find_first_of(hemisphere)+1, n_coords.find_first_of(direction)-n_coords.find_first_of(hemisphere)-1);
136  std::stringstream str(n_str); str >> lat;
137 
138  n_str = n_coords.substr(n_coords.find_first_of(direction)+1, n_coords.size());
139  std::stringstream str2(n_str); str2 >> lon;
140 
141  n_str = n_scale.substr(n_scale.find_first_of('S')+1, n_scale.find_first_of('x')-n_scale.find_first_of('S')-1);
142  std::stringstream str3(n_str); str3 >> scale_lat;
143 
144  n_str = n_scale.substr(n_scale.find_first_of('x')+1, n_scale.size());
145  std::stringstream str4(n_str); str4 >> scale_lon;
146 
147  std::cout << " hemisphere: " << hemisphere << " direction: " << direction
148  << "\n lat: " << lat << " lon: " << lon
149  << "\n scale_lat: " << scale_lat << " scale_lon: " << scale_lon << std::endl;
150 
151  // determine the upper left corner to use a vpgl_geo_cam, subtract from lat
152  if (hemisphere == "N")
153  std::cout << " upper left corner in the image is: " << hemisphere << lat+scale_lat << direction << lon << std::endl;
154  else
155  std::cout << " upper left corner in the image is: " << hemisphere << lat-scale_lat << direction << lon << std::endl;
156  if (direction == "W")
157  std::cout << " lower right corner in the image is: " << hemisphere << lat << direction << lon-scale_lon << std::endl;
158  else
159  std::cout << " lower right corner in the image is: " << hemisphere << lat << direction << lon+scale_lon << std::endl;
160  vnl_matrix<double> trans_matrix(4,4,0,nullptr);
161  //divide by ni-1 to account for 1 pixel overlap with the next tile
162  if (direction == "E") {
163  trans_matrix[0][3] = lon - 0.5/(ni-1.0);
164  trans_matrix[0][0] = scale_lon/(ni-1.0);
165  }
166  else {
167  trans_matrix[0][3] = lon + 0.5/(ni-1.0);
168  trans_matrix[0][0] = -scale_lon /(ni-1.0);
169  }
170  if (hemisphere == "N") {
171  trans_matrix[1][1] = -scale_lat/(nj-1.0);
172  trans_matrix[1][3] = lat + scale_lat + 0.5/(nj-1.0);
173  }
174  else {
175  trans_matrix[1][1] = scale_lat/(nj-1.0);
176  trans_matrix[1][3] = lat-scale_lat-0.5/(nj-1.0);
177  }
178  camera = new vpgl_geo_camera(trans_matrix, lvcs);
179  camera->set_scale_format(true);
180  return true;
181 
182 #if 0
183  std::string n = name.substr(name.find_first_of('N')+1, name.find_first_of('W'));
184  float lon, lat, scale;
185  std::stringstream str(n); str >> lat;
186  n = name.substr(name.find_first_of('W')+1, name.find_first_of('_'));
187  std::stringstream str2(n); str2 >> lon;
188  n = name.substr(name.find_first_of('x')+1, name.find_last_of('.'));
189  std::stringstream str3(n); str3 >> scale;
190  std::cout << " lat: " << lat << " lon: " << lon << " WARNING: using same scale for both ni and nj: scale:" << scale << std::endl;
191 
192  // determine the upper left corner to use a vpgl_geo_cam, subtract from lat
193  std::cout << "upper left corner in the image is: " << lat+scale << " N " << lon << " W\n"
194  << "lower right corner in the image is: " << lat << " N " << lon-scale << " W" << std::endl;
196  trans_matrix[0][0] = -scale/ni; trans_matrix[1][1] = -scale/nj;
197  trans_matrix[0][3] = lon; trans_matrix[1][3] = lat+scale;
198  camera = new vpgl_geo_camera(trans_matrix, lvcs);
199  camera->set_scale_format(true);
200  return true;
201 #endif
202 }
203 
204 // loads a geo_camera from the file and uses global WGS84 coordinates, so no need to convert negative values to positives in the global_to_img method as in the previous method
205 bool vpgl_geo_camera::init_geo_camera_from_filename(const std::string& img_name, unsigned ni, unsigned nj, const vpgl_lvcs_sptr& lvcs, vpgl_geo_camera*& camera)
206 {
207  // determine the translation matrix from the image file name and construct a geo camera
208  std::string name = vul_file::strip_directory(img_name);
209  name = name.substr(name.find_first_of('_')+1, name.size());
210 
211  std::string n_coords = name.substr(0, name.find_first_of('_'));
212  std::string n_scale = name.substr(name.find_first_of('_')+1, name.find_last_of('_')-name.find_first_of('_')-1);
213  std::cout << "will determine transformation matrix from the file name: " << name << std::endl;
214 
215  // determine the lat, lon, hemisphere (North or South) and direction (East or West)
216  std::string hemisphere, direction;
217  float lon, lat, scale;
218  std::size_t n = n_coords.find('N');
219  if (n < n_coords.size())
220  hemisphere = "N";
221  else
222  hemisphere = "S";
223  n = n_coords.find('E');
224  if (n < n_coords.size())
225  direction = "E";
226  else
227  direction = "W";
228 
229  std::string n_str = n_coords.substr(n_coords.find_first_of(hemisphere)+1, n_coords.find_first_of(direction)-n_coords.find_first_of(hemisphere)-1);
230  std::stringstream str(n_str); str >> lat;
231 
232  n_str = n_coords.substr(n_coords.find_first_of(direction)+1, n_coords.size());
233  std::stringstream str2(n_str); str2 >> lon;
234 
235  n_str = n_scale.substr(n_scale.find_first_of('S')+1, n_scale.find_first_of('x')-n_scale.find_first_of('S')-1);
236  std::stringstream str3(n_str); str3 >> scale;
237 
238  std::cout << " hemisphere: " << hemisphere << " direction: " << direction
239  << "\n lat: " << lat << " lon: " << lon
240  << "\n WARNING: using same scale for both ni and nj: " << scale << std::endl;
241 
242  // simply convert to global coords (i.e. lats for S are negative)
243  if (hemisphere == "S")
244  lat = -lat;
245  if (direction == "W")
246  lon = -lon;
247 
248  // determine the upper left corner to use a vpgl_geo_cam, subtract from lat
249  std::cout << " upper left corner in the image is: " << hemisphere << lat+scale << direction << lon << std::endl;
250  std::cout << " lower right corner in the image is: " << hemisphere << lat << direction << lon+scale << std::endl;
251 
252  vnl_matrix<double> trans_matrix(4,4,0,nullptr);
253  //divide by ni-1 to account for 1 pixel overlap with the next tile
254  trans_matrix[0][3] = lon - 0.5/(ni-1.0);
255  trans_matrix[0][0] = scale/(ni-1.0);
256  trans_matrix[1][1] = -scale/(nj-1.0);
257  trans_matrix[1][3] = lat + scale + 0.5/(nj-1.0);
258  camera = new vpgl_geo_camera(trans_matrix, lvcs);
259  camera->set_scale_format(true);
260  return true;
261 }
262 
263 
264 //: init using a tfw file, reads the transformation matrix from the tfw
265 bool vpgl_geo_camera::init_geo_camera(const std::string& tfw_name, const vpgl_lvcs_sptr& lvcs, int utm_zone, unsigned northing, vpgl_geo_camera*& camera)
266 {
267 
268  std::ifstream ifs(tfw_name.c_str());
269 
270  if (!ifs.is_open()) {
271  std::cerr << "in vpgl_geo_camera::init_geo_camera() -- cannot open: " << tfw_name << '\n';
272  return false;
273  }
274 
276  ifs >> trans_matrix[0][0];
277  ifs >> trans_matrix[0][1];
278  ifs >> trans_matrix[1][0];
279  ifs >> trans_matrix[1][1];
280  ifs >> trans_matrix[0][3];
281  ifs >> trans_matrix[1][3];
282  trans_matrix[3][3] = 1.0;
283 
284  camera = new vpgl_geo_camera(trans_matrix, lvcs);
285  if (utm_zone != 0)
286  camera->set_utm(utm_zone, northing);
287  camera->set_scale_format(true);
288 
289  ifs.close();
290  return true;
291 }
292 
293 //: transforms a given local 3d world point to image plane
294 void vpgl_geo_camera::project(const double x, const double y, const double z,
295  double& u, double& v) const
296 {
297  vnl_vector<double> vec(4), res(4);
298  double lat, lon, gz;
299 
300  if (lvcs_) {
301  if (lvcs_->get_cs_name() == vpgl_lvcs::utm) {
302  if (is_utm) { // geo cam is also utm so keep using utm
303  double gx, gy;
304  lvcs_->local_to_global(x, y, z, vpgl_lvcs::utm, gx, gy, gz);
305  this->global_utm_to_img(gx, gy, utm_zone_, gz, u, v);
306  }
307  else { // geo cam is not utm, convert to wgs84 as global
308  lvcs_->local_to_global(x, y, z, vpgl_lvcs::wgs84, lon, lat, gz);
309  this->global_to_img(lon, lat, gz, u, v);
310  }
311  }
312  else {
313  lvcs_->local_to_global(x, y, z, vpgl_lvcs::wgs84, lon, lat, gz);
314  this->global_to_img(lon, lat, gz, u, v);
315  }
316  }
317  else // if there is no lvcs, then we assume global coords are given in wgs84, i.e. x is lon and y is lat
318  this->global_to_img(x, y, z, u, v);
319 }
320 
321 //: backprojects an image point into local coordinates (based on lvcs_)
322 void vpgl_geo_camera::backproject(const double u, const double v,
323  double& x, double& y, double& z)
324 {
325  vnl_vector<double> vec(4), res(4);
326  if (scale_tag_) {
327  vec[0] = trans_matrix_[0][3] + trans_matrix_[0][0]*u;
328  vec[1] = trans_matrix_[1][3] + trans_matrix_[1][1]*v;
329  }
330  else { // assumes scale is 1
331  vec[0] = trans_matrix_[0][3] + u;
332  vec[1] = trans_matrix_[1][3] - v;
333  }
334  vec[2] = 0;
335  vec[3] = 1;
336  //std::cout << '\n' << vec << std::endl;
337 
338  double lat, lon, elev;
339  if (is_utm) {
340  if (lvcs_) {
341  if (lvcs_->get_cs_name() == vpgl_lvcs::utm) { // the local cs of lvcs is also utm, so use it directly
342  lvcs_->global_to_local(vec[0], vec[1], vec[2], vpgl_lvcs::utm, x, y, z);
343  return;
344  }
345  }
346  //find the UTM values
347  vpgl_utm utm;
348  utm.transform(utm_zone_, vec[0], vec[1], vec[2], lat, lon, elev);
349  }
350  else {
351  lon = vec[0];
352  lat = vec[1];
353  elev = vec[2];
354  }
355 
356  if (lvcs_)
357  lvcs_->global_to_local(lon, lat, elev, vpgl_lvcs::wgs84, x, y, z);
358 }
359 
360 void vpgl_geo_camera::translate(double tx, double ty, double /*z*/)
361 {
362  // use the scale values
363  if (scale_tag_) {
364  trans_matrix_[0][3] += tx*trans_matrix_[0][0];
365  trans_matrix_[1][3] += ty*trans_matrix_[1][1]; // multiplying by -1.0 to get sy
366  }
367  else {
368  std::cout << "Warning! Translation offset will only be computed correctly for lidar pixel spacing = 1 meter\n";
369  trans_matrix_[0][3] += tx;
370  trans_matrix_[1][3] -= ty;
371  }
372 }
373 
374 //: returns the corresponding geographical coordinates for a given pixel position (i,j)
375 // The output global coord is wgs84
376 void vpgl_geo_camera::img_to_global(const double i, const double j,
377  double& lon, double& lat) const
378 {
379  vnl_vector<double> v(4), res(4);
380  if (scale_tag_) {
381  v[0] = trans_matrix_[0][3] + i*trans_matrix_[0][0];
382  v[1] = trans_matrix_[1][3] + j*trans_matrix_[1][1];
383  }
384  else {
385  v[0] = trans_matrix_[0][3] + i;
386  v[1] = trans_matrix_[1][3] - j;
387  }
388  v[2] = 0;
389  v[3] = 1;
390  if (is_utm) {
391  vpgl_utm utm; double dummy;
392  utm.transform(utm_zone_, v[0], v[1], v[2], lat, lon, dummy);
393  }
394  else {
395  //lon = v[0]; lat = v[1]; elev = v[2];
396  lon = v[0]; lat = v[1];
397  }
398 }
399 
400 //: returns the corresponding pixel position for given geographical coordinates
401 // The input global coord is wgs84
402 void vpgl_geo_camera::global_to_img(const double lon, const double lat, const double gz,
403  double& u, double& v) const
404 {
405  vnl_vector<double> vec(4), res(4);
406  double x1=lon, y1=lat, z1=gz;
407  if (is_utm) {
408  vpgl_utm utm;
409  int utm_zone;
410  utm.transform(lat, lon, x1, y1, utm_zone);
411  //std::cout << "utm returned x1: " << x1 << " y1: " << y1 << std::endl;
412  //z1 = 0;
413  }
414  vec[0] = x1;
415  vec[1] = y1;
416  vec[2] = z1;
417  vec[3] = 1;
418 
419  // do we really need this, const does not allow this
421  tm[2][2] = 1;
422 
423  if (scale_tag_) {
424  u = (vec[0] - trans_matrix_[0][3])/trans_matrix_[0][0];
425  v = (vec[1] - trans_matrix_[1][3])/trans_matrix_[1][1];
426  }
427  else {
428  vnl_matrix<double> trans_matrix_inv = vnl_inverse(tm);
429  res = trans_matrix_inv*vec;
430  u = res[0];
431  v = res[1];
432  }
433 }
434 
435 //: returns the corresponding geographical coordinates for a given pixel position (i,j)
436 // The output global coord is UTM: x east, y north
437 void vpgl_geo_camera::img_to_global_utm(const double i, const double j, double& x, double& y) const
438 {
439  vnl_vector<double> v(4), res(4);
440  if (scale_tag_) {
441  v[0] = trans_matrix_[0][3] + i*trans_matrix_[0][0];
442  v[1] = trans_matrix_[1][3] + j*trans_matrix_[1][1];
443  }
444  else {
445  v[0] = trans_matrix_[0][3] + i;
446  v[1] = trans_matrix_[1][3] - j;
447  }
448  v[2] = 0;
449  v[3] = 1;
450  if (is_utm) {
451  x = v[0];
452  y = v[1];
453  }
454  else { // the trans matrix was using lat,lon coord, transform output to utm
455  vpgl_utm utm; int dummy_zone;
456  utm.transform(v[0], v[1], x, y, dummy_zone);
457  }
458 }
459 
460 //: returns the corresponding pixel position for given geographical coordinates
461 // The input global coord is UTM: x east, for y north
462 void vpgl_geo_camera::global_utm_to_img(const double x, const double y, int zone, double elev, double& u, double& v) const
463 {
464  vnl_vector<double> vec(4), res(4);
465  if (is_utm) {
466  vec[0] = x;
467  vec[1] = y;
468  vec[2] = elev;
469  }
470  else {
471  vpgl_utm utm;
472  double lat, lon, z;
473  utm.transform(zone, x, y, elev, lat, lon, z);
474  vec[0] = lat;
475  vec[1] = lon;
476  vec[2] = z;
477  }
478  vec[3] = 1;
479 
480  // do we really need this, const does not allow this
482  tm[2][2] = 1;
483 
484  if (scale_tag_) {
485  u = (vec[0] - trans_matrix_[0][3])/trans_matrix_[0][0];
486  v = (vec[1] - trans_matrix_[1][3])/trans_matrix_[1][1];
487  }
488  else {
489  vnl_matrix<double> trans_matrix_inv = vnl_inverse(tm);
490  res = trans_matrix_inv*vec;
491  u = res[0];
492  v = res[1];
493  }
494 }
495 
496 //: returns the corresponding utm location for the given local position
497 void vpgl_geo_camera::local_to_utm(const double x, const double y, const double z, double& e, double& n, int& utm_zone)
498 {
499  double lat, lon, gz;
500  lvcs_->local_to_global(x,y,z,vpgl_lvcs::wgs84,lon, lat, gz);
501 
502  vpgl_utm utm;
503  utm.transform(lat, lon, e, n, utm_zone);
504 }
505 
506 // save the camera matrix into a tfw file
507 void vpgl_geo_camera::save_as_tfw(std::string const& tfw_filename)
508 {
509  std::ofstream ofs(tfw_filename.c_str());
510  ofs.precision(12);
511  ofs << trans_matrix_[0][0] << '\n';
512  ofs << trans_matrix_[0][1] << '\n';
513  ofs << trans_matrix_[1][0] << '\n';
514  ofs << trans_matrix_[1][1] << '\n';
515  ofs << trans_matrix_[0][3] << '\n';
516  ofs << trans_matrix_[1][3] << '\n';
517  ofs.close();
518 }
519 
520 bool vpgl_geo_camera::img_four_corners_in_utm(const unsigned ni, const unsigned nj, double /*elev*/, double& e1, double& n1, double& e2, double& n2)
521 {
522  if (!is_utm) {
523  std::cerr << "In vpgl_geo_camera::img_four_corners_in_utm() -- UTM hasn't been set!\n";
524  return false;
525  }
526  double lon,lat;
527  this->img_to_global(0, 0, lon, lat);
528  vpgl_utm utm;int utm_zone;
529  utm.transform(lat, lon, e1, n1, utm_zone);
530  this->img_to_global(ni, nj, lon, lat);
531  utm.transform(lat, lon, e2, n2, utm_zone);
532  return true;
533 }
534 
535 
537 {
538  return this->trans_matrix_ == rhs.trans_matrix_ &&
539  *(this->lvcs_) == *(rhs.lvcs_);
540 }
541 
542 //: Write vpgl_geo_camera to stream
543 std::ostream& operator<<(std::ostream& s,
544  vpgl_geo_camera const& p)
545 {
546  if(p.lvcs_) s << p.trans_matrix_ << '\n'<< *(p.lvcs_) << '\n';
547  else s << p.trans_matrix_ << '\n';
548  if (p.is_utm) {
549  s << "geocam is using UTM with zone: " << p.utm_zone_ << '\n';
550  }
551 
552  return s ;
553 }
554 
555 //: Read vpgl_perspective_camera from stream
556 std::istream& operator>>(std::istream& s,
557  vpgl_geo_camera& p)
558 {
560  s >> tr_matrix;
561  vpgl_lvcs_sptr lvcs = new vpgl_lvcs();
562  s >> (*lvcs);
563  p = vpgl_geo_camera(tr_matrix.as_ref(), lvcs);
564  return s ;
565 }
566 
567 bool vpgl_geo_camera::comp_trans_matrix(double sx1, double sy1, double sz1,
568  std::vector<std::vector<double> > tiepoints,
569  vnl_matrix<double>& trans_matrix,
570  bool scale_tag)
571 {
572  // use tiepoints and scale values to create a transformation matrix
573  // for now use the first tiepoint if there are more than one
574  assert (tiepoints.size() > 0);
575  assert (tiepoints[0].size() == 6);
576  double I = tiepoints[0][0];
577  double J = tiepoints[0][1];
578  double K = tiepoints[0][2];
579  double X = tiepoints[0][3];
580  double Y = tiepoints[0][4];
581  double Z = tiepoints[0][5];
582 
583  // Define a transformation matrix as follows:
584  //
585  // |- -|
586  // | Sx 0.0 0.0 Tx |
587  // | | Tx = X - I*Sx
588  // | 0.0 -Sy 0.0 Ty | Ty = Y + J*Sy
589  // | | Tz = Z - K*Sz
590  // | 0.0 0.0 Sz Tz |
591  // | |
592  // | 0.0 0.0 0.0 1.0 |
593  // |- -|
594  double sx = 1.0, sy = 1.0, sz = 1.0;
595  if (scale_tag) {
596  sx = sx1; sy = sy1; sz = sz1;
597  }
598  double Tx = X - I*sx;
599  double Ty = Y + J*sy;
600  double Tz = Z - K*sz;
601 
602  vnl_matrix<double> m(4,4);
603  m.fill(0.0);
604  m[0][0] = sx;
605  m[1][1] = -1*sy;
606  m[2][2] = sz;
607  m[3][3] = 1.0;
608  m[0][3] = Tx;
609  m[1][3] = Ty;
610  m[2][3] = Tz;
611  trans_matrix = m;
612  std::cout << trans_matrix << std::endl;
613  return true;
614 }
615 
616 void vpgl_geo_camera::img_to_wgs(unsigned /*i*/, unsigned /*j*/, unsigned /*k*/, double& /*lon*/, double& /*lat*/, double& /*elev*/)
617 {
618  assert(!"Not yet implemented");
619 }
620 
621 //: Binary save self to stream.
623 {
624  vsl_b_write(os, version());
627  for (unsigned i = 0; i < trans_matrix_.rows(); i++)
628  for (unsigned j = 0; j < trans_matrix_.cols(); j++)
629  vsl_b_write(os, trans_matrix_[i][j]);
630 
631  lvcs_->b_write(os);
632  vsl_b_write(os, is_utm);
633  vsl_b_write(os, utm_zone_);
634  vsl_b_write(os, northing_);
635  vsl_b_write(os, scale_tag_);
636 }
637 
638 
639 //: Binary load self from stream.
641 {
642  if (!is) return;
643  short ver;
644  vsl_b_read(is, ver);
645  switch (ver)
646  {
647  case 1: {
648  unsigned nrows, ncols;
649  vsl_b_read(is, nrows);
650  vsl_b_read(is, ncols);
651  trans_matrix_.set_size(nrows, ncols);
652  for (unsigned i = 0; i < nrows; i++)
653  for (unsigned j = 0; j < ncols; j++)
654  vsl_b_read(is, trans_matrix_[i][j]);
655 
656  vpgl_lvcs_sptr lvcs_ = new vpgl_lvcs(0,0,0);
657  lvcs_->b_read(is);
658  vsl_b_read(is, is_utm);
659  vsl_b_read(is, utm_zone_);
660  vsl_b_read(is, northing_);
661  vsl_b_read(is, scale_tag_);
662  break; }
663 
664  default:
665  std::cerr << "I/O ERROR: vpgl_geo_camera::b_read(vsl_b_istream&)\n"
666  << " Unknown version number "<< ver << '\n';
667  is.is().clear(std::ios::badbit); // Set an unrecoverable IO error on stream
668  return;
669  }
670 }
unsigned int cols() const
static bool init_geo_camera_from_filename(const std::string &img_name, unsigned ni, unsigned nj, const vpgl_lvcs_sptr &lvcs, vpgl_geo_camera *&camera)
void img_to_global_utm(const double i, const double j, double &x, double &y) const
returns the corresponding geographical coordinates for a given pixel position (i,j).
A geographic coordinate system.
vnl_matrix & copy_in(double const *)
vnl_matrix & fill_diagonal(double const &)
void set_utm(int utm_zone, unsigned northing)
std::istream & operator>>(std::istream &is, vpgl_local_rational_camera< T > &p)
Read from stream.
void vsl_b_write(vsl_b_ostream &os, vpgl_affine_camera< T > const &camera)
Binary save camera to stream.
short version() const
Return IO version number;.
vnl_matrix< double > trans_matrix_
void global_utm_to_img(const double x, const double y, int zone, double elev, double &u, double &v) const
returns the corresponding pixel position for given geographical coordinates.
vnl_matrix< double > trans_matrix()
void img_to_global(const double i, const double j, double &lon, double &lat) const
returns the corresponding geographical coordinates for a given pixel position (i,j).
#define m
std::istream & is() const
void vsl_b_read(vsl_b_istream &is, vpgl_affine_camera< T > &camera)
Binary load camera from stream.
void save_as_tfw(std::string const &tfw_filename)
save the camera as tfw.
void backproject(const double u, const double v, double &x, double &y, double &z)
backprojects an image point into local coordinates (based on lvcs_).
void b_write(vsl_b_ostream &os) const
Binary save self to stream.
#define v
A rip-off of the IUE utm_geodedic and geodetic_utm transform classes which allows the GeoPt to suppor...
vnl_matrix_fixed< T, 1, 1 > vnl_inverse(vnl_matrix_fixed< T, 1, 1 > const &m)
void global_to_img(const double lon, const double lat, const double elev, double &u, double &v) const
returns the corresponding pixel position for given geographical coordinates.
vpgl_lvcs_sptr const lvcs()
A geotiff image deduced camera class.
void set_scale_format(bool scale_tag)
vnl_matrix & fill(double const &)
void translate(double tx, double ty, double z)
void local_to_utm(const double x, const double y, const double z, double &e, double &n, int &utm_zone)
returns the corresponding utm location for the given local position.
static bool init_geo_camera(vil_image_resource_sptr const &geotiff_img, const vpgl_lvcs_sptr &lvcs, vpgl_geo_camera *&camera)
uses lvcs to convert local x-y to global longitude and latitude.
std::ostream & operator<<(std::ostream &s, const vpgl_local_rational_camera< T > &p)
Write to stream.
bool img_four_corners_in_utm(const unsigned ni, const unsigned nj, double elev, double &e1, double &n1, double &e2, double &n2)
unsigned int rows() const
vpgl_geo_camera()
creates identity matrix and all zero tiepoints.
static bool comp_trans_matrix(double sx1, double sy1, double sz1, std::vector< std::vector< double > > tiepoints, vnl_matrix< double > &trans_matrix, bool scale_tag=false)
bool set_size(unsigned r, unsigned c)
vpgl_lvcs_sptr lvcs_
lvcs of world parameters.
void project(const double x, const double y, const double z, double &u, double &v) const override
Implementing the generic camera interface of vpgl_camera.
void b_read(vsl_b_istream &is)
Binary load self from stream.
void transform(int utm_zone, double x, double y, double z, double &lat, double &lon, double &elev, bool south_flag=false, double utm_central_meridian=0)
Definition: vpgl_utm.cxx:155
bool operator==(vpgl_geo_camera const &rhs) const
void img_to_wgs(unsigned i, unsigned j, unsigned k, double &lon, double &lat, double &elev)
returns the corresponding geographical coordinate (lon, lat, elev) for a given pixel position (i,...