vpgl_ray.cxx
Go to the documentation of this file.
1 // This is core/vpgl/algo/vpgl_ray.cxx
2 #include "vpgl_ray.h"
3 //:
4 // \file
5 #include <vnl/vnl_double_2.h>
6 #include <vnl/vnl_double_3.h>
7 #include <vnl/vnl_double_4.h>
8 #include <vnl/vnl_math.h>
9 #include <vgl/vgl_tolerance.h>
10 #include <vgl/vgl_distance.h>
11 #include <vgl/vgl_point_2d.h>
12 #include <vgl/vgl_point_3d.h>
13 #include <vgl/vgl_vector_3d.h>
14 #include <vgl/vgl_plane_3d.h>
15 #include <vgl/vgl_intersection.h>
17 #include "vpgl_backproject.h"
18 
20  vnl_double_3 const& point_3d,
21  vnl_double_3& r)
22 {
23  // special case of a generic camera
24  if (cam->type_name()=="vpgl_generic_camera")
25  {
26  vgl_point_3d<double> p(point_3d[0], point_3d[1], point_3d[2]);
28  const auto* gcam = dynamic_cast<const vpgl_generic_camera<double>*>(cam);
29  ray = gcam->ray(p);
30  vgl_vector_3d<double> dir = ray.direction();
31  r = vnl_double_3(dir.x(), dir.y(), dir.z());
32  return true;
33  }
34  //create an image point
35  double u, v;
36  cam->project(point_3d[0], point_3d[1], point_3d[2], u, v);
37  vnl_double_2 image_point(u, v);
38 
39  //construct a shifted plane by 1 unit in - z direction
40  vnl_double_4 plane(0, 0, 1.0, -point_3d[2]+ 1.0);
41 
42  //backproject onto the shifted plane
43  vnl_double_3 shifted_point;
44 
45  if (!vpgl_backproject::bproj_plane(cam, image_point, plane, point_3d,
46  shifted_point))
47  return false;
48  //The ray direction is just the difference
49  r = shifted_point - point_3d;
50  r.normalize();
51  return true;
52 }
53 
55  vgl_point_3d<double> const& point_3d,
57 {
58  vnl_double_3 p3d(point_3d.x(), point_3d.y(), point_3d.z());
59  vnl_double_3 tr;
60  bool success = vpgl_ray::ray(cam, p3d, tr);
61  if (!success) return false;
62  r.set(tr[0], tr[1], tr[2]);
63  return true;
64 }
65 
66 //construct a ray at a 3-d point with an origin lying in the origin_z plane
68  vgl_point_3d<double> const& point_3d,
69  double origin_z,
70  vgl_ray_3d<double>& ray)
71 {
72  vgl_plane_3d<double> pl(0.0, 0.0, 1.0, -origin_z);
74  bool success = vpgl_ray::ray(cam, point_3d, dir);
75  if (!success) return false;
76  // create an infinite line along dir
77  vgl_infinite_line_3d<double> infl(point_3d, dir);
78  vgl_point_3d<double> origin;
79  // intersect with the z plane
80  if (!vgl_intersection(infl, pl, origin))
81  return false;
82  ray.set(origin, dir);
83  return true;
84 }
85 //construct a ray at a 3-d point with an origin lying in the origin_z plane and dir from dz
87  vgl_point_2d<double> image_pt,
88  vgl_point_2d<double> const& initial_guess,
89  double origin_z, double dz,
90  vgl_ray_3d<double>& ray){
91  vgl_plane_3d<double> origin_plane(0.0, 0.0, 1.0, -origin_z);
92  vgl_plane_3d<double> tip_plane(0.0, 0.0, 1.0, -(origin_z-dz));//assuming looking downward from above
93  vgl_point_3d<double> initial_origin_guess(initial_guess.x(), initial_guess.y(), origin_z);
94  vgl_point_3d<double> initial_tip_guess(initial_guess.x(), initial_guess.y(), (origin_z-dz));
95  vgl_point_3d<double> origin, ray_tip;
96  if (!vpgl_backproject::bproj_plane(cam, image_pt, origin_plane, initial_origin_guess, origin))
97  return false;
98  if (!vpgl_backproject::bproj_plane(cam, image_pt, tip_plane, initial_tip_guess, ray_tip))
99  return false;
100  ray = vgl_ray_3d<double>(origin, ray_tip);
101  return true;
102 }
104  vnl_double_3 const& point_3d,
105  vnl_double_3& ray)
106 {
107  const auto* cam =
108  static_cast<const vpgl_camera<double>* >(&rcam);
109  return vpgl_ray::ray(cam, point_3d, ray);
110 }
111 
113  vgl_point_3d<double> const& point_3d,
115 {
116  const auto* cam =
117  static_cast<const vpgl_camera<double>* >(&rcam);
118 
119  return vpgl_ray::ray(cam,point_3d,ray);
120 }
121 
123  vgl_point_3d<double> const& point_3d,
124  vgl_ray_3d<double>& ray)
125 {
126  double z_off = rcam.offset(vpgl_rational_camera<double>::Z_INDX);
127  double z_scale = rcam.scale(vpgl_rational_camera<double>::Z_INDX);
128  double zmax = z_off + z_scale;
129 
130  const auto* cam =
131  static_cast<const vpgl_camera<double>* >(&rcam);
132 
133  return vpgl_ray::ray(cam,point_3d,zmax,ray);
134 }
135 
136 
137 // compute a ray in local Cartesian coordinates for a local rational cam
139  const double u, const double v,
140  vgl_point_3d<double>& origin,
142 {
143  // find the horizontal plane at the top of the 3-d region
144  // of valid RPC projection
145  double z_off = lrcam.offset(vpgl_rational_camera<double>::Z_INDX);
146  double z_scale = lrcam.scale(vpgl_rational_camera<double>::Z_INDX);
147  double zmax = z_off + z_scale;
148 
149  // find the point of intersection of the back-projected ray with zmax
150  vgl_plane_3d<double> top_plane(0.0, 0.0, 1.0, -zmax);
151  vgl_point_2d<double> image_point(u, v);
152  vgl_point_3d<double> initial_guess(0.0, 0.0, zmax);
153  auto* lrcam_ptr =
154  const_cast<vpgl_local_rational_camera<double>*>(&lrcam);
155  auto* cam = static_cast<vpgl_camera<double>*>(lrcam_ptr);
156  if (!vpgl_backproject::bproj_plane(cam, image_point, top_plane,
157  initial_guess, origin))
158  return false;
159 
160  // find the point of intersection of the back-projected ray with the
161  // plane at mid elevation.
162  //
163  vgl_plane_3d<double> mid_plane(0.0, 0.0, 1.0, -z_off);
164  vgl_point_3d<double> mid_initial_guess(0.0, 0.0, z_off), mid_point;
165  if (!vpgl_backproject::bproj_plane(cam, image_point, mid_plane,
166  mid_initial_guess, mid_point))
167  return false;
168 
169  dir = mid_point - origin;
170  dir/=dir.length();//unit vector
171 
172  return true;
173 }
174 
175 //: compute a ray in local Cartesian coordinates at a given (u, v)
177  const double u, const double v,
178  vgl_ray_3d<double>& ray)
179 {
181  bool success = vpgl_ray::ray(lrcam, u, v, origin, dir);
182  if (!success) return false;
183  ray.set(origin, dir);
184  return true;
185 }
186 
187 // compute a ray in local Cartesian coordinates for a local rational cam
189  const vgl_point_2d<double> image_point1,
190  const vgl_point_2d<double> image_point2,
191  vgl_plane_3d<double>& plane)
192 {
193  // find the horizontal plane at the top of the 3-d region
194  // of valid RPC projection
195  double z_off = lrcam.offset(vpgl_rational_camera<double>::Z_INDX);
196  double z_scale = lrcam.scale(vpgl_rational_camera<double>::Z_INDX);
197  double zmax = z_off + z_scale;
198 
199  // find the point of intersection of the back-projected ray with zmax
200  vgl_plane_3d<double> top_plane(0.0, 0.0, 1.0, -zmax);
201  //vgl_point_2d<double> image_point(u, v);
202  vgl_point_3d<double> initial_guess(0.0, 0.0, zmax);
203  vgl_point_3d<double> point1,point2;
204  auto* lrcam_ptr =
205  const_cast<vpgl_local_rational_camera<double>*>(&lrcam);
206  auto* cam = static_cast<vpgl_camera<double>*>(lrcam_ptr);
207  if (!vpgl_backproject::bproj_plane(cam, image_point1, top_plane,
208  initial_guess, point1))
209  return false;
210  if (!vpgl_backproject::bproj_plane(cam, image_point2, top_plane,
211  initial_guess, point2))
212  return false;
213 
214  // find the point of intersection of the back-projected ray with the
215  // plane at mid elevation.
216  //
217  vgl_plane_3d<double> mid_plane(0.0, 0.0, 1.0, -z_off);
218  vgl_point_3d<double> mid_initial_guess(0.0, 0.0, z_off), mid_point1;
219  if (!vpgl_backproject::bproj_plane(cam, image_point1, mid_plane,
220  mid_initial_guess, mid_point1))
221  return false;
222 
223  plane=vgl_plane_3d<double>(point1,point2,mid_point1);
224 
225  return true;
226 }
227 
229  vgl_point_3d<double> const& world_pt,
230  vgl_ray_3d<double>& ray)
231 {
234  return false;
235  ray = vgl_ray_3d<double>(cc, world_pt);
236  return true;
237 }
238 
240  vgl_ray_3d<double>& pray)
241 {
243  vgl_vector_3d<double> dir(C[2][0], C[2][1], C[2][2]);
244  //check if camera is affine. if so, the principal ray is not defined
246  return false;
247  dir = normalize(dir);
248  vgl_point_3d<double> cent = cam.camera_center();
249  pray = vgl_ray_3d<double>(cent, cent + dir);
250  return true;
251 }
252 
254  vgl_point_3d<double> const& world_pt,
255  vgl_ray_3d<double>& ray)
256 {
257  if (cam.is_behind_camera(vgl_homg_point_3d<double>(world_pt.x(), world_pt.y(), world_pt.z())))
258  return false;
259  ray = vgl_ray_3d<double>(cam.camera_center(), world_pt);
260  return true;
261 }
262 
264  vgl_point_3d<double> const& world_pt,
265  vgl_ray_3d<double>& ray)
266 {
267  ray = cam.ray(world_pt);
268  return true;
269 }
270 
272  vgl_rotation_3d<double> const& r1)
273 {
274  vnl_vector_fixed<double, 3> zaxis, a0, a1;
275  zaxis[0]=0.0; zaxis[1]=0.0; zaxis[2]=1.0;
276  vgl_rotation_3d<double> r0i = r0.inverse(), r1i = r1.inverse();
277  a0 = r0i*zaxis; a1 = r1i*zaxis;
278  double dp = dot_product(a0, a1);
279  return std::acos(dp);
280 }
281 
283  vgl_rotation_3d<double> const& r1)
284 {
285  // find axes for each rotation
286  vnl_vector_fixed<double, 3> zaxis, a0, a1;
287  zaxis[0]=0.0; zaxis[1]=0.0; zaxis[2]=1.0;
288  vgl_rotation_3d<double> r0i = r0.inverse(), r1i = r1.inverse();
289  a0 = r0i*zaxis; a1 = r1i*zaxis;
290  // find the transforms that map the z-axis to each axis
291  vgl_rotation_3d<double> r0b(zaxis, a0), r1b(zaxis,a1);
292  // find rotations about z axis
293  vgl_rotation_3d<double> r0_alpha = r0*r0b, r1_alpha = r1*r1b;
294  vnl_vector_fixed<double, 3> r0_alpha_rod = r0_alpha.as_rodrigues(), r1_alpha_rod = r1_alpha.as_rodrigues();
295  // get angle difference
296  double ang0 = r0_alpha_rod.magnitude(), ang1 = r1_alpha_rod.magnitude();
297  return std::fabs(ang0-ang1);
298 }
299 
302 {
303  vnl_vector_fixed<double, 3> za(0.0, 0.0, 1.0),
304  v(ray_dir.x(), ray_dir.y(), ray_dir.z());
305  //rotation from principal axis to z axis
306  vgl_rotation_3d<double> R_axis(v, za);
307  return R_axis;
308 }
309 
311  double elevation)
312 {
313  double el_rad = elevation*vnl_math::pi_over_180;
314  double s = std::sin(el_rad), c = std::cos(el_rad);
315  double az_rad = azimuth*vnl_math::pi_over_180;
316  double x = s*std::cos(az_rad), y = s*std::sin(az_rad), z = c;
318 }
abs_t magnitude() const
double vgl_distance(vgl_point_2d< T >const &p1, vgl_point_2d< T >const &p2)
static bool ray(const vpgl_camera< double > *cam, vnl_double_3 const &point_3d, vnl_double_3 &ray)
Generic camera interfaces (pointer for abstract class).
Definition: vpgl_ray.cxx:19
static bool principal_ray(vpgl_proj_camera< double > const &cam, vgl_ray_3d< double > &pray)
Definition: vpgl_ray.cxx:239
vgl_rotation_3d< T > inverse() const
vnl_vector_fixed< T, 3 > as_rodrigues() const
static vgl_rotation_3d< double > rot_to_point_ray(vgl_vector_3d< double > const &ray_dir)
the rotation required to point the principal ray in a given direction, starting with the identity cam...
Definition: vpgl_ray.cxx:301
vgl_point_3d< T > vgl_intersection(const std::vector< vgl_plane_3d< T > > &p)
Type & z()
#define v
static bool plane_ray(vpgl_local_rational_camera< double > const &lrcam, const vgl_point_2d< double > image_point1, const vgl_point_2d< double > image_point2, vgl_plane_3d< double > &plane)
compute a ray in local Cartesian coordinates for a local rational cam.
Definition: vpgl_ray.cxx:188
double length() const
T y() const
Type & y()
virtual vgl_homg_point_3d< T > camera_center() const
Find the 3d coordinates of the center of the camera.
vgl_homg_point_3d< T > camera_center() const override
Return the known camera center instead of computing it in the base class.
T x() const
T z() const
virtual std::string type_name() const
class identity functions for casting.
Definition: vpgl_camera.h:39
Type & x()
This class implements the perspective camera class as described in Hartley & Zisserman as a finite ca...
bool is_behind_camera(const vgl_homg_point_3d< T > &world_point) const
Determine whether the given point lies in front of the principal plane.
T scale(const coor_index coor_index) const
get a specific scale value.
const vnl_matrix_fixed< T, 3, 4 > & get_matrix() const
Return a copy of the camera matrix.
vgl_ray_3d< T > ray(const T u, const T v) const
the ray corresponding to a given pixel.
virtual void project(const T x, const T y, const T z, T &u, T &v) const =0
The generic camera interface. u represents image column, v image row.
static double rot_about_ray(vgl_rotation_3d< double > const &r0, vgl_rotation_3d< double > const &r1)
the rotation about the principal ray required to go from r0 to r1.
Definition: vpgl_ray.cxx:282
void set(T vx, T vy, T vz)
T dot_product(v const &a, v const &b)
static double angle_between_rays(vgl_rotation_3d< double > const &r0, vgl_rotation_3d< double > const &r1)
angle(radians) between principal ray of one rotation and the principal ray of a second rotation.
Definition: vpgl_ray.cxx:271
T offset(const coor_index coor_index) const
get a specific offset value.
v & normalize(v &a)
static bool bproj_plane(const vpgl_camera< double > *cam, vnl_double_2 const &image_point, vnl_double_4 const &plane, vnl_double_3 const &initial_guess, vnl_double_3 &world_point, double error_tol=0.05, double relative_diameter=1.0)
Generic camera interfaces (pointer for abstract class).
Methods for computing the camera ray direction at a given 3-d point and other operations on camera ra...
Methods for back_projecting from cameras to 3-d geometric structures.
Type & y()
Type & x()