00001
00002 #include "vpgl_ray.h"
00003
00004
00005 #include <vnl/vnl_double_2.h>
00006 #include <vnl/vnl_double_3.h>
00007 #include <vnl/vnl_double_4.h>
00008 #include <vnl/vnl_math.h>
00009 #include <vgl/vgl_tolerance.h>
00010 #include <vgl/vgl_distance.h>
00011 #include <vgl/vgl_point_3d.h>
00012 #include <vgl/vgl_vector_3d.h>
00013 #include <vgl/vgl_plane_3d.h>
00014 #include <vgl/vgl_intersection.h>
00015 #include <vpgl/algo/vpgl_invmap_cost_function.h>
00016 #include "vpgl_backproject.h"
00017
00018 bool vpgl_ray::ray(const vpgl_camera<double>* cam,
00019 vnl_double_3 const& point_3d,
00020 vnl_double_3& r)
00021 {
00022
00023 if (cam->type_name()=="vpgl_generic_camera")
00024 {
00025 vgl_point_3d<double> p(point_3d[0], point_3d[1], point_3d[2]);
00026 vgl_ray_3d<double> ray;
00027 const vpgl_generic_camera<double>* gcam = dynamic_cast<const vpgl_generic_camera<double>*>(cam);
00028 ray = gcam->ray(p);
00029 vgl_vector_3d<double> dir = ray.direction();
00030 r = vnl_double_3(dir.x(), dir.y(), dir.z());
00031 return true;
00032 }
00033
00034 double u, v;
00035 cam->project(point_3d[0], point_3d[1], point_3d[2], u, v);
00036 vnl_double_2 image_point(u, v);
00037
00038
00039 vnl_double_4 plane(0, 0, 1.0, -point_3d[2]+ 1.0);
00040
00041
00042 vnl_double_3 shifted_point;
00043
00044 if (!vpgl_backproject::bproj_plane(cam, image_point, plane, point_3d,
00045 shifted_point))
00046 return false;
00047
00048 r = shifted_point - point_3d;
00049 r.normalize();
00050 return true;
00051 }
00052
00053 bool vpgl_ray::ray(const vpgl_camera<double>* cam,
00054 vgl_point_3d<double> const& point_3d,
00055 vgl_vector_3d<double>& r)
00056 {
00057 vnl_double_3 p3d(point_3d.x(), point_3d.y(), point_3d.z());
00058 vnl_double_3 tr;
00059 bool success = vpgl_ray::ray(cam, p3d, tr);
00060 if (!success) return false;
00061 r.set(tr[0], tr[1], tr[2]);
00062 return true;
00063 }
00064
00065
00066 bool vpgl_ray::ray(const vpgl_camera<double>* cam,
00067 vgl_point_3d<double> const& point_3d,
00068 double origin_z,
00069 vgl_ray_3d<double>& ray)
00070 {
00071 vgl_plane_3d<double> pl(0.0, 0.0, 1.0, -origin_z);
00072 vgl_vector_3d<double> dir;
00073 bool success = vpgl_ray::ray(cam, point_3d, dir);
00074 if (!success) return false;
00075
00076 vgl_infinite_line_3d<double> infl(point_3d, dir);
00077 vgl_point_3d<double> origin;
00078
00079 if (!vgl_intersection(infl, pl, origin))
00080 return false;
00081 ray.set(origin, dir);
00082 return true;
00083 }
00084
00085 bool vpgl_ray::ray(vpgl_rational_camera<double> const& rcam,
00086 vnl_double_3 const& point_3d,
00087 vnl_double_3& ray)
00088 {
00089 const vpgl_camera<double>* cam =
00090 static_cast<const vpgl_camera<double>* >(&rcam);
00091 return vpgl_ray::ray(cam, point_3d, ray);
00092 }
00093
00094 bool vpgl_ray::ray(vpgl_rational_camera<double> const& rcam,
00095 vgl_point_3d<double> const& point_3d,
00096 vgl_vector_3d<double>& ray)
00097 {
00098 const vpgl_camera<double>* cam =
00099 static_cast<const vpgl_camera<double>* >(&rcam);
00100
00101 return vpgl_ray::ray(cam,point_3d,ray);
00102 }
00103
00104 bool vpgl_ray::ray(vpgl_rational_camera<double> const& rcam,
00105 vgl_point_3d<double> const& point_3d,
00106 vgl_ray_3d<double>& ray)
00107 {
00108 double z_off = rcam.offset(vpgl_rational_camera<double>::Z_INDX);
00109 double z_scale = rcam.scale(vpgl_rational_camera<double>::Z_INDX);
00110 double zmax = z_off + z_scale;
00111
00112 const vpgl_camera<double>* cam =
00113 static_cast<const vpgl_camera<double>* >(&rcam);
00114
00115 return vpgl_ray::ray(cam,point_3d,zmax,ray);
00116 }
00117
00118
00119
00120 bool vpgl_ray::ray(vpgl_local_rational_camera<double> const& lrcam,
00121 const double u, const double v,
00122 vgl_point_3d<double>& origin,
00123 vgl_vector_3d<double>& dir)
00124 {
00125
00126
00127 double z_off = lrcam.offset(vpgl_rational_camera<double>::Z_INDX);
00128 double z_scale = lrcam.scale(vpgl_rational_camera<double>::Z_INDX);
00129 double zmax = z_off + z_scale;
00130
00131
00132 vgl_plane_3d<double> top_plane(0.0, 0.0, 1.0, -zmax);
00133 vgl_point_2d<double> image_point(u, v);
00134 vgl_point_3d<double> initial_guess(0.0, 0.0, zmax);
00135 vpgl_local_rational_camera<double>* lrcam_ptr =
00136 const_cast<vpgl_local_rational_camera<double>*>(&lrcam);
00137 vpgl_camera<double>* cam = static_cast<vpgl_camera<double>*>(lrcam_ptr);
00138 if (!vpgl_backproject::bproj_plane(cam, image_point, top_plane,
00139 initial_guess, origin))
00140 return false;
00141
00142
00143
00144
00145 vgl_plane_3d<double> mid_plane(0.0, 0.0, 1.0, -z_off);
00146 vgl_point_3d<double> mid_initial_guess(0.0, 0.0, z_off), mid_point;
00147 if (!vpgl_backproject::bproj_plane(cam, image_point, mid_plane,
00148 mid_initial_guess, mid_point))
00149 return false;
00150
00151 dir = mid_point - origin;
00152 dir/=dir.length();
00153
00154 return true;
00155 }
00156
00157
00158 bool vpgl_ray::ray(vpgl_local_rational_camera<double> const& lrcam,
00159 const double u, const double v,
00160 vgl_ray_3d<double>& ray)
00161 {
00162 vgl_point_3d<double> origin; vgl_vector_3d<double> dir;
00163 bool success = vpgl_ray::ray(lrcam, u, v, origin, dir);
00164 if (!success) return false;
00165 ray.set(origin, dir);
00166 return true;
00167 }
00168
00169
00170 bool vpgl_ray::plane_ray(vpgl_local_rational_camera<double> const& lrcam,
00171 const vgl_point_2d<double> image_point1,
00172 const vgl_point_2d<double> image_point2,
00173 vgl_plane_3d<double>& plane)
00174 {
00175
00176
00177 double z_off = lrcam.offset(vpgl_rational_camera<double>::Z_INDX);
00178 double z_scale = lrcam.scale(vpgl_rational_camera<double>::Z_INDX);
00179 double zmax = z_off + z_scale;
00180
00181
00182 vgl_plane_3d<double> top_plane(0.0, 0.0, 1.0, -zmax);
00183
00184 vgl_point_3d<double> initial_guess(0.0, 0.0, zmax);
00185 vgl_point_3d<double> point1,point2;
00186 vpgl_local_rational_camera<double>* lrcam_ptr =
00187 const_cast<vpgl_local_rational_camera<double>*>(&lrcam);
00188 vpgl_camera<double>* cam = static_cast<vpgl_camera<double>*>(lrcam_ptr);
00189 if (!vpgl_backproject::bproj_plane(cam, image_point1, top_plane,
00190 initial_guess, point1))
00191 return false;
00192 if (!vpgl_backproject::bproj_plane(cam, image_point2, top_plane,
00193 initial_guess, point2))
00194 return false;
00195
00196
00197
00198
00199 vgl_plane_3d<double> mid_plane(0.0, 0.0, 1.0, -z_off);
00200 vgl_point_3d<double> mid_initial_guess(0.0, 0.0, z_off), mid_point1;
00201 if (!vpgl_backproject::bproj_plane(cam, image_point1, mid_plane,
00202 mid_initial_guess, mid_point1))
00203 return false;
00204
00205 plane=vgl_plane_3d<double>(point1,point2,mid_point1);
00206
00207 return true;
00208 }
00209
00210 bool vpgl_ray::ray(vpgl_proj_camera<double> const& cam,
00211 vgl_point_3d<double> const& world_pt,
00212 vgl_ray_3d<double>& ray)
00213 {
00214 vgl_point_3d<double> cc = cam.camera_center();
00215 if (vgl_distance(cc, world_pt)<vgl_tolerance<double>::position)
00216 return false;
00217 ray = vgl_ray_3d<double>(cc, world_pt);
00218 return true;
00219 }
00220
00221 bool vpgl_ray::principal_ray(vpgl_proj_camera<double> const& cam,
00222 vgl_ray_3d<double>& pray)
00223 {
00224 vnl_matrix_fixed<double, 3, 4> C = cam.get_matrix();
00225 vgl_vector_3d<double> dir(C[2][0], C[2][1], C[2][2]);
00226
00227 if (dir.length()<vgl_tolerance<double>::position)
00228 return false;
00229 dir = normalize(dir);
00230 vgl_point_3d<double> cent = cam.camera_center();
00231 pray = vgl_ray_3d<double>(cent, cent + dir);
00232 return true;
00233 }
00234
00235 bool vpgl_ray::ray(vpgl_perspective_camera<double> const& cam,
00236 vgl_point_3d<double> const& world_pt,
00237 vgl_ray_3d<double>& ray)
00238 {
00239 if (cam.is_behind_camera(vgl_homg_point_3d<double>(world_pt.x(), world_pt.y(), world_pt.z())))
00240 return false;
00241 ray = vgl_ray_3d<double>(cam.camera_center(), world_pt);
00242 return true;
00243 }
00244
00245 bool vpgl_ray::ray(vpgl_generic_camera<double> const& cam,
00246 vgl_point_3d<double> const& world_pt,
00247 vgl_ray_3d<double>& ray)
00248 {
00249 ray = cam.ray(world_pt);
00250 return true;
00251 }
00252
00253 double vpgl_ray::angle_between_rays(vgl_rotation_3d<double> const& r0,
00254 vgl_rotation_3d<double> const& r1)
00255 {
00256 vnl_vector_fixed<double, 3> zaxis, a0, a1;
00257 zaxis[0]=0.0; zaxis[1]=0.0; zaxis[2]=1.0;
00258 vgl_rotation_3d<double> r0i = r0.inverse(), r1i = r1.inverse();
00259 a0 = r0i*zaxis; a1 = r1i*zaxis;
00260 double dp = dot_product(a0, a1);
00261 return vcl_acos(dp);
00262 }
00263
00264 double vpgl_ray::rot_about_ray(vgl_rotation_3d<double> const& r0,
00265 vgl_rotation_3d<double> const& r1)
00266 {
00267
00268 vnl_vector_fixed<double, 3> zaxis, a0, a1;
00269 zaxis[0]=0.0; zaxis[1]=0.0; zaxis[2]=1.0;
00270 vgl_rotation_3d<double> r0i = r0.inverse(), r1i = r1.inverse();
00271 a0 = r0i*zaxis; a1 = r1i*zaxis;
00272
00273 vgl_rotation_3d<double> r0b(zaxis, a0), r1b(zaxis,a1);
00274
00275 vgl_rotation_3d<double> r0_alpha = r0*r0b, r1_alpha = r1*r1b;
00276 vnl_vector_fixed<double, 3> r0_alpha_rod = r0_alpha.as_rodrigues(), r1_alpha_rod = r1_alpha.as_rodrigues();
00277
00278 double ang0 = r0_alpha_rod.magnitude(), ang1 = r1_alpha_rod.magnitude();
00279 return vcl_fabs(ang0-ang1);
00280 }
00281
00282 vgl_rotation_3d<double> vpgl_ray::
00283 rot_to_point_ray(vgl_vector_3d<double> const& ray_dir)
00284 {
00285 vnl_vector_fixed<double, 3> za(0.0, 0.0, 1.0),
00286 v(ray_dir.x(), ray_dir.y(), ray_dir.z());
00287
00288 vgl_rotation_3d<double> R_axis(v, za);
00289 return R_axis;
00290 }
00291
00292 vgl_rotation_3d<double> vpgl_ray::rot_to_point_ray(double azimuth,
00293 double elevation)
00294 {
00295 double el_rad = elevation*vnl_math::pi_over_180;
00296 double s = vcl_sin(el_rad), c = vcl_cos(el_rad);
00297 double az_rad = azimuth*vnl_math::pi_over_180;
00298 double x = s*vcl_cos(az_rad), y = s*vcl_sin(az_rad), z = c;
00299 return vpgl_ray::rot_to_point_ray(vgl_vector_3d<double>(x, y, z));
00300 }