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