contrib/gel/vmal/vmal_operators.cxx
Go to the documentation of this file.
00001 // This is gel/vmal/vmal_operators.cxx
00002 #include "vmal_operators.h"
00003 #include <vcl_cmath.h>
00004 #include <vnl/vnl_double_2.h>
00005 #include <vnl/vnl_cross.h>
00006 
00007 vmal_operators::vmal_operators()
00008 {
00009 }
00010 
00011 vmal_operators::~vmal_operators()
00012 {
00013 }
00014 
00015 //Project the point (x0,y0) on the line [(ax,ay),(bx,by)]. (x,y) are
00016 //the coordinates of the projected. If (x,y) does not belong to the
00017 //segment, it sets (x,y) to (-1,-1). The function returns the distance
00018 //between the point and its projected.
00019 double vmal_operators::project_point(double x0,double y0,
00020                                      double ax,double ay,
00021                                      double bx,double by,
00022                                      double *x,double *y)
00023 {
00024   *x=0;
00025   *y=0;
00026   double n1=bx-ax;
00027   double n2=by-ay;
00028   double norm=n1*n1+n2*n2;
00029   if (norm!=0)
00030   {
00031     double resy=-(ax*n1*n2-ay*n1*n1-x0*n1*n2-y0*n2*n2)/norm;
00032     double resx= (ax*n2*n2-ay*n1*n2+x0*n1*n1+y0*n1*n2)/norm;
00033 
00034     if (((ax-resx)*(bx-resx)+(ay-resy)*(by-resy))>0)
00035     {
00036       *x=-1;
00037       *y=-1;
00038     }
00039     else
00040     {
00041       *x=resx;
00042       *y=resy;
00043     }
00044       return vcl_sqrt((resx-x0)*(resx-x0)+(resy-y0)*(resy-y0));
00045   }
00046 
00047   return -1;
00048 }
00049 
00050 
00051 bool vmal_operators::project_point(vnl_double_3 &x,
00052                                    vnl_double_3 &a,
00053                                    vnl_double_3 &b,
00054                                    vnl_double_3 &px)
00055 {
00056   double ax=a[0]/a[2];
00057   double ay=a[1]/a[2];
00058   double bx=b[0]/b[2];
00059   double by=b[1]/b[2];
00060   double x0=x[0]/x[2];
00061   double y0=x[1]/x[2];
00062 
00063   double n1=bx-ax;
00064   double n2=by-ay;
00065   double norm=n1*n1+n2*n2;
00066 
00067   double resy=-(ax*n1*n2-ay*n1*n1-x0*n1*n2-y0*n2*n2)/norm;
00068   double resx= (ax*n2*n2-ay*n1*n2+x0*n1*n1+y0*n1*n2)/norm;
00069   px[0]=resx;
00070   px[1]=resy;
00071   px[2]=1;
00072 
00073   return ((ax-resx)*(bx-resx)+(ay-resy)*(by-resy))<=0;
00074 }
00075 
00076 //
00077 bool vmal_operators::cross_seg(double f1x,double f1y,double f2x,double f2y,//first segment
00078                                double s1x,double s1y,double s2x,double s2y)//second segment
00079 {
00080   //compute the directors vectors
00081   double nsx=s2x-s1x;
00082   double nsy=s2y-s1y;
00083 
00084   double nfx=f2x-f1x;
00085   double nfy=f2y-f1y;
00086 
00087   double df=-f1x*nfy+f1y*nfx;
00088   double ds=-s1x*nsy+s1y*nsx;
00089 
00090   //compute the determinant
00091   double det=nsy*nfx-nsx*nfy;
00092   if (det==0)
00093   return false;
00094 
00095   //compute the intersection point
00096   double interx=(-nfx*ds+nsx*df)/det;
00097   double intery=(nsy*df-ds*nfy)/det;
00098 
00099   // test if the intersection point belongs to the segments
00100   return ((((s1x-interx)*(s2x-interx)+(s1y-intery)*(s2y-intery)) < 0) &&
00101       (((f1x-interx)*(f2x-interx)+(f1y-intery)*(f2y-intery)) < 0));
00102 }
00103 
00104 
00105 bool vmal_operators::line_cross_seg(vnl_double_3 start_seg,
00106                                     vnl_double_3 end_seg,
00107                                     vnl_double_3 & line_equ,
00108                                     vnl_double_3 & inter,
00109                                     double &alpha)
00110 {
00111   start_seg[0]=start_seg[0]/start_seg[2];
00112   start_seg[1]=start_seg[1]/start_seg[2];
00113   start_seg[2]=1;
00114 
00115   end_seg[0]=end_seg[0]/end_seg[2];
00116   end_seg[1]=end_seg[1]/end_seg[2];
00117   end_seg[2]=1;
00118 
00119   vnl_double_3 seg_equ;
00120   seg_equ[0]=end_seg[1]-start_seg[1];
00121   seg_equ[1]=-(end_seg[0]-start_seg[0]);
00122   seg_equ[2]=-(seg_equ[0]*start_seg[0]+
00123          seg_equ[1]*start_seg[1]);
00124 
00125   inter=vnl_cross_3d(line_equ,seg_equ);
00126   inter[0]=inter[0]/inter[2];
00127   inter[1]=inter[1]/inter[2];
00128   inter[2]=1;
00129 
00130   vnl_double_2 vect_line(-line_equ[1], line_equ[0]);
00131   vnl_double_2 vect_seg(-seg_equ[1], -seg_equ[0]);
00132 
00133   alpha=angle(vect_line,vect_seg);
00134 
00135   return ((start_seg[0]-inter[0])*(end_seg[0]-inter[0])+
00136           (start_seg[1]-inter[1])*(end_seg[1]-inter[1])) < 0;
00137 }