00001 #ifndef vil_quad_distance_function_h_
00002 #define vil_quad_distance_function_h_
00003
00004
00005
00006
00007
00008 #include <vil/vil_image_view.h>
00009 #include <vcl_vector.h>
00010 #include <vcl_cassert.h>
00011
00012
00013
00014
00015 inline void vil_update_parabola_set(vcl_vector<double>& x,
00016 vcl_vector<double>& y,
00017 vcl_vector<double>& z, double a,
00018 double x0, double y0, double n)
00019 {
00020 unsigned int k=x.size()-1;
00021 while (true)
00022 {
00023
00024
00025 double new_z = 0.5*((y0-y[k])/a + (x0*x0-x[k]*x[k]))/(x0-x[k]);
00026 if (new_z>n) return;
00027 if (new_z>z[k])
00028 {
00029 x.push_back(x0);
00030 y.push_back(y0);
00031 z.push_back(new_z);
00032 return;
00033 }
00034 if (k==0)
00035 {
00036
00037 x[0]=x0; y[0]=y0; z[0]=0.0;
00038 return;
00039 }
00040
00041
00042 x.erase(x.begin()+k);
00043 y.erase(y.begin()+k);
00044 z.erase(z.begin()+k);
00045 --k;
00046 }
00047 }
00048
00049
00050
00051
00052
00053
00054
00055 template<class srcT>
00056 inline void vil_quad_envelope(const srcT* src,vcl_ptrdiff_t s_step,
00057 unsigned int n,
00058 vcl_vector<double>& x,
00059 vcl_vector<double>& y,
00060 vcl_vector<double>& z, double a)
00061 {
00062 x.resize(1); x[0]=0.0;
00063 y.resize(1); y[0]=double(*src);
00064 z.resize(1); z[0]=0.0;
00065 src+=s_step;
00066 for (unsigned int x0=1;x0<n;++x0,src+=s_step)
00067 {
00068 vil_update_parabola_set(x,y,z,a,x0,double(*src),double(n));
00069 }
00070 z.push_back(n);
00071 }
00072
00073
00074
00075
00076
00077 template<class destT>
00078 inline void vil_sample_quad_envelope(const vcl_vector<double>& x,
00079 const vcl_vector<double>& y,
00080 const vcl_vector<double>& z, double a,
00081 destT* dest, vcl_ptrdiff_t d_step,
00082 unsigned int n)
00083 {
00084 unsigned int k=0;
00085 for (unsigned int i=0;i<n;++i,dest+=d_step)
00086 {
00087 while (z[k+1]<i) ++k;
00088 *dest = destT(y[k] + a*(i-x[k])*(i-x[k]));
00089 }
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 template<class destT, class iT>
00101 inline void vil_sample_quad_envelope_with_pos(const vcl_vector<double>& x,
00102 const vcl_vector<double>& y,
00103 const vcl_vector<double>& z,
00104 double a,
00105 destT* dest, vcl_ptrdiff_t d_step,
00106 unsigned int n,
00107 iT* pos, vcl_ptrdiff_t p_step)
00108 {
00109 unsigned int k=0;
00110 for (unsigned int i=0;i<n;++i,dest+=d_step,pos+=p_step)
00111 {
00112 while (z[k+1]<i) ++k;
00113 *dest = destT(y[k] + a*(i-x[k])*(i-x[k]));
00114 *pos = iT(x[k]+0.5);
00115 }
00116 }
00117
00118
00119
00120
00121
00122
00123
00124 template<class srcT, class destT>
00125 inline void vil_quad_distance_function_1D(const srcT* src,vcl_ptrdiff_t s_step,
00126 unsigned int n,
00127 double a,
00128 destT* dest, vcl_ptrdiff_t d_step)
00129 {
00130 vcl_vector<double> x,y,z;
00131 vil_quad_envelope(src,s_step,n,x,y,z,a);
00132 vil_sample_quad_envelope(x,y,z,a,dest,d_step,n);
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142 template<class srcT, class destT, class posT>
00143 inline void vil_quad_distance_function_1D(const srcT* src,vcl_ptrdiff_t s_step,
00144 unsigned int n,
00145 double a,
00146 destT* dest, vcl_ptrdiff_t d_step,
00147 posT* pos, vcl_ptrdiff_t p_step)
00148 {
00149 vcl_vector<double> x,y,z;
00150 vil_quad_envelope(src,s_step,n,x,y,z,a);
00151 vil_sample_quad_envelope_with_pos(x,y,z,a,dest,d_step,n, pos,p_step);
00152 }
00153
00154
00155
00156
00157
00158 template<class srcT, class destT>
00159 inline void vil_quad_distance_function(const vil_image_view<srcT>& src,
00160 double ai, double aj,
00161 vil_image_view<destT>& dest)
00162 {
00163 assert(src.nplanes()==1);
00164 unsigned int ni=src.ni(),nj=src.nj();
00165 dest.set_size(ni,nj);
00166 vil_image_view<destT> tmp(ni,nj);
00167 vcl_ptrdiff_t s_istep = src.istep(), s_jstep = src.jstep();
00168 vcl_ptrdiff_t t_istep = tmp.istep(), t_jstep = tmp.jstep();
00169 vcl_ptrdiff_t d_istep = dest.istep(), d_jstep = dest.jstep();
00170
00171 const srcT* s_row = src.top_left_ptr();
00172 destT* t_row = tmp.top_left_ptr();
00173
00174 vcl_vector<double> x,y,z;
00175
00176
00177 for (unsigned int j=0;j<nj;++j, s_row+=s_jstep, t_row+=t_jstep)
00178 {
00179 vil_quad_envelope(s_row,s_istep,ni,x,y,z,ai);
00180 vil_sample_quad_envelope(x,y,z,ai,t_row,t_istep,ni);
00181 }
00182
00183 destT* t_col = tmp.top_left_ptr();
00184 destT* d_col = dest.top_left_ptr();
00185 for (unsigned int i=0;i<ni;++i, d_col+=d_istep, t_col+=t_istep)
00186 {
00187 vil_quad_envelope(t_col,t_jstep,nj,x,y,z,aj);
00188 vil_sample_quad_envelope(x,y,z,aj,d_col,d_jstep,nj);
00189 }
00190 }
00191
00192
00193
00194
00195
00196
00197 template<class srcT, class destT, class posT>
00198 inline void vil_quad_distance_function(const vil_image_view<srcT>& src,
00199 double ai, double aj,
00200 vil_image_view<destT>& dest,
00201 vil_image_view<posT>& pos)
00202 {
00203 assert(src.nplanes()==1);
00204 unsigned int ni=src.ni(), nj=src.nj();
00205 dest.set_size(ni,nj);
00206 pos.set_size(ni,nj,2);
00207 vil_image_view<destT> tmp(ni,nj);
00208 vil_image_view<posT> tmp_pos(ni,nj);
00209 vcl_ptrdiff_t s_istep = src.istep(), s_jstep = src.jstep();
00210 vcl_ptrdiff_t t_istep = tmp.istep(), t_jstep = tmp.jstep();
00211 vcl_ptrdiff_t d_istep = dest.istep(), d_jstep = dest.jstep();
00212 vcl_ptrdiff_t tp_istep = tmp_pos.istep(), tp_jstep = tmp_pos.jstep();
00213 vcl_ptrdiff_t p_istep = pos.istep(), p_jstep = pos.jstep();
00214
00215 const srcT* s_row = src.top_left_ptr();
00216 destT* t_row = tmp.top_left_ptr();
00217 posT* tp_row = tmp_pos.top_left_ptr();
00218
00219 vcl_vector<double> x,y,z;
00220
00221
00222 for (unsigned int j=0;j<nj;++j,s_row+=s_jstep,t_row+=t_jstep,tp_row+=tp_jstep)
00223 {
00224 vil_quad_envelope(s_row,s_istep,ni,x,y,z,ai);
00225 vil_sample_quad_envelope_with_pos(x,y,z,ai,t_row,t_istep,ni,tp_row,tp_istep);
00226 }
00227
00228 destT* t_col = tmp.top_left_ptr();
00229 destT* d_col = dest.top_left_ptr();
00230 posT* pi_col = pos.top_left_ptr();
00231 posT* pj_col = pi_col + pos.planestep();
00232 posT* tp_col = tmp_pos.top_left_ptr();
00233
00234 for (unsigned int i=0;i<ni;++i, d_col+=d_istep, t_col+=t_istep,
00235 pi_col+=p_istep, pj_col+=p_istep,
00236 tp_col+=tp_istep)
00237 {
00238 vil_quad_envelope(t_col,t_jstep,nj,x,y,z,aj);
00239 vil_sample_quad_envelope_with_pos(x,y,z,aj,d_col,d_jstep,nj,pj_col,p_jstep);
00240
00241 for (unsigned int j=0;j<nj;++j)
00242 {
00243 pi_col[j*p_jstep] = tp_col[pj_col[j*p_jstep]*tp_jstep];
00244 }
00245 }
00246 }
00247
00248 #endif