1 // This is brl/bseg/bvxm/pro/processes/bvxm_create_ortho_camera_process.cxx
2 #include "bvxm_create_ortho_camera_process.h"
3 //:
4 // \file
5 #include <bprb/bprb_func_process.h>
6 #include <bvxm/bvxm_voxel_world.h>
7 #include <bvxm/bvxm_image_metadata.h>
8 #include <bvxm/bvxm_edge_ray_processor.h>
9 #include <brip/brip_vil_float_ops.h>
10 #include "vil/vil_image_view.h"
11 #include "vpgl/vpgl_utm.h"
12 
bvxm_create_ortho_camera_process_cons(bprb_func_process & pro)13 bool bvxm_create_ortho_camera_process_cons(bprb_func_process& pro)
14 {
15   using namespace bvxm_create_ortho_camera_process_globals;
16   std::vector<std::string> input_types_(n_inputs_);
17   input_types_[0] = "bvxm_voxel_world_sptr";
18   input_types_[1] = "bool";
19   if (!pro.set_input_types(input_types_))
20     return false;
21 
22   std::vector<std::string> output_types_(n_outputs_);
23   output_types_[0] = "vpgl_camera_double_sptr";  // return the ortho camera of the scene, as it may be needed for other processes
24   return pro.set_output_types(output_types_);
25 }
26 
27 // generates an ortho camera from the scene bounding box, GSD of the image is 1 meter
bvxm_create_ortho_camera_process(bprb_func_process & pro)28 bool bvxm_create_ortho_camera_process(bprb_func_process& pro)
29 {
30   using namespace bvxm_create_ortho_camera_process_globals;
31 
32   if (pro.n_inputs()<n_inputs_)
33   {
34     std::cout << pro.name() << " The input number should be " << n_inputs_<< std::endl;
35     return false;
36   }
37 
38   //voxel_world
39   bvxm_voxel_world_sptr world =  pro.get_input<bvxm_voxel_world_sptr>(0);
40   if (!world) {
41     std::cout << pro.name() <<" :--  Input 0  is not valid!\n";
42     return false;
43   }
44 
45   bool is_utm = pro.get_input<bool>(1);
46 
47   // generate vpgl_geo_camera for the scene
48   bvxm_world_params_sptr params = world->get_params();
49   vgl_box_3d<double> box = params->world_box_local();
50   vgl_point_3d<float> corner = params->corner();
51   vgl_point_3d<float> upper_left(corner.x(), (float)(corner.y() + box.height()), corner.z());
52   vgl_point_3d<float> lower_right((float)(corner.x()+box.width()), corner.y(), corner.z());
53   float voxel_length = params->voxel_length();
54 
55   vpgl_lvcs_sptr lvcs = params->lvcs();
56   double lat, lon, elev;
57   lvcs->get_origin(lat, lon, elev);
58   std::cout << " lvcs origin: " << lat << " " << lon << " " << elev << std::endl;
59 
60   // determine the upper left corner to use a vpgl_geo_cam, WARNING: assumes that the world is compass-alinged
61   double upper_left_lon, upper_left_lat, upper_left_elev;
62   lvcs->local_to_global(upper_left.x(), upper_left.y(), upper_left.z(), vpgl_lvcs::wgs84, upper_left_lon, upper_left_lat, upper_left_elev);
63   std::cout << "upper left corner in the image is: " << upper_left_lon << " lat: " << upper_left_lat << std::endl;
64 
65   double lower_right_lon, lower_right_lat, lower_right_elev;
66   lvcs->local_to_global(lower_right.x(), lower_right.y(), lower_right.z(), vpgl_lvcs::wgs84, lower_right_lon, lower_right_lat, lower_right_elev);
67   std::cout << "lower right corner in the image is: " << lower_right_lon << " lat: " << lower_right_lat << std::endl;
68 
69   vnl_matrix<double> trans_matrix(4,4,0.0);
70 
71   if (is_utm) {
72     double scale_x = voxel_length;
73     double scale_y = -1*voxel_length;
74     // transfer upper left corner to utm system
75     vpgl_utm utm;
76     double upper_left_x, upper_left_y;
77     int utm_zone;
78     utm.transform(upper_left_lat, upper_left_lon, upper_left_x, upper_left_y, utm_zone);
79     std::cout << "upper left in utm = " << upper_left_x << " x " << upper_left_y << std::endl;
80     std::cout << "scale_x = " << scale_x << " scale_y = " << scale_y << std::endl;
81     trans_matrix[0][0] = scale_x;
82     trans_matrix[1][1] = scale_y;
83     trans_matrix[0][3] = upper_left_x;
84     trans_matrix[1][3] = upper_left_y;
85     vpgl_geo_camera* cam = new vpgl_geo_camera(trans_matrix, lvcs);
86     unsigned northing = 1;
87     if (upper_left_lat < 0 && lower_right_lat < 0)
88       northing = 0;
89     if (upper_left_lat*lower_right_lat < 0)
90       std::cout << "warning: scene world crosses the Equator" << std::endl;
91     cam->set_utm(utm_zone,northing);
92     cam->set_scale_format(true);
93     vpgl_camera_double_sptr camera = new vpgl_geo_camera(*cam);
94     pro.set_output_val<vpgl_camera_double_sptr>(0, camera);
95     return true;
96   }
97   else {
98     auto ni = (unsigned)std::ceil(box.width() / voxel_length);
99     auto nj = (unsigned)std::ceil(box.height()/ voxel_length);
100     //trans_matrix[0][0] = (lower_right_lon-lon)/ni; trans_matrix[1][1] = -(upper_left_lat-lat)/nj;
101     // lvcs origin is not necessarily one of the corners of the scene
102     trans_matrix[0][0] = (lower_right_lon-upper_left_lon)/ni; trans_matrix[1][1] = -(upper_left_lat-lower_right_lat)/nj;
103     trans_matrix[0][3] = upper_left_lon; trans_matrix[1][3] = upper_left_lat;
104     vpgl_geo_camera* cam = new vpgl_geo_camera(trans_matrix, lvcs);
105     cam->set_scale_format(true);
106     vpgl_camera_double_sptr camera = new vpgl_geo_camera(*cam);
107 
108     pro.set_output_val<vpgl_camera_double_sptr>(0, camera);
109     return true;
110   }
111 
112 
113 }
114