core/vgui/vgui_soview2D.cxx
Go to the documentation of this file.
00001 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00002 #pragma implementation
00003 #endif
00004 //:
00005 // \file
00006 // \author Philip C. Pritchett, RRG, University of Oxford
00007 // \date   24 Mar 1999
00008 // \brief  See vgui_soview2D.h for a description of this file.
00009 
00010 #include "vgui_soview2D.h"
00011 
00012 #include <vcl_cmath.h>
00013 #include <vcl_iostream.h>
00014 
00015 #include <vgl/vgl_distance.h>
00016 #include <vnl/vnl_math.h> // for twopi
00017 #include <vil/vil_image_view_base.h>
00018 #include <vil/vil_new.h>
00019 #include <vil1/vil1_image.h>
00020 #include <vgui/vgui_range_map_params.h>
00021 #include <vgui/vgui_gl.h>
00022 #include <vgui/vgui_style.h>
00023 #include <vgui/vgui_section_buffer.h>
00024 #include <vgui/internals/vgui_draw_line.h>
00025 
00026 //--------------------------------------------------------------------------//
00027 
00028 vcl_ostream& vgui_soview2D_point::print(vcl_ostream& s) const
00029 {
00030   s << "[ vgui_soview2D_point " << x << ',' << y << ' ';
00031   return vgui_soview2D::print(s) << " ]";
00032 }
00033 
00034 void vgui_soview2D_point::draw() const
00035 {
00036 #if 0
00037   style->apply_point_size();
00038 #endif // 0
00039   glBegin(GL_POINTS);
00040     glVertex2f(x,y);
00041   glEnd();
00042 }
00043 
00044 void vgui_soview2D_point::draw_select() const
00045 {
00046   // It's much faster to draw a polygon than a point. (At least, it is
00047   // on Win2000 OpenGL.) For selection, we just need to draw some
00048   // little area in the vicinity of the point. We make the area really
00049   // small to account for large zoom factors. In principle, we should
00050   // take the zoom factor into account when determining the radius,
00051   // but that's too much trouble. The radius should be large enough
00052   // that it doesn't get swallowed up when added to x and to y.
00053 
00054   // This will allow a 10000x zoom before the "circle" gets bigger
00055   // than one pixel. Should be good enough!
00056   //
00057   float const rad = 0.0001f;
00058   glBegin(GL_POLYGON);
00059     glVertex2f( x - rad, y - rad );
00060     glVertex2f( x + rad, y - rad );
00061     glVertex2f( x + rad, y + rad );
00062     glVertex2f( x - rad, y + rad );
00063   glEnd();
00064 }
00065 
00066 float vgui_soview2D_point::distance_squared(float vx, float vy) const
00067 {
00068   float dx = x - vx;
00069   float dy = y - vy;
00070   return dx*dx + dy*dy;
00071 }
00072 
00073 void vgui_soview2D_point::get_centroid(float* vx, float* vy) const
00074 {
00075   *vx = x;
00076   *vy = y;
00077 }
00078 
00079 void vgui_soview2D_point::translate(float tx, float ty)
00080 {
00081   x += tx;
00082   y += ty;
00083 }
00084 
00085 //--------------------------------------------------------------------------//
00086 
00087 vcl_ostream& vgui_soview2D_lineseg::print(vcl_ostream& s) const
00088 {
00089   s << "[ vgui_soview2D_lineseg " << x0 << ',' << y0 << " -- " << x1 << ',' << y1 << ' ';
00090   return vgui_soview2D::print(s) << " ]";
00091 }
00092 
00093 void vgui_soview2D_lineseg::draw() const
00094 {
00095 #ifdef DEBUG
00096   vcl_cerr << "vgui_soview2D_lineseg::draw() line id=" << id << '\n';
00097 #endif
00098 
00099 #if 0
00100   glLineWidth(style->line_width);
00101 #endif // 0
00102   glBegin(GL_LINES);
00103   glVertex2f(x0,y0);
00104   glVertex2f(x1,y1);
00105   glEnd();
00106 }
00107 
00108 float vgui_soview2D_lineseg::distance_squared(float vx, float vy) const
00109 {
00110   // Here we explicitly cast some parameters to type float to help
00111   // the Borland compiler, which otherwise tries to use
00112   // vgl_distance2_to_linesegment<const float>, presumably because
00113   // this is a const member function so some of the parameters passed
00114   // to vgl_distance2_to_linesegment are effectively of type const
00115   // float.
00116   return (float)vgl_distance2_to_linesegment(x0, y0, x1, y1, vx, vy);
00117 }
00118 
00119 void vgui_soview2D_lineseg::get_centroid(float* vx, float* vy) const
00120 {
00121   *vx = (x0 + x1) / 2;
00122   *vy = (y0 + y1) / 2;
00123 }
00124 
00125 void vgui_soview2D_lineseg::translate(float tx, float ty)
00126 {
00127   x0 += tx;
00128   y0 += ty;
00129   x1 += tx;
00130   y1 += ty;
00131 }
00132 
00133 //--------------------------------------------------------------------------//
00134 
00135 vgui_soview2D_group::~vgui_soview2D_group()
00136 {
00137   for (unsigned int i=0; i< ls.size(); i++)
00138     if ( ls[i] )
00139       delete ls[i];
00140 
00141   // clear vector
00142   ls.clear();
00143 }
00144 
00145 void vgui_soview2D_group::set_style(const vgui_style_sptr& s)
00146 {
00147   for (unsigned int i=0; i< ls.size(); i++)
00148     if (!ls[i]->get_style())
00149       ls[i]->set_style(s);
00150 
00151   vgui_soview::set_style( s);
00152 }
00153 
00154 vcl_ostream& vgui_soview2D_group::print(vcl_ostream& s) const
00155 {
00156   s << "[ vgui_soview2D_group ";
00157 
00158   for (unsigned int i=0; i< ls.size(); i++)
00159     ls[i]->print(s);
00160 
00161   return vgui_soview2D::print(s) << " ]";
00162 }
00163 
00164 void vgui_soview2D_group::draw() const
00165 {
00166   for (unsigned int i=0; i< ls.size(); i++)
00167     ls[i]->draw();
00168 }
00169 
00170 void vgui_soview2D_group::draw_select() const
00171 {
00172   for (unsigned int i=0; i< ls.size(); i++)
00173     ls[i]->draw_select();
00174 }
00175 
00176 float vgui_soview2D_group::distance_squared(float vx, float vy) const
00177 {
00178   if (ls.size() == 0)
00179     return -1e30f;
00180 
00181   float min= ls[0]->distance_squared( vx, vy);
00182 
00183   for (unsigned int i=1; i< ls.size(); i++)
00184   {
00185     float d= ls[i]->distance_squared( vx, vy);
00186     if ( d< min ) min= d;
00187   }
00188 
00189   return min;
00190 }
00191 
00192 void vgui_soview2D_group::get_centroid(float* vx, float* vy) const
00193 {
00194   *vx = 0;
00195   *vy = 0;
00196   const int n = ls.size();
00197 
00198   for (int i=0; i < n; i++)
00199   {
00200     float cx, cy;
00201     ls[i]->get_centroid(&cx, &cy);
00202     *vx += cx;
00203     *vy += cy;
00204   }
00205 
00206   float s = 1.0f/n;
00207   *vx *= s;
00208   *vy *= s;
00209 }
00210 
00211 void vgui_soview2D_group::translate(float tx, float ty)
00212 {
00213   for (unsigned int i=0; i < ls.size(); i++)
00214     ls[i]->translate(tx, ty);
00215 }
00216 
00217 //--------------------------------------------------------------------------//
00218 
00219 vcl_ostream& vgui_soview2D_infinite_line::print(vcl_ostream& s) const
00220 {
00221   s << "[ vgui_soview2D_infinite_line " << a << ',' << b << ',' << c << ' ';
00222   return vgui_soview2D::print(s) << " ]";
00223 }
00224 
00225 void vgui_soview2D_infinite_line::draw() const
00226 {
00227   vgui_draw_line(a, b, c);
00228 }
00229 
00230 float vgui_soview2D_infinite_line::distance_squared(float vx, float vy) const
00231 {
00232   float tmp = a*vx + b*vy + c;
00233   return tmp*tmp/(a*a + b*b);
00234 }
00235 
00236 void vgui_soview2D_infinite_line::get_centroid(float* vx, float* vy) const
00237 {
00238   *vx = 0;
00239   *vy = 0;
00240 }
00241 
00242 void vgui_soview2D_infinite_line::translate(float tx, float ty)
00243 {
00244   c += a * tx + b * ty;
00245 }
00246 
00247 //--------------------------------------------------------------------------//
00248 
00249 const int vgui__CIRCLE2D_LIST = 1;
00250 
00251 void vgui_soview2D_circle::compile()
00252 {
00253   glNewList(vgui__CIRCLE2D_LIST, GL_COMPILE);
00254   glBegin(GL_LINE_LOOP);
00255   for (unsigned int i=0;i<100;i++)
00256   {
00257     double angle = vnl_math::twopi*0.01*i;
00258     glVertex2d(vcl_cos(angle), vcl_sin(angle));
00259   }
00260   glEnd();
00261   glEndList();
00262 }
00263 
00264 
00265 vcl_ostream& vgui_soview2D_circle::print(vcl_ostream& s) const
00266 {
00267   s << "[ vgui_soview2D_circle " << x << ',' << y << " r" << r << ' ';
00268   return vgui_soview2D::print(s) << " ]";
00269 }
00270 
00271 void vgui_soview2D_circle::draw() const
00272 {
00273   glBegin(GL_LINE_LOOP);
00274   for (unsigned int i=0;i<100;i++)
00275   {
00276     double angle = vnl_math::twopi*0.01*i;
00277     glVertex2d(x+r*vcl_cos(angle), y+r*vcl_sin(angle));
00278   }
00279   glEnd();
00280 }
00281 
00282 float vgui_soview2D_circle::distance_squared(float vx, float vy) const
00283 {
00284   float dx = x - vx;
00285   float dy = y - vy;
00286 
00287   // distance from point to centre
00288   float dcentre = vcl_sqrt(dx*dx + dy*dy);
00289 
00290   // signed distance from point to circumference
00291   float dcircum = dcentre - this->r;
00292 
00293   return dcircum * dcircum;
00294 }
00295 
00296 void vgui_soview2D_circle::get_centroid(float* vx, float* vy) const
00297 {
00298   *vx = x;
00299   *vy = y;
00300 }
00301 
00302 void vgui_soview2D_circle::translate(float tx, float ty)
00303 {
00304   x += tx;
00305   y += ty;
00306 }
00307 
00308 //--------------------------------------------------------------------------------//
00309 
00310 vcl_ostream& vgui_soview2D_ellipse::print(vcl_ostream& s) const
00311 {
00312   s << "[ vgui_soview2D_ellipse " << x << ',' << y
00313     << " w" << w << " h" << h << " phi" << phi << ' ';
00314   return vgui_soview2D::print(s) << " ]";
00315 }
00316 
00317 void vgui_soview2D_ellipse::draw() const
00318 {
00319   double px, py;
00320 
00321   glBegin(GL_LINE_LOOP);
00322   for (unsigned int i=0;i<100;i++)
00323   {
00324     double angle = vnl_math::twopi*0.01*i;
00325     px = w*vcl_cos(this->phi)*vcl_cos(angle) + h*vcl_sin(this->phi)*vcl_sin(angle);
00326     py = h*vcl_cos(this->phi)*vcl_sin(angle) - w*vcl_sin(this->phi)*vcl_cos(angle);
00327     glVertex2d(x+px, y+py);
00328   }
00329   glEnd();
00330 }
00331 
00332 //:
00333 // \todo not correctly implemented (assumes a circle)
00334 float vgui_soview2D_ellipse::distance_squared(float vx, float vy) const
00335 {
00336   return (vx - x)*(vx - x) + (vy - y)*(vy - y);
00337 }
00338 
00339 void vgui_soview2D_ellipse::get_centroid(float* vx, float* vy) const
00340 {
00341   *vx = x;
00342   *vy = y;
00343 }
00344 
00345 void vgui_soview2D_ellipse::translate(float tx, float ty)
00346 {
00347   x += tx;
00348   y += ty;
00349 }
00350 
00351 
00352 //--------------------------------------------------------------------------------//
00353 
00354 vgui_soview2D_linestrip::vgui_soview2D_linestrip(unsigned n_, float const *x_, float const *y_)
00355   : n(n_), x(new float[n]), y(new float[n])
00356 {
00357   for (unsigned i=0; i<n; ++i)
00358   {
00359     x[i] = x_[i];
00360     y[i] = y_[i];
00361   }
00362 }
00363 
00364 vgui_soview2D_linestrip::~vgui_soview2D_linestrip()
00365 {
00366   n=0;
00367   delete [] x; x=0;
00368   delete [] y; y=0;
00369 }
00370 
00371 void vgui_soview2D_linestrip::draw() const
00372 {
00373   glBegin(GL_LINE_STRIP);
00374   for (unsigned i=0; i<n; ++i)
00375     glVertex2f(x[i], y[i]);
00376   glEnd();
00377 }
00378 
00379 vcl_ostream& vgui_soview2D_linestrip::print(vcl_ostream&s) const { return s << "[ a linestrip. FIXME ]"; }
00380 
00381 float vgui_soview2D_linestrip::distance_squared(float vx, float vy) const
00382 {
00383   double tmp = vgl_distance_to_non_closed_polygon(x, y, this->n, vx, vy);
00384   return static_cast<float>(tmp*tmp);
00385 }
00386 
00387 void vgui_soview2D_linestrip::get_centroid(float* vx, float* vy) const
00388 {
00389   *vx = 0;
00390   *vy = 0;
00391   for (unsigned i=0; i<n; ++i)
00392   {
00393     *vx += x[i];
00394     *vy += y[i];
00395   }
00396   float s = 1.0f / float(n);
00397   *vx *= s;
00398   *vy *= s;
00399 }
00400 
00401 void vgui_soview2D_linestrip::translate(float tx, float ty)
00402 {
00403   for (unsigned i=0; i<n; ++i)
00404   {
00405     x[i] += tx;
00406     y[i] += ty;
00407   }
00408 }
00409 
00410 void vgui_soview2D_linestrip::set_size(unsigned nn)
00411 {
00412   if (nn < n) { n = nn; return; }
00413 
00414   // we know that n <= nn
00415   float *nx = new float[nn];
00416   float *ny = new float[nn];
00417   for (unsigned i=0; i<n; ++i)
00418   {
00419     nx[i] = x[i];
00420     ny[i] = y[i];
00421   }
00422 
00423   n = nn;
00424   delete [] x; x = nx;
00425   delete [] y; y = ny;
00426 }
00427 
00428 //--------------------------------------------------------------------------------//
00429 
00430 vgui_soview2D_polygon::vgui_soview2D_polygon(unsigned n_, float const *x_, float const *y_, bool fill)
00431   : n(n_), x(new float[n]), y(new float[n]), filled(fill)
00432 {
00433   for (unsigned i=0; i<n; ++i)
00434   {
00435     x[i] = x_[i];
00436     y[i] = y_[i];
00437   }
00438 }
00439 
00440 vgui_soview2D_polygon::~vgui_soview2D_polygon()
00441 {
00442   n=0;
00443   delete [] x; x=0;
00444   delete [] y; y=0;
00445 }
00446 
00447 void vgui_soview2D_polygon::draw() const
00448 {
00449   if(filled){
00450     glBegin(GL_POLYGON);
00451     for (unsigned i=0; i<n; ++i)
00452       glVertex2f(x[i], y[i]);
00453     glEnd();
00454   }else{
00455     glBegin(GL_LINE_LOOP);
00456     for (unsigned i=0; i<n; ++i)
00457       glVertex2f(x[i], y[i]);
00458     glEnd();
00459   }
00460 }
00461 
00462 vcl_ostream& vgui_soview2D_polygon::print(vcl_ostream&s) const { return s << "[ a polygon. FIXME ]"; }
00463 
00464 float vgui_soview2D_polygon::distance_squared(float vx, float vy) const
00465 {
00466   double tmp = vgl_distance_to_closed_polygon(x, y, this->n, vx, vy);
00467   return static_cast<float>(tmp*tmp);
00468 }
00469 
00470 void vgui_soview2D_polygon::get_centroid(float* vx, float* vy) const
00471 {
00472   *vx = 0;
00473   *vy = 0;
00474   for (unsigned i=0; i<n; ++i)
00475   {
00476     *vx += x[i];
00477     *vy += y[i];
00478   }
00479   float s = 1.0f / float(n);
00480   *vx *= s;
00481   *vy *= s;
00482 }
00483 
00484 void vgui_soview2D_polygon::translate(float tx, float ty)
00485 {
00486   for (unsigned i=0; i<n; ++i)
00487   {
00488     x[i] += tx;
00489     y[i] += ty;
00490   }
00491 }
00492 
00493 void vgui_soview2D_polygon::set_size(unsigned nn)
00494 {
00495   if (nn < n) { n = nn; return; }
00496 
00497   // we know that n <= nn
00498   float *nx = new float[nn];
00499   float *ny = new float[nn];
00500   for (unsigned i=0; i<n; ++i)
00501   {
00502     nx[i] = x[i];
00503     ny[i] = y[i];
00504   }
00505 
00506   n = nn;
00507   delete [] x; x = nx;
00508   delete [] y; y = ny;
00509 }
00510 
00511 
00512 //-----------------------------------------------------------
00513 
00514 vgui_soview2D_image::vgui_soview2D_image( float in_x, float in_y,
00515                                           vil1_image const& img,
00516                                           bool in_blend,
00517                                           GLenum format,
00518                                           GLenum type )
00519   : x_( in_x ),
00520     y_( in_y ),
00521     w_( img.width() ),
00522     h_( img.height() ),
00523     blend_( in_blend ),
00524     buffer_( new vgui_section_buffer( 0, 0, w_, h_, format, type ) )
00525 {
00526   buffer_->apply( img , (vgui_range_map_params*) 0);
00527 }
00528 
00529 vgui_soview2D_image::vgui_soview2D_image( float in_x, float in_y,
00530                                           vil_image_view_base const& img,
00531                                           bool in_blend,
00532                                           GLenum format,
00533                                           GLenum type )
00534   : x_( in_x ),
00535     y_( in_y ),
00536     w_( img.ni() ),
00537     h_( img.nj() ),
00538     blend_( in_blend ),
00539     buffer_( new vgui_section_buffer( 0, 0, w_, h_, format, type ) )
00540 {
00541   buffer_->apply( vil_new_image_resource_of_view( img ), (vgui_range_map_params*) 0);
00542 }
00543 
00544 vgui_soview2D_image::~vgui_soview2D_image()
00545 {
00546   delete buffer_;
00547 }
00548 
00549 void vgui_soview2D_image::draw() const
00550 {
00551   // Get the current blend state so we can restore it later
00552   GLboolean blend_on;
00553   glGetBooleanv( GL_BLEND, &blend_on );
00554 
00555   if ( blend_ ) {
00556     glEnable( GL_BLEND );
00557     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00558   }
00559   else
00560     glDisable( GL_BLEND );
00561 
00562   glTranslatef(  x_,  y_, 0.0f );
00563   buffer_->draw_as_image() || buffer_->draw_as_rectangle();
00564   glTranslatef( -x_, -y_, 0.0f );
00565 
00566   if ( blend_on )
00567     glEnable( GL_BLEND );
00568   else
00569     glDisable( GL_BLEND );
00570 }
00571 
00572 vcl_ostream& vgui_soview2D_image::print(vcl_ostream&s) const
00573 {
00574   return s << "[ vgui_soview2D_image "<<w_<<'x'<<h_<<", blend="<<blend_<<" ]";
00575 }
00576 
00577 float vgui_soview2D_image::distance_squared(float vx, float vy) const
00578 {
00579   float dx = (x_ + (w_ / 2.0f)) - vx;
00580   float dy = (y_ + (h_ / 2.0f)) - vy;
00581   return dx*dx + dy*dy;
00582 }
00583 
00584 void vgui_soview2D_image::get_centroid(float* vx, float* vy) const
00585 {
00586   float x1 = x_ + (w_ / 2.0f);
00587   float y1 = y_ + (h_ / 2.0f);
00588 
00589   *vx = x1;
00590   *vy = y1;
00591 }
00592 
00593 void vgui_soview2D_image::translate(float tx, float ty)
00594 {
00595     x_ += tx;
00596     y_ += ty;
00597 }