contrib/brl/bbas/bgui/bgui_picker_tableau.cxx
Go to the documentation of this file.
00001 // This is brl/bbas/bgui/bgui_picker_tableau.cxx
00002 #include "bgui_picker_tableau.h"
00003 //:
00004 // \file
00005 // \author K.Y.McGaul
00006 //  See bgui_picker_tableau.h for a description of this file.
00007 //
00008 // \verbatim
00009 //  Modifications
00010 //   K.Y.McGaul - 26-APR-2001 - Initial version.
00011 // \endverbatim
00012 
00013 #include <vgui/vgui.h>
00014 #include <vgui/vgui_gl.h>
00015 #include <vgui/vgui_projection_inspector.h>
00016 #include <vsol/vsol_point_2d.h>
00017 #include <vsol/vsol_polygon_2d.h>
00018 #include <vsol/vsol_polyline_2d.h>
00019 
00020 bgui_picker_tableau::object_type bgui_picker_tableau::obj_type = none_enum;
00021 
00022 //========================================================================
00023 //: Constructor, takes a child tableau.
00024 bgui_picker_tableau::bgui_picker_tableau(vgui_tableau_sptr const& t)
00025   :child_tab(this, t)
00026 {
00027   r = 1.0f;
00028   g = 1.0f;
00029   b = 1.0f;
00030   w = 2.0f;
00031   use_event_ = false;
00032   pointx1 = pointy1 = pointx2 = pointy2 = 0;
00033   FIRSTPOINT = true;
00034   pointx = 0; pointy = 0;
00035   point_ret = true;
00036   anchor_x = 0;
00037   anchor_y = 0;
00038   //for polygon draw
00039   gesture0 = vgui_event_condition(vgui_LEFT, vgui_MODIFIER_NULL, true);
00040   gesture1 = vgui_event_condition(vgui_LEFT, vgui_SHIFT, true);
00041   gesture2 = vgui_event_condition(vgui_END, vgui_MODIFIER_NULL, true);
00042   last_x = 0;
00043   last_y = 0;
00044   active = false;
00045 }
00046 
00047 //========================================================================
00048 //: Destructor.
00049 bgui_picker_tableau::~bgui_picker_tableau()
00050 {
00051 }
00052 
00053 //========================================================================
00054 //: Gets a user selected point.
00055 //  This function grabs the event loop and will not return until a
00056 //  mouse down event occurs.
00057 //  Returns true if this is done with the left mouse button, otherwise false.
00058 //  The coordinates of the point are returned in the parameters.
00059 bool bgui_picker_tableau::pick_point(float* x, float* y)
00060 {
00061   obj_type = point_enum;
00062   picking_completed = false;
00063   point_ret = true;
00064   vgui::flush();  // handle any pending events before we grab the event loop.
00065 
00066   // Grab event loop until picking is completed:
00067   while (!picking_completed)
00068     next();
00069 
00070   *x = pointx;
00071   *y = pointy;
00072   obj_type = none_enum;
00073   return point_ret;
00074 }
00075 
00076 void bgui_picker_tableau::pick_box(float* x1, float* y1, float *x2, float* y2)
00077 {
00078   obj_type = box_enum;
00079   picking_completed = false;
00080   point_ret = true;
00081   vgui::flush();  // handle any pending events before we grab the event loop.
00082 
00083   // Grab event loop until picking is completed:
00084   while (!picking_completed)
00085     next();
00086 
00087   *x1 = pointx1;
00088   *y1 = pointy1;
00089   *x2 = pointx2;
00090   *y2 = pointy2;
00091 
00092   //reset everything for the next pick
00093   FIRSTPOINT=true;
00094   post_redraw();
00095   obj_type = none_enum;
00096 }//========================================================================
00097 
00098 //: Draw a line to help the user pick it.
00099 void bgui_picker_tableau::draw_line()
00100 {
00101   if (!FIRSTPOINT)  // there is no point in drawing till we have a first point
00102   {
00103     glLineWidth(w);
00104     glColor3f(r,g,b);
00105 
00106     glBegin(GL_LINES);
00107     glVertex2f(pointx1, pointy1);
00108     glVertex2f(pointx2, pointy2);
00109     glEnd();
00110   }
00111 }
00112 
00113 //: Draw a box to help the user pick it.
00114 void bgui_picker_tableau::draw_box()
00115 {
00116   if (!FIRSTPOINT)  // there is no point in drawing till we have a first point
00117   {
00118     glLineWidth(w);
00119     glColor3f(r,g,b);
00120 
00121     glBegin(GL_LINE_LOOP);
00122     glVertex2f(pointx1, pointy1);
00123     glVertex2f(pointx2, pointy1);
00124     glVertex2f(pointx2, pointy2);
00125     glVertex2f(pointx1, pointy2);
00126     glEnd();
00127   }
00128 }
00129 
00130 
00131 //========================================================================
00132 //: Draw a line to help the user pick it.
00133 void bgui_picker_tableau::draw_anchor_line()
00134 {
00135   glLineWidth(w);
00136   glColor3f(r,g,b);
00137   glBegin(GL_LINES);
00138   glVertex2f(anchor_x, anchor_y);
00139   glVertex2f(pointx1, pointy1);
00140   glEnd();
00141 }
00142 
00143 //========================================================================
00144 //: Gets a user selected line.
00145 //  This function grabs the event loop and will not return until two mouse
00146 //  down events occur.
00147 //  The parameters return the two points defining the line.
00148 void bgui_picker_tableau::pick_line(float* x1, float* y1, float* x2, float* y2)
00149 {
00150   obj_type = line_enum;
00151   picking_completed = false;
00152   vgui::flush();  // handle any pending events before we grab the event loop.
00153 
00154   // Grab event loop until picking is completed:
00155   while (!picking_completed)
00156     next();
00157 
00158   *x1 = pointx1;
00159   *y1 = pointy1;
00160   *x2 = pointx2;
00161   *y2 = pointy2;
00162 
00163   // Reset everything ready for the next pick:
00164   FIRSTPOINT=true;
00165   post_redraw();
00166   obj_type = none_enum;
00167 }
00168 
00169 //========================================================================
00170 //: Gets a user selected point (x, y)
00171 //  This function grabs the event loop and will not return until a
00172 //  mouse button down event occurs.
00173 void bgui_picker_tableau::anchored_pick_point(const float anch_x,
00174                                               const float anch_y,
00175                                               float* x, float* y)
00176 {
00177   anchor_x = anch_x;
00178   anchor_y = anch_y;
00179 
00180   obj_type = anchor_enum;
00181   picking_completed = false;
00182   vgui::flush();  // handle any pending events before we grab the event loop.
00183   // Grab event loop until picking is completed:
00184   while (!picking_completed)
00185     next();
00186 
00187   *x = pointx1;
00188   *y = pointy1;
00189   post_redraw();
00190   obj_type = none_enum;
00191 }
00192 
00193 void bgui_picker_tableau::pick_polygon(vsol_polygon_2d_sptr& poly)
00194 {
00195   point_list.clear();
00196   obj_type = poly_enum;
00197   picking_completed = false;
00198   active = true;
00199   vgui::flush();  // handle any pending events before we grab the event loop.
00200   // Grab event loop until picking is completed:
00201   while (!picking_completed)
00202     next();
00203   if (point_list.size() >=3)
00204     poly =  new vsol_polygon_2d( point_list );
00205   obj_type = none_enum;
00206 }
00207 
00208 void bgui_picker_tableau::pick_polyline(vsol_polyline_2d_sptr& poly)
00209 {
00210   point_list.clear();
00211   obj_type = polyline_enum;
00212   picking_completed = false;
00213   active = true;
00214   vgui::flush();  // handle any pending events before we grab the event loop.
00215   // Grab event loop until picking is completed:
00216   while (!picking_completed)
00217     next();
00218   if (point_list.size() >=2)
00219     poly =  new vsol_polyline_2d( point_list );
00220   obj_type = none_enum;
00221 }
00222 
00223 //========================================================================
00224 // add max as argument to this method
00225 bool bgui_picker_tableau::pick_point_set(vcl_vector< vsol_point_2d_sptr >& ps_list,
00226                                          unsigned max)
00227 {
00228   obj_type = point_set_enum;
00229   picking_completed = false;
00230   vgui::flush();  // handle any pending events before we grab the event loop.
00231 
00232   // start with empty lists
00233   point_set_list.clear();
00234   ps_list.clear();
00235 
00236   // Grab event loop until picking is completed:
00237   while (!picking_completed)
00238      next();
00239 
00240   if (point_set_list.size() <= max)
00241   {
00242     // copy points into return vector ps_list
00243     ps_list.clear();
00244     for (unsigned i=0; i < point_set_list.size(); i++)
00245       ps_list.push_back(point_set_list[i]);
00246     obj_type = none_enum;
00247     return true;
00248   }
00249   else       // too many points picked?
00250   {
00251     ps_list.clear();          // error, return empty list
00252     vcl_cout << "Error, " << point_set_list.size()
00253              << " points picked (more than " << max << ")!!  Try again.\n";
00254     vcl_cout.flush();
00255     return false;
00256   }
00257 }
00258 
00259 //========================================================================
00260 //: Handles all events for this tableau.
00261 //  We grab events in this way rather than using a vgui_event_server because
00262 //  if we look at events outside the handle function then the gl state
00263 //  associated with those events will have changed.  This means for a
00264 //  draw_overlay event we would end up drawing into the wrong buffer.
00265 //  For a mouse event we would not be able to get the position in the image
00266 //  using the projection_inspector (if e.g. the image was zoomed) since all
00267 //  the gl matrices would have been reset.
00268 bool bgui_picker_tableau::handle(const vgui_event& e)
00269 {
00270   //USE BUTTON_UP TO INITIALIZE, COMPETITION FOR BUTTON_DOWN on other tableaux
00271   // Pass events on down to the child tableaux:
00272   child_tab->handle(e);
00273 
00274   use_event_ = true;
00275 
00276   //---- Object type is point -----
00277   if (obj_type == point_enum)
00278   {
00279     if (e.type == vgui_BUTTON_DOWN)
00280     {
00281       vgui_projection_inspector p_insp;
00282       p_insp.window_to_image_coordinates(e.wx, e.wy, pointx, pointy);
00283 
00284       if (e.button != vgui_LEFT)
00285         point_ret= false;
00286       picking_completed = true;
00287     }
00288     return true;
00289   }
00290   // ---- Object type is line ----
00291   if (obj_type == line_enum)
00292   {
00293     if (e.type == vgui_DRAW_OVERLAY)
00294       draw_line();
00295     else if (e.type == vgui_MOTION)
00296     {
00297       vgui_projection_inspector p_insp;
00298       if (!FIRSTPOINT)
00299         p_insp.window_to_image_coordinates(e.wx, e.wy, pointx2, pointy2);
00300       else
00301         p_insp.window_to_image_coordinates(e.wx, e.wy, pointx1, pointy1);
00302       post_overlay_redraw();
00303     }
00304     else if (e.type == vgui_BUTTON_UP)
00305     {
00306       if (FIRSTPOINT)
00307       {
00308         vgui_projection_inspector p_insp;
00309         p_insp.window_to_image_coordinates(e.wx,e.wy, pointx1,pointy1);
00310         pointx2 = pointx1;
00311         pointy2 = pointy1;
00312         FIRSTPOINT=false;
00313       }
00314       else
00315       {
00316         picking_completed = true;
00317       }
00318     }
00319     return true;
00320   }
00321 
00322   // ---- Object type is box ----
00323   if (obj_type == box_enum)
00324   {
00325     if (e.type == vgui_DRAW_OVERLAY)
00326       draw_box();
00327     else if (e.type == vgui_MOTION)
00328     {
00329       vgui_projection_inspector p_insp;
00330       p_insp.window_to_image_coordinates(e.wx, e.wy, pointx2, pointy2);
00331       post_overlay_redraw();
00332     }
00333     else if (e.type == vgui_BUTTON_DOWN)
00334     {
00335       if (FIRSTPOINT)
00336       {
00337         vgui_projection_inspector p_insp;
00338         p_insp.window_to_image_coordinates(e.wx,e.wy, pointx1,pointy1);
00339         pointx2 = pointx1;
00340         pointy2 = pointy1;
00341         FIRSTPOINT=false;
00342       }
00343       else
00344       {
00345         picking_completed = true;
00346       }
00347     }
00348     return true;
00349   }
00350 
00351   // ---- Object type is anchor line ----
00352   if (obj_type == anchor_enum)
00353   {
00354     if (e.type == vgui_DRAW_OVERLAY)
00355       draw_anchor_line();
00356     else if (e.type == vgui_MOTION)
00357     {
00358       vgui_projection_inspector p_insp;
00359       p_insp.window_to_image_coordinates(e.wx, e.wy, pointx1, pointy1);
00360       post_overlay_redraw();
00361     }
00362     else if (e.type == vgui_BUTTON_UP)
00363       picking_completed = true;
00364     return true;
00365   }
00366 
00367   // ---- Object type is polygon or polyline ----
00368   if ((obj_type == poly_enum) || (obj_type == polyline_enum))
00369   {
00370     if (active && e.type == vgui_OVERLAY_DRAW )
00371     {
00372       glLineWidth(w);
00373       glColor3f(r,g,b);
00374 
00375       if (obj_type == poly_enum)
00376       {
00377         glBegin(GL_LINE_LOOP);
00378         for (unsigned i=0; i<point_list.size(); ++i)
00379           glVertex2f(static_cast<float>(point_list[i]->x()), static_cast<float>(point_list[i]->y()));
00380         glVertex2f(last_x,last_y);
00381         glEnd();
00382         return true;
00383       }
00384       else if (obj_type == polyline_enum)
00385       {
00386         unsigned n = point_list.size();
00387         for (unsigned i=1; i<n; ++i){
00388           glBegin(GL_LINES);
00389           glVertex2f(static_cast<float>(point_list[i-1]->x()), static_cast<float>(point_list[i-1]->y()));
00390           glVertex2f(static_cast<float>(point_list[i]->x()), static_cast<float>(point_list[i]->y()));
00391           glEnd();
00392         }
00393         if (n > 0) {
00394           glBegin(GL_LINES);
00395           glVertex2f(last_x,last_y);
00396           glVertex2f(static_cast<float>(point_list[n-1]->x()), static_cast<float>(point_list[n-1]->y()));
00397           glEnd();
00398         }
00399         return true;
00400       }
00401     }
00402 
00403     float ix, iy;
00404 
00405     vgui_projection_inspector pi;
00406     pi.window_to_image_coordinates(e.wx,e.wy,ix, iy);
00407 
00408     if (active) {
00409       if (e.type == vgui_MOTION) {
00410         last_x = ix; last_y = iy;
00411         post_overlay_redraw();
00412       }
00413       else if ( gesture0(e) ) {
00414         point_list.push_back(vsol_point_2d_sptr( new vsol_point_2d( ix , iy )));
00415         last_x = ix; last_y = iy;
00416       }
00417       else if ( gesture1(e) || gesture2(e) ) {
00418         if (gesture1(e))
00419           point_list.push_back( vsol_point_2d_sptr( new vsol_point_2d(ix,iy) ));
00420         active = false;
00421         picking_completed = true;
00422       }
00423     }
00424   }
00425   // ---- Object type is point_set_enum ----
00426   //  -- similar to polygon except that we don't need to draw anything between points --
00427   if (obj_type == point_set_enum)
00428   {
00429     if (e.type == vgui_OVERLAY_DRAW ) {
00430       unsigned n = point_set_list.size();
00431       glPointSize(3);
00432       glColor3f(r,g,b);
00433       glBegin(GL_POINTS);
00434       for (unsigned i=0; i<n; ++i){
00435         glVertex2f(static_cast<float>(point_set_list[i]->x()), static_cast<float>(point_set_list[i]->y()));
00436       }
00437       glEnd();
00438     }
00439 
00440     float ix, iy;
00441     vgui_projection_inspector().window_to_image_coordinates(e.wx,
00442                                                             e.wy,
00443                                                             ix, iy);
00444 
00445     // gesture0 = left mouse click, just add point to list
00446     if ( gesture0(e) ) {
00447       point_set_list.push_back(vsol_point_2d_sptr( new vsol_point_2d(ix,iy) ));
00448       post_overlay_redraw();
00449       return true;
00450 #ifdef DEBUG
00451       vcl_cout << "Left click returned " << ix << ",  " << iy  << vcl_endl;
00452       vcl_cout.flush();
00453 #endif
00454     }
00455 
00456     // gesture1 = shift left mouse click or gesture2 = END key press
00457     if ( gesture1(e)||gesture2(e) )
00458     {
00459       // if middle mouse, add point to list and end, if END key just end
00460       if (gesture1(e)) {
00461         point_set_list.push_back(vsol_point_2d_sptr(new vsol_point_2d(ix,iy)));
00462         post_overlay_redraw();
00463 #ifdef DEBUG
00464         vcl_cout << "Shift left returned " << ix << ",  " << iy << vcl_endl;
00465         vcl_cout.flush();
00466 #endif
00467       }
00468 
00469       // either way, end of picking
00470       active = false;
00471       picking_completed = true;
00472 #ifdef DEBUG
00473       vcl_cout << "Detected either middle or END key\n";
00474       vcl_cout.flush();
00475 #endif
00476     }
00477   }
00478   return true;
00479 }
00480 
00481 //========================================================================
00482 //: Get next event in event loop
00483 bool bgui_picker_tableau::next()
00484 {
00485   use_event_ = false;
00486   while (!use_event_) {
00487     vgui::run_one_event();
00488   }
00489   return true;
00490 }