1 // This is brl/bpro/core/vpgl_pro/processes/vpgl_geo_camera_processes.cxx
2 #include <iostream>
3 #include <vil/vil_config.h>
4 #if HAS_GEOTIFF
5 #include <bprb/bprb_func_process.h>
6 //:
7 // \file
8 
9 #include <bprb/bprb_parameters.h>
10 #ifdef _MSC_VER
11 #  include "vcl_msvc_warnings.h"
12 #endif
13 #include <vpgl/file_formats/vpgl_geo_camera.h>
14 #include <vpgl/algo/vpgl_camera_convert.h>
15 #include "vpgl/vpgl_lvcs_sptr.h"
16 #include <bkml/bkml_write.h>
17 #include "vil/vil_image_resource.h"
18 #include "vil/vil_load.h"
19 #include "vul/vul_file.h"
20 
21 
22 //: process to create a geo camera given its lower left corner and image size
vpgl_create_geo_camera_process_cons(bprb_func_process & pro)23 bool vpgl_create_geo_camera_process_cons(bprb_func_process& pro)
24 {
25   // this process takes 7 inputs
26   std::vector<std::string> input_types_;
27   input_types_.emplace_back("double");          // lower left lon
28   input_types_.emplace_back("double");          // lower left lat
29   input_types_.emplace_back("double");          // upper right lon
30   input_types_.emplace_back("double");          // upper right lat
31   input_types_.emplace_back("unsigned");        // image size ni
32   input_types_.emplace_back("unsigned");        // image size nj
33   input_types_.emplace_back("vpgl_lvcs_sptr");  // camera lvcs, empty by default
34   // this process takes 1 output
35   std::vector<std::string> output_types_;
36   output_types_.emplace_back("vpgl_camera_double_sptr");  // camera output
37 
38   // set default lvcs
39   vpgl_lvcs_sptr lvcs = new vpgl_lvcs;
40   pro.set_input(6, new brdb_value_t<vpgl_lvcs_sptr>(lvcs));
41   return pro.set_input_types(input_types_) && pro.set_output_types(output_types_);
42 }
43 
vpgl_create_geo_camera_process(bprb_func_process & pro)44 bool vpgl_create_geo_camera_process(bprb_func_process& pro)
45 {
46   if (!pro.verify_inputs()) {
47     std::cerr << pro.name() << ": Wrong Input!\n";
48     return false;
49   }
50   // get the inputs
51   unsigned in_i = 0;
52   auto ll_lon = pro.get_input<double>(in_i++);
53   auto ll_lat = pro.get_input<double>(in_i++);
54   auto ur_lon = pro.get_input<double>(in_i++);
55   auto ur_lat = pro.get_input<double>(in_i++);
56   auto ni = pro.get_input<unsigned>(in_i++);
57   auto nj = pro.get_input<unsigned>(in_i++);
58   vpgl_lvcs_sptr lvcs = pro.get_input<vpgl_lvcs_sptr>(in_i++);
59   if (ni == 0 || nj == 0) {
60     std::cerr << pro.name() << ": image size can not be zero -- ni: " << ni << ", nj: " << nj << "!\n";
61     return false;
62   }
63   double scale_x = (ur_lon - ll_lon) / ni;
64   double scale_y = (ll_lat - ur_lat) / nj;
65   vnl_matrix<double> trans_matrix(4,4,0.0);
66   trans_matrix[0][0] = scale_x;
67   trans_matrix[1][1] = scale_y;
68   trans_matrix[0][3] = ll_lon;
69   trans_matrix[1][3] = ur_lat;
70   vpgl_geo_camera* out_cam = new vpgl_geo_camera(trans_matrix, lvcs);
71   out_cam->set_scale_format(true);
72 
73   // output
74   pro.set_output_val<vpgl_camera_double_sptr>(0, out_cam);
75   return true;
76 }
77 
78 
79 //: initialization
vpgl_load_geo_camera_process_cons(bprb_func_process & pro)80 bool vpgl_load_geo_camera_process_cons(bprb_func_process& pro)
81 {
82   //this process takes 4 inputs and one output
83   std::vector<std::string> input_types;
84   input_types.emplace_back("vcl_string");
85   input_types.emplace_back("vpgl_lvcs_sptr");
86   input_types.emplace_back("int");  // UTM zone, pass 0 if not UTM
87   input_types.emplace_back("unsigned");  // UTM hemisphere, pass 0 for north, 1 for south
88   std::vector<std::string> output_types;
89   output_types.emplace_back("vpgl_camera_double_sptr");  //camera output
90 
91   bool good = pro.set_input_types(input_types)
92       && pro.set_output_types(output_types);
93 
94   vpgl_lvcs_sptr lvcs = new vpgl_lvcs;  // initialize lvcs to empty
95   pro.set_input(1, new brdb_value_t<vpgl_lvcs_sptr>(lvcs));
96 
97   return good;
98 }
99 
100 //: Execute the process
vpgl_load_geo_camera_process(bprb_func_process & pro)101 bool vpgl_load_geo_camera_process(bprb_func_process& pro)
102 {
103   if (pro.n_inputs()!= 4) {
104     std::cout << "vpgl_load_geo_camera_process: The number of inputs should be 4" << std::endl;
105     return false;
106   }
107 
108   // get the inputs
109   std::string tfw_filename = pro.get_input<std::string>(0);
110   vpgl_lvcs_sptr lvcs = pro.get_input<vpgl_lvcs_sptr>(1);
111   int utm_zone = pro.get_input<int>(2);
112   auto northing = pro.get_input<unsigned>(3);
113 
114   std::ifstream ifs(tfw_filename.c_str());
115   if(!ifs)
116   {
117       std::cout<<"Could not open file "<<std::endl;
118       return false;
119   }
120   vnl_matrix<double> trans_matrix(4,4,0.0);
121   ifs >> trans_matrix[0][0];
122   ifs >> trans_matrix[0][1];
123   ifs >> trans_matrix[1][0];
124   ifs >> trans_matrix[1][1];
125   ifs >> trans_matrix[0][3];
126   ifs >> trans_matrix[1][3];
127   trans_matrix[3][3] = 1.0;
128   ifs.close();
129 
130   std::cout << "trans matrix: " << trans_matrix << std::endl;
131 
132   vpgl_geo_camera *cam = new vpgl_geo_camera(trans_matrix, lvcs);
133   if (utm_zone != 0)
134     cam->set_utm(utm_zone, northing);
135   cam->set_scale_format(true);
136 
137   pro.set_output_val<vpgl_camera_double_sptr>(0, cam);
138   return true;
139 }
140 
141 
142 //: initialization
vpgl_translate_geo_camera_process_cons(bprb_func_process & pro)143 bool vpgl_translate_geo_camera_process_cons(bprb_func_process& pro)
144 {
145   //this process takes 3 inputs and one output
146   std::vector<std::string> input_types;
147   input_types.emplace_back("vpgl_camera_double_sptr");  // input geo camera
148   input_types.emplace_back("double");
149   input_types.emplace_back("double");
150   std::vector<std::string> output_types;
151   output_types.emplace_back("vpgl_camera_double_sptr");  //camera output
152   return pro.set_input_types(input_types)
153       && pro.set_output_types(output_types);
154 }
155 
156 //: Execute the process
vpgl_translate_geo_camera_process(bprb_func_process & pro)157 bool vpgl_translate_geo_camera_process(bprb_func_process& pro)
158 {
159   if (pro.n_inputs()!= 3) {
160     std::cout << "vpgl_translate_geo_camera_process: The number of inputs should be 3" << std::endl;
161     return false;
162   }
163 
164   // get the inputs
165   vpgl_camera_double_sptr cam = pro.get_input<vpgl_camera_double_sptr>(0);
166   auto tx = pro.get_input<double>(1);
167   auto ty = pro.get_input<double>(2);
168   auto* geocam = dynamic_cast<vpgl_geo_camera*> (cam.ptr());
169   auto* outcam = new vpgl_geo_camera(*geocam);
170   outcam->translate(tx, ty, 0.0);
171   pro.set_output_val<vpgl_camera_double_sptr>(0, outcam);
172   return true;
173 }
174 
175 //: initialization
vpgl_convert_geo_camera_to_generic_process_cons(bprb_func_process & pro)176 bool vpgl_convert_geo_camera_to_generic_process_cons(bprb_func_process& pro)
177 {
178   //this process takes 5 inputs and one output
179   std::vector<std::string> input_types;
180   input_types.emplace_back("vpgl_camera_double_sptr");  // input geo camera
181   input_types.emplace_back("int");
182   input_types.emplace_back("int");
183   input_types.emplace_back("double");
184   input_types.emplace_back("int");
185   std::vector<std::string> output_types;
186   output_types.emplace_back("vpgl_camera_double_sptr");  // generic camera output
187   return pro.set_input_types(input_types)
188       && pro.set_output_types(output_types);
189 }
190 
191 //: Execute the process
vpgl_convert_geo_camera_to_generic_process(bprb_func_process & pro)192 bool vpgl_convert_geo_camera_to_generic_process(bprb_func_process& pro)
193 {
194   if (pro.n_inputs()!= 5) {
195     std::cout << "vpgl_convert_geo_camera_to_generic_process: The number of inputs should be 5" << std::endl;
196     return false;
197   }
198 
199   // get the inputs
200   vpgl_camera_double_sptr cam = pro.get_input<vpgl_camera_double_sptr>(0);
201   int ni = pro.get_input<int>(1);
202   int nj = pro.get_input<int>(2);
203   auto scene_height = pro.get_input<double>(3);
204   int level = pro.get_input<int>(4);
205   auto* geocam = dynamic_cast<vpgl_geo_camera*> (cam.ptr());
206   vpgl_generic_camera<double> gcam;
207   vpgl_generic_camera_convert::convert(*geocam, ni, nj, scene_height, gcam, level);
208 
209   vpgl_camera_double_sptr out = new vpgl_generic_camera<double>(gcam);
210   pro.set_output_val<vpgl_camera_double_sptr>(0, out);
211   return true;
212 }
213 
214 //: initialization
215 //  also input a ray direction, and thus create a generic camera with parallel rays with the given direction
216 //  so this process creates an orthographic camera which is not necessarily nadir
vpgl_convert_non_nadir_geo_camera_to_generic_process_cons(bprb_func_process & pro)217 bool vpgl_convert_non_nadir_geo_camera_to_generic_process_cons(bprb_func_process& pro)
218 {
219   //this process takes 5 inputs and one output
220   std::vector<std::string> input_types;
221   input_types.emplace_back("vpgl_camera_double_sptr");  // input geo camera
222   input_types.emplace_back("int");
223   input_types.emplace_back("int");
224   input_types.emplace_back("double");
225   input_types.emplace_back("int");
226   input_types.emplace_back("double");  // ray direction x   (nadir direction would be (0,0,-1)
227   input_types.emplace_back("double");  // ray direction y
228   input_types.emplace_back("double");  // ray direction z
229   std::vector<std::string> output_types;
230   output_types.emplace_back("vpgl_camera_double_sptr");  // generic camera output
231   return pro.set_input_types(input_types)
232       && pro.set_output_types(output_types);
233 }
234 
235 //: Execute the process
vpgl_convert_non_nadir_geo_camera_to_generic_process(bprb_func_process & pro)236 bool vpgl_convert_non_nadir_geo_camera_to_generic_process(bprb_func_process& pro)
237 {
238   if (pro.n_inputs()!= 8) {
239     std::cout << "vpgl_convert_geo_camera_to_generic_process: The number of inputs should be 5" << std::endl;
240     return false;
241   }
242 
243   // get the inputs
244   vpgl_camera_double_sptr cam = pro.get_input<vpgl_camera_double_sptr>(0);
245   int ni = pro.get_input<int>(1);
246   int nj = pro.get_input<int>(2);
247   auto scene_height = pro.get_input<double>(3);
248   int level = pro.get_input<int>(4);
249   auto dir_x = pro.get_input<double>(5);
250   auto dir_y = pro.get_input<double>(6);
251   auto dir_z = pro.get_input<double>(7);
252   vgl_vector_3d<double> dir(dir_x, dir_y, dir_z);
253 
254   auto* geocam = dynamic_cast<vpgl_geo_camera*> (cam.ptr());
255   vpgl_generic_camera<double> gcam;
256   vpgl_generic_camera_convert::convert(*geocam, ni, nj, scene_height, dir, gcam, level);
257 
258   vpgl_camera_double_sptr out = new vpgl_generic_camera<double>(gcam);
259   pro.set_output_val<vpgl_camera_double_sptr>(0, out);
260   return true;
261 }
262 
263 
264 //: initialization
vpgl_geo_footprint_process_cons(bprb_func_process & pro)265 bool vpgl_geo_footprint_process_cons(bprb_func_process& pro)
266 {
267   //this process takes 4 inputs:
268   std::vector<std::string> input_types;
269   input_types.emplace_back("vpgl_camera_double_sptr");  // as read from a geotiff image header or from a tfw file
270   input_types.emplace_back("vcl_string");               // geotiff file, to determine image size
271   input_types.emplace_back("vcl_string");               // the filename of the kml file to write footprints to
272   input_types.emplace_back("bool");                     // put the tags do initialize and end the document, if writing only one file these are needed, otherwise add manually to the file
273   return pro.set_input_types(input_types);
274 }
275 
276 //: Execute the process
vpgl_geo_footprint_process(bprb_func_process & pro)277 bool vpgl_geo_footprint_process(bprb_func_process& pro)
278 {
279   if (pro.n_inputs() != 4) {
280     std::cout << "vpgl_geo_footprint_process: Number of inputs is " << pro.n_inputs() << ", should be 2" << std::endl;
281     return false;
282   }
283 
284   // get the inputs
285   vpgl_camera_double_sptr cam = pro.get_input<vpgl_camera_double_sptr>(0);
286   std::string geotiff_filename = pro.get_input<std::string>(1);
287   vil_image_resource_sptr img_res = vil_load_image_resource(geotiff_filename.c_str());
288   std::string footprint_filename = pro.get_input<std::string>(2);
289   bool init_finish = pro.get_input<bool>(3);
290   unsigned ni = img_res->ni(); unsigned nj = img_res->nj();
291 
292   std::ofstream ofs(footprint_filename.c_str(), std::ios::app);
293   if (!ofs.good()) {
294     std::cerr << "ERROR: vpgl_geo_footprint_process : Error opening " << footprint_filename << " for write.\n";
295     return false;
296   }
297 
298   if (init_finish)
299     bkml_write::open_document(ofs);
300 
301   auto* geocam=dynamic_cast<vpgl_geo_camera*> (cam.ptr());
302   if (!geocam) {
303     std::cerr << "In vpgl_geo_footprint_process() - input camera is not valid!\n";
304     return false;
305   }
306 
307   double lon, lat;
308   geocam->img_to_global(0,0,lon,lat);
309   vnl_double_2 ul; ul[0] = lat; ul[1] = lon;
310 
311   geocam->img_to_global(0,nj,lon,lat);
312   vnl_double_2 ur; ur[0] = lat; ur[1] = lon;
313 
314   geocam->img_to_global(ni,0,lon,lat);
315   vnl_double_2 ll; ll[0] = lat; ll[1] = lon;
316 
317   geocam->img_to_global(ni,nj,lon,lat);
318   vnl_double_2 lr; lr[0] = lat; lr[1] = lon;
319 
320   std::string g_id = vul_file::strip_directory(geotiff_filename);
321   std::string desc = geotiff_filename + " footprint";
322 
323   bkml_write::write_box(ofs, g_id, desc, ul, ur, ll, lr);
324 
325   if (init_finish)
326     bkml_write::close_document(ofs);
327 
328   return true;
329 }
330 
331 //: process to return the lower left and upper right corners of a geotiff image
vpgl_geo_footprint_process2_cons(bprb_func_process & pro)332 bool vpgl_geo_footprint_process2_cons(bprb_func_process& pro)
333 {
334   // this process takes 4 inputs:
335   std::vector<std::string> input_types;
336   input_types.emplace_back("vpgl_camera_double_sptr");  // as read from a geotiff image header or from a tfw file
337   input_types.emplace_back("vcl_string");               // geotiff file, to determine image size
338   input_types.emplace_back("vcl_string");               // the filename of the kml file to write footprints to
339   input_types.emplace_back("bool");                     // put the tags do initialize and end the document, if writing only one file these are needed, otherwise add manually to the file
340   // this process takes 4 outputs:
341   std::vector<std::string> output_types;
342   output_types.emplace_back("double");                  // lower left  longitude
343   output_types.emplace_back("double");                  // lower left   latitude
344   output_types.emplace_back("double");                  // upper right longitude
345   output_types.emplace_back("double");                  // upper right  latitude
346   return pro.set_input_types(input_types) && pro.set_output_types(output_types);
347 }
348 
vpgl_geo_footprint_process2(bprb_func_process & pro)349 bool vpgl_geo_footprint_process2(bprb_func_process& pro)
350 {
351   if (!pro.verify_inputs()) {
352     std::cerr << pro.name() << ": Wrong Inputs!!!" << std::endl;
353     return false;
354   }
355   // get the inputs
356   unsigned in_i = 0;
357   vpgl_camera_double_sptr cam  = pro.get_input<vpgl_camera_double_sptr>(in_i++);
358   std::string geotiff_filename  = pro.get_input<std::string>(in_i++);
359   std::string out_footprint_kml = pro.get_input<std::string>(in_i++);
360   bool write_kml               = pro.get_input<bool>(in_i++);
361 
362   // get the image size
363   vil_image_resource_sptr img_res = vil_load_image_resource(geotiff_filename.c_str());
364   unsigned ni = img_res->ni();
365   unsigned nj = img_res->nj();
366 
367   // get the geo camera of the input image
368   auto* geocam = dynamic_cast<vpgl_geo_camera*>(cam.ptr());
369   if (!geocam) {
370     std::cerr << pro.name() << ": input camera is not valid!\n";
371     return false;
372   }
373 
374   // obtain the lower left and upper right corner
375   double ll_lon, ll_lat;
376   geocam->img_to_global(0,  nj,  ll_lon, ll_lat);
377   double ur_lon, ur_lat;
378   geocam->img_to_global(ni,  0, ur_lon, ur_lat);
379 
380   // generate kml if required
381   if (write_kml) {
382     std::ofstream ofs(out_footprint_kml.c_str());
383     if (!ofs.good()) {
384       std::cerr << pro.name() << ": Error opening " << out_footprint_kml << " for writing footprint!\n";
385       return false;
386     }
387     bkml_write::open_document(ofs);
388     vgl_box_2d<double> bbox(ll_lon, ur_lon, ll_lat, ur_lat);
389     std::cout << "bbox: " << bbox << std::endl;
390     vnl_double_2 ul(bbox.max_y(), bbox.min_x());
391     vnl_double_2 ur(bbox.max_y(), bbox.max_x());
392     vnl_double_2 ll(bbox.min_y(), bbox.min_x());
393     vnl_double_2 lr(bbox.min_y(), bbox.max_x());
394     std::string img_name = vul_file::strip_directory(geotiff_filename);
395     std::string desc     = geotiff_filename + " footPrint";
396     bkml_write::write_box(ofs, img_name, desc, ul, ur, ll, lr, 0, 255, 0);
397     bkml_write::close_document(ofs);
398     ofs.close();
399   }
400 
401   // output
402   std::cout << " lower left: [" << ll_lon << "," << ll_lat << ']' << std::endl;
403   std::cout << "upper right: [" << ur_lon << "," << ur_lat << ']' << std::endl;
404   // generate output
405   unsigned out_i = 0;
406   pro.set_output_val<double>(out_i++, ll_lon);
407   pro.set_output_val<double>(out_i++, ll_lat);
408   pro.set_output_val<double>(out_i++, ur_lon);
409   pro.set_output_val<double>(out_i++, ur_lat);
410 
411   return true;
412 }
413 
vpgl_geo_cam_global_to_img_process_cons(bprb_func_process & pro)414 bool vpgl_geo_cam_global_to_img_process_cons(bprb_func_process& pro)
415 {
416   //this process takes 3 inputs and one output
417   std::vector<std::string> input_types;
418   input_types.emplace_back("vpgl_camera_double_sptr");  // input geo camera
419   input_types.emplace_back("double"); // lon
420   input_types.emplace_back("double"); // lat
421   std::vector<std::string> output_types;
422   output_types.emplace_back("int");  // i
423   output_types.emplace_back("int");  // j
424   return pro.set_input_types(input_types)
425       && pro.set_output_types(output_types);
426 }
427 
428 //: Execute the process
vpgl_geo_cam_global_to_img_process(bprb_func_process & pro)429 bool vpgl_geo_cam_global_to_img_process(bprb_func_process& pro)
430 {
431   if (pro.n_inputs()!= 3) {
432     std::cout << "vpgl_translate_geo_camera_process: The number of inputs should be 3" << std::endl;
433     return false;
434   }
435 
436   // get the inputs
437   vpgl_camera_double_sptr cam = pro.get_input<vpgl_camera_double_sptr>(0);
438   auto lon = pro.get_input<double>(1);
439   auto lat = pro.get_input<double>(2);
440   auto* geocam = dynamic_cast<vpgl_geo_camera*> (cam.ptr());
441   double u,v;
442   geocam->global_to_img(lon, lat, 0.0, u, v);
443   pro.set_output_val<int>(0, (int)u);
444   pro.set_output_val<int>(1, (int)v);
445   return true;
446 }
447 
vpgl_geo_cam_img_to_global_process_cons(bprb_func_process & pro)448 bool vpgl_geo_cam_img_to_global_process_cons(bprb_func_process& pro)
449 {
450   // this process takes 3 inputs and two outputs
451   std::vector<std::string> input_types(3);
452   input_types[0] = "vpgl_camera_double_sptr";  // input geo camera
453   input_types[1] = "unsigned";                 // input pixel row
454   input_types[2] = "unsigned";                 // input pixel column
455   // this process takes 2 outputs
456   std::vector<std::string> output_types(2);
457   output_types[0] = "double";                  // lon
458   output_types[1] = "double";                  // lat
459   return pro.set_input_types(input_types) && pro.set_output_types(output_types);
460 }
461 
vpgl_geo_cam_img_to_global_process(bprb_func_process & pro)462 bool vpgl_geo_cam_img_to_global_process(bprb_func_process& pro)
463 {
464   if (!pro.verify_inputs()) {
465     std::cerr << pro.name() << ": Wrong Inputs!\n";
466     return false;
467   }
468   // get inputs
469   unsigned in_i = 0;
470   vpgl_camera_double_sptr cam = pro.get_input<vpgl_camera_double_sptr>(in_i++);
471   auto i = pro.get_input<unsigned>(in_i++);
472   auto j = pro.get_input<unsigned>(in_i++);
473   // convert
474   auto* geocam = dynamic_cast<vpgl_geo_camera*>(cam.ptr());
475   if (!geocam) {
476     std::cerr << pro.name() << ": Can not convert input camera into a geo camera!\n";
477     return false;
478   }
479   double lon, lat;
480   geocam->img_to_global(i, j, lon, lat);
481   // output
482   pro.set_output_val<double>(0, lon);
483   pro.set_output_val<double>(1, lat);
484   return true;
485 }
486 
487 //: construct the camera from the name of the image with a known specific format
488 //  this geocam has no lvcs, so it's only useful for img_to_global or global_to_img operations
vpgl_load_geo_camera_process2_cons(bprb_func_process & pro)489 bool vpgl_load_geo_camera_process2_cons(bprb_func_process& pro)
490 {
491   std::vector<std::string> input_types;
492   input_types.emplace_back("vcl_string"); // image name
493   input_types.emplace_back("unsigned"); // image size ni
494   input_types.emplace_back("unsigned"); // nj
495   std::vector<std::string> output_types;
496   output_types.emplace_back("vpgl_camera_double_sptr");  //camera output
497   return pro.set_input_types(input_types)
498       && pro.set_output_types(output_types);
499 }
500 
501 //: Execute the process
vpgl_load_geo_camera_process2(bprb_func_process & pro)502 bool vpgl_load_geo_camera_process2(bprb_func_process& pro)
503 {
504   if (pro.n_inputs()!= 3) {
505     std::cout << "vpgl_load_geo_camera_process2: The number of inputs should be 3" << std::endl;
506     return false;
507   }
508 
509   // get the inputs
510   std::string filename = pro.get_input<std::string>(0);
511   auto ni = pro.get_input<unsigned>(1);
512   auto nj = pro.get_input<unsigned>(2);
513   vpgl_lvcs_sptr lvcs = new vpgl_lvcs;
514 
515   vpgl_geo_camera *cam;
516   vpgl_geo_camera::init_geo_camera_from_filename(filename, ni, nj, lvcs, cam);
517   //vpgl_geo_camera::init_geo_camera(filename, ni, nj, lvcs, cam);
518   pro.set_output_val<vpgl_camera_double_sptr>(0, cam);
519   return true;
520 }
521 
522 //: construct the camera from the header of the geoiff file
vpgl_load_geo_camera_process3_cons(bprb_func_process & pro)523 bool vpgl_load_geo_camera_process3_cons(bprb_func_process& pro)
524 {
525   std::vector<std::string> input_types;
526   input_types.emplace_back("vcl_string"); // image name. will load resource from this file
527   input_types.emplace_back("vpgl_lvcs_sptr"); // creates an empty one as a default if not available so do not set if not available
528   std::vector<std::string> output_types;
529   output_types.emplace_back("vpgl_camera_double_sptr");  //camera output
530   bool good = pro.set_input_types(input_types)
531            && pro.set_output_types(output_types);
532 
533   //input default args
534   vpgl_lvcs_sptr lvcs = new vpgl_lvcs;
535   brdb_value_sptr vpgl_val = new brdb_value_t<vpgl_lvcs_sptr>(lvcs);
536   pro.set_input(1, vpgl_val);
537 
538   return good;
539 }
540 
541 
542 //: Execute the process
vpgl_load_geo_camera_process3(bprb_func_process & pro)543 bool vpgl_load_geo_camera_process3(bprb_func_process& pro)
544 {
545   if (pro.n_inputs()!= 2) {
546     std::cout << "vpgl_load_geo_camera_process3: The number of inputs should be 2" << std::endl;
547     return false;
548   }
549 
550   // get the inputs
551   std::string filename = pro.get_input<std::string>(0);
552   vpgl_lvcs_sptr lvcs = pro.get_input<vpgl_lvcs_sptr>(1);
553   vil_image_resource_sptr img = vil_load_image_resource(filename.c_str());
554 
555   vpgl_geo_camera *cam;
556   vpgl_geo_camera::init_geo_camera(img, lvcs, cam);
557   pro.set_output_val<vpgl_camera_double_sptr>(0, cam);
558   return true;
559 }
560 
561 
562 
563 //: construct the camera as an ESRI world file (.tfw)
564 //
565 // World file uses the following transformation:
566 //  [ x_geo ]   [ A B C ] [ x_tfw ]
567 //  [ y_geo ] = [ D E F ] [ y_tfw ]
568 //                        [ 1     ]
569 //
570 // World file is a six line file written as follows
571 // (see https://en.wikipedia.org/wiki/World_file)
572 //   Line 1: A: x-component of the pixel width (x-scale)
573 //   Line 2: D: y-component of the pixel width (y-skew)
574 //   Line 3: B: x-component of the pixel height (x-skew)
575 //   Line 4: E: y-component of the pixel height (y-scale), typically negative
576 //   Line 5: C: x-coordinate of the center of the upper left pixel
577 //   Line 6: F: y-coordinate of the center of the upper left pixel
578 //
579 // World file (.tfw) origin has a half-pixel offset with respect to
580 // the vpgl_geo_camera origin:
581 //   x_vpgl = x_tfw + 0.5 (in pixels)
582 //   y_vpgl = y_tfw + 0.5 (in pixels)
583 //
vpgl_save_geo_camera_tfw_process_cons(bprb_func_process & pro)584 bool vpgl_save_geo_camera_tfw_process_cons(bprb_func_process& pro)
585 {
586   std::vector<std::string> input_types;
587   input_types.emplace_back("vpgl_camera_double_sptr");
588   input_types.emplace_back("vcl_string");
589   std::vector<std::string> output_types;
590   return pro.set_input_types(input_types)
591       && pro.set_output_types(output_types);
592 }
593 
594 //: Execute the process
vpgl_save_geo_camera_tfw_process(bprb_func_process & pro)595 bool vpgl_save_geo_camera_tfw_process(bprb_func_process& pro)
596 {
597   if (pro.n_inputs()!= 2) {
598     std::cout << "vpgl_save_geo_camera_tfw_process: The number of inputs should be 2" << std::endl;
599     return false;
600   }
601 
602   // get the inputs
603   vpgl_camera_double_sptr cam = pro.get_input<vpgl_camera_double_sptr>(0);
604   std::string filename = pro.get_input<std::string>(1);
605 
606   auto *geo_cam = dynamic_cast<vpgl_geo_camera*>(cam.ptr());
607   if (!geo_cam) {
608     std::cerr << "vpgl_save_geo_camera_tfw_process: Cannot cast camera to a geo cam! Exiting!\n";
609     return false;
610   }
611 
612   vnl_matrix<double> trans_matrix = geo_cam->trans_matrix();
613 
614   double A,B,C,D,E,F;
615   A = trans_matrix[0][0];
616   B = trans_matrix[1][0];
617   C = 0.5*A + 0.5*B + trans_matrix[0][3];
618   D = trans_matrix[0][1];
619   E = trans_matrix[1][1];
620   F = 0.5*D + 0.5*E + trans_matrix[1][3];
621 
622   std::ofstream ofs(filename.c_str());
623   ofs.precision(12);
624   ofs << A << std::endl << D << std::endl << B << std::endl;
625   ofs << E << std::endl << C << std::endl << F << std::endl;
626   ofs.close();
627 
628   return true;
629 }
630 
631 
632 //: return GeoTransform suitable for GDAL GeoTiff
633 //  Xgeo = GT(0) + Xpixel*GT(1) + Yline*GT(2)
634 //  Ygeo = GT(3) + Xpixel*GT(4) + Yline*GT(5)
635 //  http://www.gdal.org/gdal_datamodel.html
636 // Note that the pixel/line coordinates in the above are from (0.0,0.0) at the top
637 // left corner of the top left pixel to (width_in_pixels,height_in_pixels) at the
638 // bottom right corner of the bottom right pixel. The pixel/line location of the
639 // center of the top left pixel would therefore be (0.5,0.5).
vpgl_get_geotransform_process_cons(bprb_func_process & pro)640 bool vpgl_get_geotransform_process_cons(bprb_func_process& pro)
641 {
642   std::vector<std::string> input_types;
643   input_types.push_back("vpgl_camera_double_sptr");
644 
645   std::vector<std::string> output_types;
646   output_types.push_back("double");          // GT(0)
647   output_types.push_back("double");          // GT(1)
648   output_types.push_back("double");          // GT(2)
649   output_types.push_back("double");          // GT(3)
650   output_types.push_back("double");          // GT(4)
651   output_types.push_back("double");          // GT(5)
652 
653   return pro.set_input_types(input_types)
654       && pro.set_output_types(output_types);
655 }
656 
657 //: Execute the process
vpgl_get_geotransform_process(bprb_func_process & pro)658 bool vpgl_get_geotransform_process(bprb_func_process& pro)
659 {
660   if (pro.n_inputs()!= 1) {
661     std::cout << "vpgl_get_geotransform_process: The number of inputs should be 1" << std::endl;
662     return false;
663   }
664 
665   // get the inputs
666   vpgl_camera_double_sptr cam = pro.get_input<vpgl_camera_double_sptr>(0);
667 
668   // convert to geocamera if possible
669   vpgl_geo_camera *geo_cam = dynamic_cast<vpgl_geo_camera*>(cam.ptr());
670   if (!geo_cam) {
671     std::cerr << "vpgl_get_geotransform_process: Cannot cast camera to a geo cam! Exiting!\n";
672     return false;
673   }
674 
675   // output 6 doubles in expected order
676   vnl_matrix<double> trans_matrix = geo_cam->trans_matrix();
677   pro.set_output_val<double>(0, (double)trans_matrix[0][3]);
678   pro.set_output_val<double>(1, (double)trans_matrix[0][0]);
679   pro.set_output_val<double>(2, (double)trans_matrix[1][0]);
680   pro.set_output_val<double>(3, (double)trans_matrix[1][3]);
681   pro.set_output_val<double>(4, (double)trans_matrix[0][1]);
682   pro.set_output_val<double>(5, (double)trans_matrix[1][1]);
683 
684   return true;
685 }
686 
687 
688 #endif
689 
690 
691 
692