contrib/gel/mrc/vpgl/algo/vpgl_vsol_lens_warp.cxx
Go to the documentation of this file.
00001 // This is gel/mrc/vpgl/algo/vpgl_vsol_lens_warp.cxx
00002 #include "vpgl_vsol_lens_warp.h"
00003 //:
00004 // \file
00005 
00006 #include <vgl/vgl_point_2d.h>
00007 #include <vgl/vgl_homg_point_2d.h>
00008 #include <vgl/vgl_distance.h>
00009 #include <vsol/vsol_point_2d.h>
00010 #include <vsol/vsol_line_2d.h>
00011 #include <vsol/vsol_polyline_2d.h>
00012 #include <vsol/vsol_digital_curve_2d.h>
00013 #include <vsol/vsol_polygon_2d.h>
00014 #include <vcl_list.h>
00015 #include <vcl_iostream.h>
00016 
00017 
00018 //: Apply lens distortion to this vsol_spatial_object_2d and produce a new spatial object
00019 vsol_spatial_object_2d_sptr
00020 vpgl_vsol_lens_warp(const vsol_spatial_object_2d_sptr& obj,
00021                     const vpgl_lens_distortion<double>& lens,
00022                     bool invert,
00023                     double midpt_thresh)
00024 {
00025   if (vsol_point_2d_sptr pt = obj->cast_to_point())
00026   {
00027     return vpgl_vsol_lens_warp(pt, lens, invert, midpt_thresh).ptr();
00028   }
00029   else if (vsol_curve_2d* curve = obj->cast_to_curve())
00030   {
00031     if (vsol_line_2d_sptr line = curve->cast_to_line())
00032     {
00033       return vpgl_vsol_lens_warp(line, lens, invert, midpt_thresh).ptr();
00034     }
00035     else if (vsol_polyline_2d_sptr pline = curve->cast_to_polyline())
00036     {
00037       return vpgl_vsol_lens_warp(pline, lens, invert, midpt_thresh).ptr();
00038     }
00039     else if (vsol_digital_curve_2d_sptr dc = curve->cast_to_digital_curve())
00040     {
00041       return vpgl_vsol_lens_warp(dc, lens, invert, midpt_thresh).ptr();
00042     }
00043   }
00044   else if (vsol_region_2d* region = obj->cast_to_region())
00045   {
00046     if (vsol_polygon_2d_sptr pg = region->cast_to_polygon())
00047     {
00048       return vpgl_vsol_lens_warp(pg, lens, invert, midpt_thresh).ptr();
00049     }
00050   }
00051   return NULL;
00052 }
00053 
00054 //: Apply lens distortion to this vsol_point_2d and produce a new point
00055 vsol_point_2d_sptr
00056 vpgl_vsol_lens_warp(const vsol_point_2d_sptr& pt,
00057                     const vpgl_lens_distortion<double>& lens,
00058                     bool invert,
00059                     double midpt_thresh)
00060 {
00061   if ( midpt_thresh <= 0 )
00062     return 0;
00063   if (invert)
00064     return new vsol_point_2d( lens.undistort( vgl_homg_point_2d<double>(pt->get_p()) ) );
00065   else
00066     return new vsol_point_2d( lens.distort( vgl_homg_point_2d<double>(pt->get_p()) ) );
00067 }
00068 
00069 
00070 //: Recursively divide the line segment in half as long as the midpoint moves more than \p midpt_thresh
00071 static bool
00072 vpgl_vsol_warp_divide(const vsol_line_2d_sptr& ln,
00073                       const vsol_line_2d_sptr& wln,
00074                       const vpgl_lens_distortion<double>& lens,
00075                       bool invert,
00076                       double midpt_thresh,
00077                       vcl_list<vsol_point_2d_sptr>& pts)
00078 {
00079   if ( midpt_thresh <= 0 )
00080     return false;
00081   vsol_point_2d_sptr mp = ln->middle();
00082   vsol_point_2d_sptr dmp = vpgl_vsol_lens_warp(mp,lens,invert,midpt_thresh);
00083   vsol_point_2d_sptr wmp = wln->middle();
00084   if (vgl_distance(wmp->get_p(), dmp->get_p()) < midpt_thresh)
00085     return false;
00086 
00087   vcl_list<vsol_point_2d_sptr> pts1, pts2;
00088   vpgl_vsol_warp_divide(new vsol_line_2d(ln->p0(),mp),
00089                          new vsol_line_2d(wln->p0(),dmp),
00090                          lens, invert, midpt_thresh, pts1);
00091   vpgl_vsol_warp_divide(new vsol_line_2d(mp,ln->p1()),
00092                          new vsol_line_2d(dmp,wln->p1()),
00093                          lens, invert, midpt_thresh, pts2);
00094 
00095   pts.splice(pts.end(),pts1);
00096   pts.push_back(dmp);
00097   pts.splice(pts.end(),pts2);
00098   return true;
00099 }
00100 
00101 
00102 //: Apply lens distortion to this vsol_line_2d and produce a new line
00103 vsol_curve_2d_sptr
00104 vpgl_vsol_lens_warp(const vsol_line_2d_sptr& ln,
00105                     const vpgl_lens_distortion<double>& lens,
00106                     bool invert,
00107                     double midpt_thresh)
00108 {
00109   vsol_point_2d_sptr p0 = vpgl_vsol_lens_warp(ln->p0(), lens, invert, midpt_thresh);
00110   vsol_point_2d_sptr p1 = vpgl_vsol_lens_warp(ln->p1(), lens, invert, midpt_thresh);
00111   if (!p0 || !p1)
00112     return NULL;
00113   vsol_line_2d_sptr line = new vsol_line_2d(p0,p1);
00114   vcl_list<vsol_point_2d_sptr> pts;
00115   vpgl_vsol_warp_divide(ln,line,lens,invert,midpt_thresh,pts);
00116   if (pts.empty())
00117     return line.ptr();
00118   pts.push_front(p0);
00119   pts.push_back(p1);
00120   vcl_vector<vsol_point_2d_sptr> v_pts;
00121   for (vcl_list<vsol_point_2d_sptr>::iterator i = pts.begin();
00122        i != pts.end(); ++i )
00123     v_pts.push_back(*i);
00124   return new vsol_polyline_2d(v_pts);
00125 }
00126 
00127 
00128 //: Apply lens distortion to this vsol_polyline_2d and produce a new polyline
00129 vsol_polyline_2d_sptr
00130 vpgl_vsol_lens_warp(const vsol_polyline_2d_sptr& pln,
00131                     const vpgl_lens_distortion<double>& lens,
00132                     bool invert,
00133                     double midpt_thresh)
00134 {
00135   vcl_list<vsol_point_2d_sptr> pts;
00136   vsol_point_2d_sptr last_p = pln->p0();
00137   vsol_point_2d_sptr last_dp = vpgl_vsol_lens_warp(last_p, lens, invert, midpt_thresh);
00138   pts.push_back(last_dp);
00139   for (unsigned int i=1; i<pln->size(); ++i)
00140   {
00141     vsol_point_2d_sptr p = pln->vertex(i);
00142     vsol_point_2d_sptr dp = vpgl_vsol_lens_warp(p, lens, invert, midpt_thresh);
00143     if (!dp)
00144       return 0;
00145     vsol_line_2d_sptr ln = new vsol_line_2d(last_p,p);
00146     vsol_line_2d_sptr wln = new vsol_line_2d(last_dp,dp);
00147     vcl_list<vsol_point_2d_sptr> new_pts;
00148     vpgl_vsol_warp_divide(ln,wln,lens,invert,midpt_thresh,new_pts);
00149     pts.splice(pts.end(),new_pts);
00150     pts.push_back(dp);
00151     last_p = p;
00152     last_dp = dp;
00153   }
00154   vcl_vector<vsol_point_2d_sptr> v_pts;
00155   for (vcl_list<vsol_point_2d_sptr>::iterator i = pts.begin();
00156        i != pts.end(); ++i )
00157     v_pts.push_back(*i);
00158   return new vsol_polyline_2d(v_pts);
00159 }
00160 
00161 
00162 //: Apply lens distortion to this vsol_digital_curve_2d and produce a new digital curve
00163 vsol_digital_curve_2d_sptr
00164 vpgl_vsol_lens_warp(const vsol_digital_curve_2d_sptr& dc,
00165                     const vpgl_lens_distortion<double>& lens,
00166                     bool invert,
00167                     double midpt_thresh)
00168 {
00169   vcl_list<vsol_point_2d_sptr> pts;
00170   vsol_point_2d_sptr last_p = dc->p0();
00171   vsol_point_2d_sptr last_dp = vpgl_vsol_lens_warp(last_p, lens, invert, midpt_thresh);
00172   pts.push_back(last_dp);
00173   for (unsigned int i=1; i<dc->size(); ++i){
00174     vsol_point_2d_sptr p = dc->point(i);
00175     vsol_point_2d_sptr dp = vpgl_vsol_lens_warp(p, lens, invert, midpt_thresh);
00176     if (!dp)
00177       return 0;
00178     vsol_line_2d_sptr ln = new vsol_line_2d(last_p,p);
00179     vsol_line_2d_sptr wln = new vsol_line_2d(last_dp,dp);
00180     vcl_list<vsol_point_2d_sptr> new_pts;
00181     vpgl_vsol_warp_divide(ln,wln,lens,invert,midpt_thresh,new_pts);
00182     pts.splice(pts.end(),new_pts);
00183     pts.push_back(dp);
00184     last_p = p;
00185     last_dp = dp;
00186   }
00187   vcl_vector<vsol_point_2d_sptr> v_pts;
00188   for (vcl_list<vsol_point_2d_sptr>::iterator i = pts.begin();
00189        i != pts.end(); ++i )
00190     v_pts.push_back(*i);
00191   return new vsol_digital_curve_2d(v_pts);
00192 }
00193 
00194 
00195 //: Apply lens distortion to this vsol_polygon_2d and produce a new polygon
00196 vsol_polygon_2d_sptr
00197 vpgl_vsol_lens_warp(const vsol_polygon_2d_sptr& pg,
00198                     const vpgl_lens_distortion<double>& lens,
00199                     bool invert,
00200                     double midpt_thresh)
00201 {
00202   vcl_list<vsol_point_2d_sptr> pts;
00203   vsol_point_2d_sptr last_p = pg->vertex(pg->size()-1);
00204   vsol_point_2d_sptr last_dp = vpgl_vsol_lens_warp(last_p, lens, invert, midpt_thresh);
00205   for (unsigned int i=0; i<pg->size(); ++i){
00206     vsol_point_2d_sptr p = pg->vertex(i);
00207     vsol_point_2d_sptr dp = vpgl_vsol_lens_warp(p, lens, invert, midpt_thresh);
00208     if (!dp)
00209       return 0;
00210     vsol_line_2d_sptr ln = new vsol_line_2d(last_p,p);
00211     vsol_line_2d_sptr wln = new vsol_line_2d(last_dp,dp);
00212     vcl_list<vsol_point_2d_sptr> new_pts;
00213     vpgl_vsol_warp_divide(ln,wln,lens,invert,midpt_thresh,new_pts);
00214     pts.splice(pts.end(),new_pts);
00215     pts.push_back(dp);
00216     last_p = p;
00217     last_dp = dp;
00218   }
00219   vcl_vector<vsol_point_2d_sptr> v_pts;
00220   for (vcl_list<vsol_point_2d_sptr>::iterator i = pts.begin();
00221        i != pts.end(); ++i )
00222     v_pts.push_back(*i);
00223   return new vsol_polygon_2d(v_pts);
00224 }
00225 
00226 //================================================================
00227 
00228 //: Apply lens distortion to this vsol_spatial_object_2d in place
00229 // \return true if successful
00230 bool
00231 vpgl_vsol_lens_warp(vsol_spatial_object_2d_sptr& obj,
00232                     const vpgl_lens_distortion<double>& lens,
00233                     bool invert)
00234 {
00235   if (invert)
00236     vcl_cerr << "Warning: invert not yet implemented in vpgl_vsol_lens_warp\n";
00237 
00238   if (vsol_point_2d_sptr pt = obj->cast_to_point())
00239   {
00240     return vpgl_vsol_lens_warp(pt, lens);
00241   }
00242   else if (vsol_curve_2d* curve = obj->cast_to_curve())
00243   {
00244     if (vsol_line_2d_sptr line = curve->cast_to_line())
00245     {
00246       return vpgl_vsol_lens_warp(line, lens);
00247     }
00248     else if (vsol_polyline_2d_sptr pline = curve->cast_to_polyline())
00249     {
00250       return vpgl_vsol_lens_warp(pline, lens);
00251     }
00252     else if (vsol_digital_curve_2d_sptr dc = curve->cast_to_digital_curve())
00253     {
00254       return vpgl_vsol_lens_warp(dc, lens);
00255     }
00256   }
00257   else if (vsol_region_2d* region = obj->cast_to_region())
00258   {
00259     if (vsol_polygon_2d_sptr pg = region->cast_to_polygon())
00260     {
00261       return vpgl_vsol_lens_warp(pg, lens);
00262     }
00263   }
00264   return false;
00265 }
00266 
00267 
00268 //: Apply lens distortion to this vsol_point_2d in place
00269 // \return true if successful
00270 bool
00271 vpgl_vsol_lens_warp(vsol_point_2d_sptr& pt,
00272                     const vpgl_lens_distortion<double>& lens,
00273                     bool invert)
00274 {
00275   vgl_point_2d<double> new_pt;
00276   if (invert)
00277     new_pt = lens.undistort( vgl_homg_point_2d<double>(pt->get_p()) );
00278   else
00279     new_pt = lens.distort( vgl_homg_point_2d<double>(pt->get_p()) );
00280   pt->set_x(new_pt.x());
00281   pt->set_y(new_pt.y());
00282   return true;
00283 }
00284 
00285 
00286 //: Apply lens distortion to this vsol_line_2d in place
00287 // \return true if successful
00288 // \note only the end points are warped
00289 bool
00290 vpgl_vsol_lens_warp(vsol_line_2d_sptr& ln,
00291                     const vpgl_lens_distortion<double>& lens,
00292                     bool invert)
00293 {
00294   if (invert)
00295     vcl_cerr << "Warning: line invert not yet implemented in vpgl_vsol_lens_warp\n";
00296 
00297   vsol_point_2d_sptr p0=ln->p0(), p1=ln->p1();
00298   return vpgl_vsol_lens_warp(p0, lens) &&
00299          vpgl_vsol_lens_warp(p1, lens);
00300 }
00301 
00302 //: Apply lens distortion to this vsol_polyline_2d in place
00303 // \return true if successful
00304 // \note only the segment end points are warped
00305 bool
00306 vpgl_vsol_lens_warp(vsol_polyline_2d_sptr& pln,
00307                     const vpgl_lens_distortion<double>& lens,
00308                     bool invert)
00309 {
00310   if (invert)
00311     vcl_cerr << "Warning: polyline invert not yet implemented in vpgl_vsol_lens_warp\n";
00312 
00313   for (unsigned int i=0; i<pln->size(); ++i){
00314     vsol_point_2d_sptr p=pln->vertex(i);
00315     if (!vpgl_vsol_lens_warp(p, lens))
00316       return false;
00317   }
00318   return true;
00319 }
00320 
00321 
00322 //: Apply lens distortion to this vsol_digital_curve_2d in place
00323 // \return true if successful
00324 // \note only the sample points are warped
00325 bool
00326 vpgl_vsol_lens_warp(vsol_digital_curve_2d_sptr& dc,
00327                     const vpgl_lens_distortion<double>& lens,
00328                     bool invert)
00329 {
00330   if (invert)
00331     vcl_cerr << "Warning: curve invert not yet implemented in vpgl_vsol_lens_warp\n";
00332 
00333   for (unsigned int i=0; i<dc->size(); ++i) {
00334     vsol_point_2d_sptr p=dc->point(i);
00335     if (!vpgl_vsol_lens_warp(p, lens))
00336       return false;
00337   }
00338   return true;
00339 }
00340 
00341 
00342 //: Apply lens distortion to this vsol_polygon_2d in place
00343 // \return true if successful
00344 // \note only the segment end points are warped
00345 bool
00346 vpgl_vsol_lens_warp(vsol_polygon_2d_sptr& pg,
00347                     const vpgl_lens_distortion<double>& lens,
00348                     bool invert)
00349 {
00350   if (invert)
00351     vcl_cerr << "Warning: polygon invert not yet implemented in vpgl_vsol_lens_warp\n";
00352 
00353   for (unsigned int i=0; i<pg->size(); ++i){
00354     vsol_point_2d_sptr p=pg->vertex(i);
00355     if (!vpgl_vsol_lens_warp(p, lens))
00356       return false;
00357   }
00358   return true;
00359 }