00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008 #include "vdgl_edgel_chain.h"
00009 #include <vgl/vgl_distance.h>
00010 #include <vcl_cassert.h>
00011 #include <vcl_cmath.h>
00012 #include <vcl_cstdlib.h>
00013 #include <vcl_iostream.h>
00014
00015 vdgl_edgel_chain::vdgl_edgel_chain( const double x0, const double y0,
00016 const double x1, const double y1)
00017 {
00018 bool init = true, done = false;
00019 double x, y;
00020 while (this->line_gen(x0, y0, x1, y1, init, done, x, y))
00021 es_.push_back(vdgl_edgel( x, y));
00022 }
00023
00024 bool vdgl_edgel_chain::add_edgel( const vdgl_edgel &e)
00025 {
00026 es_.push_back( e);
00027
00028
00029 notify_change();
00030
00031 return true;
00032 }
00033
00034 bool vdgl_edgel_chain::set_edgel( int index, const vdgl_edgel &e)
00035 {
00036 assert(index>=0);
00037 if ( (unsigned int)index >= es_.size())
00038 return false;
00039
00040 es_[index]= e;
00041
00042 return true;
00043 }
00044
00045 void vdgl_edgel_chain::notify_change()
00046 {
00047
00048 vul_timestamp::touch();
00049 }
00050
00051 bool vdgl_edgel_chain::add_edgels( const vcl_vector<vdgl_edgel> &es, int index)
00052 {
00053 assert(index>=0);
00054 if ( (unsigned int)index> es_.size())
00055 return false;
00056 else if (es_.size()== 0)
00057 es_= es;
00058 else
00059 {
00060 vcl_vector<vdgl_edgel> temp;
00061 for (int i=0; i< index; i++)
00062 temp.push_back( es_[i]);
00063
00064 for (unsigned int i=0; i< es.size(); i++)
00065 temp.push_back( es[i]);
00066
00067 for (unsigned int i=index; i< es_.size(); i++)
00068 temp.push_back( es_[i]);
00069
00070 es_= temp;
00071 }
00072
00073
00074 notify_change();
00075
00076 return true;
00077 }
00078
00079 vcl_ostream& operator<<(vcl_ostream& s, const vdgl_edgel_chain& p)
00080 {
00081 s << "<vdgl_edgel_chain (";
00082 if ( p.es_.size() > 0)
00083 s << p.es_[0];
00084 for (unsigned int i=1; i< p.es_.size(); ++i)
00085 s << ", " << p.es_[i];
00086
00087 return s << ')';
00088 }
00089
00090 inline static double sq_dist(vdgl_edgel const& e, double x, double y)
00091 {
00092 double dx = e.get_x() - x, dy = e.get_y() - y;
00093 return dx*dx+dy+dy;
00094 }
00095
00096 vdgl_edgel_chain_sptr vdgl_edgel_chain::extract_subchain(int start, int end)
00097 {
00098 vcl_vector<vdgl_edgel> e;
00099 ++end;
00100 if (end > (int)size()) end = size();
00101 if (start < 0) start = 0;
00102 for (int i=start; i<end; ++i)
00103 e.push_back(edgel(i));
00104 return new vdgl_edgel_chain(e);
00105 }
00106
00107 bool vdgl_edgel_chain::split( double x, double y,
00108 vdgl_edgel_chain_sptr &ec1,
00109 vdgl_edgel_chain_sptr &ec2)
00110 {
00111 int split_index = -1;
00112 const int n = size();
00113 double d = 1e10;
00114 for (int i=0;i+1<n;i++) {
00115 double x1=edgel(i ).get_x(), y1=edgel(i ).get_y(),
00116 x2=edgel(i+1).get_x(), y2=edgel(i+1).get_y();
00117 double e = vgl_distance2_to_linesegment(x1,y1,x2,y2,x,y);
00118 if (e < d) { d=e; split_index = i+1;}
00119 }
00120
00121 if (split_index < 0) return false;
00122
00123 if (split_index == 1 && d == sq_dist(edgel(0),x,y)) split_index = 0;
00124 if (split_index == n-1 && d == sq_dist(edgel(n-1),x,y)) split_index = n;
00125
00126 if (split_index > 0) ec1 = this->extract_subchain(0, split_index-1);
00127 if (split_index < n) ec2 = this->extract_subchain(split_index, n-1);
00128 return split_index > 0 && split_index < n;
00129 }
00130
00131
00132
00133 bool vdgl_edgel_chain::line_gen(double xs, double ys, double xe, double ye,
00134 bool& init, bool& done,
00135 double& x, double& y)
00136 {
00137 assert(xs >= 0.0); assert(ys >= 0.0);
00138 const double pix_edge = 1.0;
00139 static double xi=0.0, yi=0.0;
00140 if (init)
00141 {
00142 xi = xs;
00143 yi = ys;
00144 x = (double)(unsigned int)(xi/pix_edge);
00145 y = (double)(unsigned int)(yi/pix_edge);
00146 init = false;
00147 return true;
00148 }
00149 if (done) return false;
00150 double dx = xe-xs;
00151 double dy = ye-ys;
00152 double mag = vcl_sqrt(dx*dx + dy*dy);
00153 if (mag<pix_edge)
00154 {
00155 x = (double)(unsigned int)xe;
00156 y = (double)(unsigned int)ye;
00157 done = true;
00158 return true;
00159 }
00160 double delta = (0.5*pix_edge)/mag;
00161
00162 int xp = int(xi/pix_edge);
00163 int yp = int(yi/pix_edge);
00164
00165 for (int i = 0; i<3; i++)
00166 {
00167 xi += dx*delta;
00168 yi += dy*delta;
00169
00170 if ((xe>=xs&&xi>xe)||(xe<=xs&&xi<xe)||(ye>=ys&&yi>ye)||(ye<=ys&&yi<ye))
00171 {
00172 x = xe; y = ye;
00173 done = true;
00174 return true;
00175 }
00176
00177 x = (xi/pix_edge);
00178 y = (yi/pix_edge);
00179 double dx1 = (double)(int(x)-xp), dy1 = (double)(int(y)-yp);
00180 if (vcl_abs(dx1)>(.5*pix_edge)||vcl_abs(dy1)>(.5*pix_edge))
00181 return true;
00182 }
00183 vcl_cout << "in vdgl_edgel_chain::line_gen(..) - shouldn't happen\n";
00184 return false;
00185 }
00186
00187 bool operator==( const vdgl_edgel_chain &ec1, const vdgl_edgel_chain &ec2)
00188 {
00189 int size1 = ec1.size(), size2 = ec2.size();
00190 if (size1 != size2)
00191 return false;
00192 for (int i = 0; i<size1; i++)
00193 if (!(ec1[i] == ec2[i]))
00194 return false;
00195 return true;
00196 }
00197
00198 bool operator!=( const vdgl_edgel_chain &ec1, const vdgl_edgel_chain &ec2)
00199 {
00200 return !(ec1==ec2);
00201 }
00202
00203
00204
00205
00206
00207
00208 void vdgl_edgel_chain::b_write(vsl_b_ostream &os) const
00209 {
00210 vsl_b_write(os, version());
00211 vsl_b_write(os, es_.size());
00212 for (unsigned int i = 0; i<es_.size(); i++)
00213 {
00214 vsl_b_write(os, es_[i].get_x());
00215 vsl_b_write(os, es_[i].get_y());
00216 vsl_b_write(os, es_[i].get_grad());
00217 vsl_b_write(os, es_[i].get_theta());
00218 }
00219 }
00220
00221 void vdgl_edgel_chain::b_read(vsl_b_istream &is)
00222 {
00223 if (!is)
00224 return;
00225 short ver;
00226 vsl_b_read(is, ver);
00227 switch (ver)
00228 {
00229 case 1:
00230 {
00231 int size =0; vsl_b_read(is, size);
00232 for (int i = 0; i<size; i++)
00233 {
00234 double x=0, y=0, grad=-1, theta=0;
00235 vsl_b_read(is, x);
00236 vsl_b_read(is, y);
00237 vsl_b_read(is, grad);
00238 vsl_b_read(is, theta);
00239 vdgl_edgel e(x, y, grad, theta);
00240 this->add_edgel(e);
00241 }
00242 return;
00243 }
00244 default:
00245 assert(!"Invalid version");
00246 return;
00247 }
00248 }
00249
00250 short vdgl_edgel_chain::version() const
00251 {
00252 return 1;
00253 }
00254
00255
00256 void vdgl_edgel_chain::print_summary(vcl_ostream &os) const
00257 {
00258 os << *this;
00259 }
00260
00261
00262 void
00263 vsl_b_write(vsl_b_ostream &os, const vdgl_edgel_chain* e)
00264 {
00265 if (!e){
00266 vsl_b_write(os, false);
00267 }
00268 else{
00269 vsl_b_write(os,true);
00270 e->b_write(os);
00271 }
00272 }
00273
00274
00275 void
00276 vsl_b_read(vsl_b_istream &is, vdgl_edgel_chain* &ec)
00277 {
00278 delete ec;
00279 bool not_null_ptr;
00280 vsl_b_read(is, not_null_ptr);
00281 if (not_null_ptr) {
00282 ec = new vdgl_edgel_chain();
00283 ec->b_read(is);
00284 }
00285 else
00286 ec = 0;
00287 }
00288
00289
00290 void
00291 vsl_print_summary(vcl_ostream &os, const vdgl_edgel_chain* e)
00292 {
00293 os << *e;
00294 }
00295