core/vgui/vgui_easy2D_tableau.cxx
Go to the documentation of this file.
00001 // This is core/vgui/vgui_easy2D_tableau.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \brief  See vgui_easy2D_tableau.h for a description of this file.
00008 // \author Philip C. Pritchett, RRG, University of Oxford
00009 // \date   24 Sep 1999
00010 //
00011 // \verbatim
00012 //  Modifications
00013 //   24-SEP-1999 P.Pritchett - Initial version.
00014 // \endverbatim
00015 
00016 #include "vgui_easy2D_tableau.h"
00017 
00018 #include <vcl_vector.h>
00019 #include <vcl_cassert.h>
00020 #include <vcl_cstdlib.h> // for abort
00021 
00022 #include <vxl_config.h> // for vxl_byte
00023 
00024 #include <vul/vul_psfile.h>
00025 #include <vnl/vnl_math.h>
00026 
00027 #include <vil1/vil1_image.h>
00028 #include <vil1/vil1_pixel.h>
00029 
00030 #include <vil/vil_image_view.h>
00031 #include <vil/vil_image_resource.h>
00032 
00033 #include <vgui/vgui_event.h>
00034 #include <vgui/vgui_macro.h>
00035 #include <vgui/vgui_soview2D.h>
00036 #include <vgui/vgui_displaylist2D_tableau.h>
00037 #include <vgui/vgui_image_tableau.h>
00038 #include <vgui/vgui_style.h>
00039 
00040 #ifdef DEBUG
00041 #include <vil/vil_save.h>
00042 #endif
00043 
00044 static bool debug = false;
00045 
00046 vgui_easy2D_tableau::vgui_easy2D_tableau(const char* n) : image_slot(this), name_(n), style_(vgui_style::new_style())
00047 {
00048   style_->rgba[0] = 1.0f;
00049   style_->rgba[1] = 1.0f;
00050   style_->rgba[2] = 0.0f;
00051 
00052   style_->line_width = 1;
00053   style_->point_size = 3;
00054 }
00055 
00056 
00057 vgui_easy2D_tableau::vgui_easy2D_tableau(vgui_image_tableau_sptr const& i, const char* n)
00058   : image_slot(this,i), image_image(i), name_(n), style_(vgui_style::new_style())
00059 {
00060   style_->rgba[0] = 1.0f;
00061   style_->rgba[1] = 1.0f;
00062   style_->rgba[2] = 0.0f;
00063 
00064   style_->line_width = 1;
00065   style_->point_size = 3;
00066 }
00067 
00068 
00069 vgui_easy2D_tableau::vgui_easy2D_tableau(vgui_tableau_sptr const& i, const char* n)
00070   : image_slot(this,i), name_(n), style_(vgui_style::new_style())
00071 {
00072   style_->rgba[0] = 1.0f;
00073   style_->rgba[1] = 1.0f;
00074   style_->rgba[2] = 0.0f;
00075 
00076   style_->line_width = 1;
00077   style_->point_size = 3;
00078 }
00079 
00080 
00081 bool vgui_easy2D_tableau::handle(vgui_event const& e)
00082 {
00083   if (image_slot && (e.type != vgui_DRAW || gl_mode != GL_SELECT))
00084     image_slot.handle(e);
00085 
00086   return vgui_displaylist2D_tableau::handle(e);
00087 }
00088 
00089 vcl_string vgui_easy2D_tableau::file_name() const
00090 {
00091   if (image_slot)
00092     return type_name() + "[" + name_ + ",i=" + image_slot->file_name() + "]";
00093   else
00094     return name_;
00095 }
00096 
00097 
00098 vcl_string vgui_easy2D_tableau::pretty_name() const
00099 {
00100   if (image_slot)
00101     return type_name() + "[" + name_ + ",i=" + image_slot->file_name() + "]";
00102   else
00103     return type_name() + "[" + name_ + ",i=null]";
00104 }
00105 
00106 vcl_string vgui_easy2D_tableau::type_name() const
00107 {
00108   return "vgui_easy2D_tableau";
00109 }
00110 
00111 //: Set the child tableau to be the given image_tableau.
00112 void vgui_easy2D_tableau::set_image(vcl_string const& fn)
00113 {
00114   image_image->set_image(fn.c_str());
00115 }
00116 
00117 //: Set the child tableau to be the given tableau.
00118 void vgui_easy2D_tableau::set_child(vgui_tableau_sptr const& i)
00119 {
00120   if (i->type_name() != "vgui_image_tableau" &&
00121       i->type_name() != "xcv_image_tableau")
00122     vgui_macro_warning << "assigning what seems like a non-image to my child : i = " << i << vcl_endl;
00123   image_slot.assign(i);
00124 }
00125 
00126 //: Set the colour of objects to the given red, green, blue, alpha values.
00127 void vgui_easy2D_tableau::set_foreground(float r, float g, float b, float a)
00128 {
00129   // create a new style object so that already added objects don't
00130   // suddenly change
00131   style_ = vgui_style::new_style( style_ );
00132   style_->rgba[0] = r;
00133   style_->rgba[1] = g;
00134   style_->rgba[2] = b;
00135   style_->rgba[3] = a;
00136 }
00137 
00138 //: Set the width of lines to the given width.
00139 void vgui_easy2D_tableau::set_line_width(float w)
00140 {
00141   // create a new style object so that already added objects don't
00142   // suddenly change
00143   style_ = vgui_style::new_style( style_ );
00144   style_->line_width = w;
00145 }
00146 
00147 //: Set the radius of points to the given radius.
00148 void vgui_easy2D_tableau::set_point_radius(float r)
00149 {
00150   // create a new style object so that already added objects don't
00151   // suddenly change
00152   style_ = vgui_style::new_style( style_ );
00153   style_->point_size = r;
00154 }
00155 
00156 //: Add the given two-dimensional object to the display.
00157 void vgui_easy2D_tableau::add(vgui_soview2D* object)
00158 {
00159   object->set_style(style_);
00160   vgui_displaylist2D_tableau::add(object);
00161 }
00162 
00163 //: Add a point at the given position to the display.
00164 vgui_soview2D_point* vgui_easy2D_tableau::add_point(float x, float y)
00165 {
00166   vgui_soview2D_point *obj = new vgui_soview2D_point;
00167 
00168   obj->x = x;
00169   obj->y = y;
00170   add(obj);
00171   return obj;
00172 }
00173 
00174 //: Add a finite line with the given start and end points to the display.
00175 //  Note that this will be added as a vgui_lineseg (not vgui_line - which doesn't exist).
00176 vgui_soview2D_lineseg* vgui_easy2D_tableau::add_line(float x0, float y0, float x1, float y1)
00177 {
00178   vgui_soview2D_lineseg *obj = new vgui_soview2D_lineseg;
00179 
00180   obj->x0 = x0;
00181   obj->y0 = y0;
00182   obj->x1 = x1;
00183   obj->y1 = y1;
00184 
00185   add(obj);
00186   return obj;
00187 }
00188 
00189 //: Add an infinite line (ax + by +c = 0) to the display.
00190 vgui_soview2D_infinite_line* vgui_easy2D_tableau::add_infinite_line(float a, float b, float c)
00191 {
00192   vgui_soview2D_infinite_line *obj = new vgui_soview2D_infinite_line;
00193 
00194   obj->a = a;
00195   obj->b = b;
00196   obj->c = c;
00197 
00198   add(obj);
00199   return obj;
00200 }
00201 
00202 //: Add a circle with the given centre and radius to the display.
00203 vgui_soview2D_circle* vgui_easy2D_tableau::add_circle(float x, float y, float r)
00204 {
00205   vgui_soview2D_circle *obj = new vgui_soview2D_circle;
00206 
00207   obj->x = x;
00208   obj->y = y;
00209   obj->r = r;
00210 
00211   add(obj);
00212   return obj;
00213 }
00214 
00215 vgui_soview2D_ellipse* vgui_easy2D_tableau::add_ellipse(float x, float y, float w, float h, float phi)
00216 {
00217   vgui_soview2D_ellipse *obj = new vgui_soview2D_ellipse;
00218 
00219   obj->x = x;
00220   obj->y = y;
00221   obj->w = w;
00222   obj->h = h;
00223   obj->phi = phi;
00224 
00225   add(obj);
00226   return obj;
00227 }
00228 
00229 //: Add a point with the given projective coordinates.
00230 vgui_soview2D_point* vgui_easy2D_tableau::add_point_3dv(double const p[3])
00231 {
00232   return add_point(float(p[0]/p[2]), float(p[1]/p[2]));
00233 }
00234 
00235 //: Add a line with the given projective start and end points.
00236 vgui_soview2D_lineseg* vgui_easy2D_tableau::add_line_3dv_3dv(double const p[3], double const q[3])
00237 {
00238   return add_line(float(p[0]/p[2]), float(p[1]/p[2]),
00239                   float(q[0]/q[2]), float(q[1]/q[2]));
00240 }
00241 
00242 //: Add an infinite line with the given projective coordinates.
00243 vgui_soview2D_infinite_line* vgui_easy2D_tableau::add_infinite_line_3dv(double const l[3])
00244 {
00245   return add_infinite_line(float(l[0]), float(l[1]), float(l[2]));
00246 }
00247 
00248 //: Add a circle with the given centre (in projective coords) and radius to the display.
00249 vgui_soview2D_circle* vgui_easy2D_tableau::add_circle_3dv(double const point[3], float r)
00250 {
00251   return add_circle(float(point[0]/point[2]), float(point[1]/point[2]), r);
00252 }
00253 
00254 //: Add a linestrip with the given n vertices to the display.
00255 vgui_soview2D_linestrip* vgui_easy2D_tableau::add_linestrip(unsigned n, float const *x, float const *y)
00256 {
00257   vgui_soview2D_linestrip *obj = new vgui_soview2D_linestrip(n, x, y);
00258 
00259   add(obj);
00260   return obj;
00261 }
00262 
00263 //: Add  polygon with the given n vertices to the display.
00264 vgui_soview2D_polygon* vgui_easy2D_tableau::add_polygon(unsigned n, float const *x, float const *y)
00265 {
00266   vgui_soview2D_polygon *obj = new vgui_soview2D_polygon(n, x, y);
00267 
00268   add(obj);
00269   return obj;
00270 }
00271 
00272 //: Screen dump to postscript file.
00273 //  Specify the optional arguments in case this tableau does not contain
00274 //  an image tableau, or if you want a smaller part of the image printed.
00275 //  If wd or ht are 0, no image is printed at all.
00276 void vgui_easy2D_tableau::print_psfile(vcl_string filename, int reduction_factor, bool print_geom_objs, int wd, int ht)
00277 {
00278   // Set wd and ht from the image tableau, if not specified as parameters
00279   if (wd < 0 || ht < 0)
00280   {
00281     assert(get_image_tableau());
00282     if (get_image_tableau()->get_image_resource())
00283     {
00284       vil_image_resource_sptr img_sptr = get_image_tableau()->get_image_resource();
00285       if (wd < 0) wd = img_sptr->ni();
00286       if (ht < 0) ht = img_sptr->nj();
00287     }
00288     else
00289     {
00290       vil1_image img = get_image_tableau()->get_image();
00291       if (wd < 0) wd = img.width();
00292       if (ht < 0) ht = img.height();
00293       assert (wd <= img.width());
00294       assert (ht <= img.height());
00295     }
00296   }
00297 
00298   // Write PostScript header
00299   vul_psfile psfile(filename.c_str(), false);
00300   psfile.set_paper_layout(vul_psfile::MAX);
00301   psfile.set_reduction_factor(reduction_factor);
00302   // psfile.set_parameters(wd, ht); // no longer needed - vul_psfile does this
00303 
00304   // Write image, if present
00305   if (get_image_tableau() && wd*ht > 0)
00306   {
00307     if (get_image_tableau()->get_image_resource())
00308     {
00309       vil_image_resource_sptr img_sptr = get_image_tableau()->get_image_resource();
00310       vil_image_view<vxl_byte> img= img_sptr->get_view();
00311       if (!img)
00312       {
00313         // invalid pixel type
00314         vgui_macro_warning<< "failed to print image of unsupported pixel format: "
00315                           << img << vcl_endl;
00316       }
00317       if (img.nplanes()==1) // greyscale image
00318       {
00319         if (img.istep() != 1)
00320           vgui_macro_warning<< "The istep of this image view is not 1: "
00321                             << img << vcl_endl;
00322         else {
00323           if (debug)
00324             vcl_cerr << "vgui_easy2D_tableau::print_psfile printing greyscale image to"
00325                      << filename.c_str() << '\n';
00326           psfile.print_greyscale_image(img.top_left_ptr(), img.ni(), img.nj());
00327         }
00328       }
00329       else if (img.nplanes() == 3) // color image
00330       {}
00331       else
00332         // urgh
00333         vgui_macro_warning<< "Don't know how to handle image with "
00334                           << img.nplanes() << " planes" << vcl_endl;
00335     }
00336     else
00337     {
00338       vil1_image img = get_image_tableau()->get_image();
00339       unsigned char* data = new unsigned char[img.get_size_bytes()];
00340       img.get_section(data, 0, 0, wd, ht);
00341       if (vil1_pixel_format(img) == VIL1_BYTE)
00342       {
00343         if (debug)
00344           vcl_cerr << "vgui_easy2D_tableau::print_psfile printing greyscale image to"
00345                    << filename.c_str() << '\n';
00346         psfile.print_greyscale_image(data, wd, ht);
00347       }
00348       else if (vil1_pixel_format(img) == VIL1_RGB_BYTE)
00349       {
00350         if (debug)
00351           vcl_cerr << "vgui_easy2D_tableau::print_psfile printing color image to "
00352                    << filename.c_str() << '\n';
00353         psfile.print_color_image(data, wd, ht);
00354       }
00355       else
00356         // urgh
00357         vgui_macro_warning<< "failed to print image of unsupported pixel format: "
00358                           << img << vcl_endl;
00359       delete[] data;
00360     }
00361   }
00362 
00363   // Skip the rest of this function if no geometry is wanted
00364   if (!print_geom_objs) return;
00365   if (debug)
00366     vcl_cerr << "vgui_easy2D_tableau: Printing geometric objects\n";
00367 
00368   vcl_vector<vgui_soview*> all_objs = get_all();
00369   vgui_style_sptr style = 0;
00370   float style_point_size = 0;
00371   for (vcl_vector<vgui_soview*>::iterator i = all_objs.begin(); i != all_objs.end(); ++i)
00372   {
00373     vgui_soview* sv = *i;
00374     if (sv == NULL) {
00375        vgui_macro_warning << "An object in soview list is null\n";
00376        continue;
00377     }
00378     // Send style info if it has changed.
00379     vgui_style_sptr svstyle = sv->get_style();
00380     if (svstyle != style) {
00381       // rgba, line_width, point_size
00382       style = svstyle;
00383       psfile.set_line_width(style->line_width);
00384       style_point_size = style->point_size;
00385       psfile.set_fg_color(style->rgba[0],style->rgba[1],style->rgba[2]);
00386     }
00387 
00388     if (sv->type_name() == "vgui_soview2D_point")
00389     {
00390       vgui_soview2D_point* pt = (vgui_soview2D_point*)sv;
00391       psfile.point(pt->x, pt->y, style_point_size);
00392       if (debug)
00393         vcl_cerr << "  vgui_easy2D_tableau: Adding a point at "
00394                  << pt->x << ", " << pt->y << '\n';
00395     }
00396     else if (sv->type_name() == "vgui_soview2D_circle")
00397     {
00398       vgui_soview2D_circle* circ = (vgui_soview2D_circle*)sv;
00399       psfile.circle(circ->x, circ->y, circ->r);
00400       if (debug)
00401         vcl_cerr << "  vgui_easy2D_tableau: Adding circle, center " << circ->x << ", "
00402                  << circ->y << " radius " << circ->r << '\n';
00403     }
00404     else if (sv->type_name() == "vgui_soview2D_lineseg")
00405     {
00406       vgui_soview2D_lineseg* line = (vgui_soview2D_lineseg*)sv;
00407       psfile.line(line->x0, line->y0, line->x1, line->y1);
00408       if (debug)
00409         vcl_cerr << " vgui_easy2D_tableau: Adding line between " << line->x0 << ", "
00410                  << line->y0 << " and " << line->x1 << ", " << line->y1 << '\n';
00411     }
00412     else if (sv->type_name() == "vgui_soview2D_linestrip")
00413     {
00414       vgui_soview2D_linestrip *linestrip = (vgui_soview2D_linestrip *)sv;
00415       for (unsigned int ii = 1; ii<linestrip->n; ++ii)
00416         psfile.line(linestrip->x[ii-1],linestrip->y[ii-1],
00417                     linestrip->x[ii  ],linestrip->y[ii  ]);
00418       if (debug)
00419         vcl_cerr<< " vgui_easy2D_tableau: Adding linestrip\n";
00420     }
00421     else if (sv->type_name() == "vgui_soview2D_polygon")
00422     {
00423       vgui_soview2D_polygon *polygon = (vgui_soview2D_polygon *)sv;
00424       for (unsigned int ii = 1; ii<polygon->n; ++ii)
00425         psfile.line(polygon->x[ii-1],polygon->y[ii-1],
00426                     polygon->x[ii  ],polygon->y[ii  ]);
00427       psfile.line(polygon->x[polygon->n - 1],
00428                   polygon->y[polygon->n - 1],
00429                   polygon->x[0], polygon->y[0]);
00430       if (debug)
00431         vcl_cerr<< " vgui_easy2D_tableau: Adding polygon\n";
00432     }
00433     else if (sv->type_name() == "vgui_soview2D_ellipse")
00434     {
00435       vgui_soview2D_ellipse* ellip = (vgui_soview2D_ellipse*)sv;
00436       psfile.ellipse(ellip->x, ellip->y, ellip->w, ellip->h, int(vnl_math::deg_per_rad * ellip->phi + 0.5)); // convert radians to degrees
00437       if (debug)
00438         vcl_cerr << "  vgui_easy2D_tableau: Adding ellipse, center " << ellip->x << ", "
00439                  << ellip->y << " width " << ellip->w << " height " << ellip->h
00440                  << " angle " << ellip->phi << " (" << int(vnl_math::deg_per_rad * ellip->phi + 0.5) << " deg)\n";
00441     }
00442     else
00443       vgui_macro_warning << "unknown soview typename = " << sv->type_name() << vcl_endl;
00444   }
00445 }
00446 
00447 //: Add an image at the given position to the display.
00448 vgui_soview2D_image* vgui_easy2D_tableau::add_image( float x, float y,
00449                                                      vil1_image const& img )
00450 {
00451   // Assume alpha blending is necessary iff there are four components
00452   // in the image
00453   bool blend = false;
00454   if ( img.components() == 4 )
00455     blend = true;
00456   vgui_soview2D_image *obj = new vgui_soview2D_image( x, y, img, blend );
00457   add(obj);
00458   return obj;
00459 }
00460 
00461 //: Add an image at the given position to the display.
00462 vgui_soview2D_image* vgui_easy2D_tableau::add_image( float x, float y,
00463                                                      vil_image_view_base const& img )
00464 {
00465   // Assume alpha blending is necessary iff there are four components
00466   // in the image
00467   bool blend = false;
00468   if ( img.nplanes() == 4 )
00469     blend = true;
00470   vgui_soview2D_image *obj = new vgui_soview2D_image( x, y, img, blend );
00471   add(obj);
00472   return obj;
00473 }
00474 
00475 #if 0 // deprecated method
00476 vgui_soview2D_image* vgui_easy2D_tableau::add_image( float x, float y,
00477                                                      float width, float height,
00478                                                      char *data,
00479                                                      unsigned int format, unsigned int type )
00480 {
00481   if ( type != GL_UNSIGNED_BYTE ) {
00482     vcl_cerr << "Don't know how to add non-byte sprites using old interface\n";
00483     vcl_abort();
00484   }
00485   unsigned w = unsigned(width);
00486   unsigned h = unsigned(height);
00487   vil_image_view<vxl_byte> img;
00488   if ( format == GL_RGB ) {
00489     img = vil_image_view<vxl_byte>( reinterpret_cast<vxl_byte*>(data), w, h, 3, 3, w*3, 1 );
00490 #ifdef DEBUG
00491     vil_save(img, "tmp_image_GL_RGB.jpeg", "jpeg");
00492 #endif
00493   }
00494   else if ( format == GL_RGBA ) {
00495     img = vil_image_view<vxl_byte>( reinterpret_cast<vxl_byte*>(data), w, h, 4, 4, w*4, 1 );
00496 #ifdef DEBUG // inserted debugging jr Oct 24, 2003
00497     vil_save(img, "tmp_image_GL_RGBA.jpeg", "jpeg");
00498 #endif
00499   }
00500   else {
00501     vcl_cerr << "Don't know how to handle format " << format << " with old interface\n";
00502     vcl_abort();
00503   }
00504   return this->add_image( x, y, img );
00505 }
00506 #endif // 0