QtLasso.cc

00001 /*===========================================================================*\
00002  *                                                                           *
00003  *                              OpenFlipper                                  *
00004  *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
00005  *                           www.openflipper.org                             *
00006  *                                                                           *
00007  *---------------------------------------------------------------------------*
00008  *  This file is part of OpenFlipper.                                        *
00009  *                                                                           *
00010  *  OpenFlipper is free software: you can redistribute it and/or modify      *
00011  *  it under the terms of the GNU Lesser General Public License as           *
00012  *  published by the Free Software Foundation, either version 3 of           *
00013  *  the License, or (at your option) any later version with the              *
00014  *  following exceptions:                                                    *
00015  *                                                                           *
00016  *  If other files instantiate templates or use macros                       *
00017  *  or inline functions from this file, or you compile this file and         *
00018  *  link it with other files to produce an executable, this file does        *
00019  *  not by itself cause the resulting executable to be covered by the        *
00020  *  GNU Lesser General Public License. This exception does not however       *
00021  *  invalidate any other reasons why the executable file might be            *
00022  *  covered by the GNU Lesser General Public License.                        *
00023  *                                                                           *
00024  *  OpenFlipper is distributed in the hope that it will be useful,           *
00025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027  *  GNU Lesser General Public License for more details.                      *
00028  *                                                                           *
00029  *  You should have received a copy of the GNU LesserGeneral Public          *
00030  *  License along with OpenFlipper. If not,                                  *
00031  *  see <http://www.gnu.org/licenses/>.                                      *
00032  *                                                                           *
00033 \*===========================================================================*/
00034 
00035 /*===========================================================================*\
00036  *                                                                           *
00037  *   $Revision: 6743 $                                                       *
00038  *   $Author: moebius $                                                      *
00039  *   $Date: 2009-08-05 11:03:10 +0200 (Mi, 05. Aug 2009) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 
00044 
00045 //=============================================================================
00046 //
00047 //  CLASS QtLasso - IMPLEMENTATION
00048 //
00049 //=============================================================================
00050 
00051 //== INCLUDES =================================================================
00052 
00053 
00054 //ACG
00055 #include "QtLasso.hh"
00056 #include "QtColorTranslator.hh"
00057 #include "../GL/gl.hh"
00058 
00059 // stdc++
00060 #include <list>
00061 #include <vector>
00062 
00063 #include <QMouseEvent>
00064 #include <QEvent>
00065 #include <QRgb>
00066 
00067 
00068 
00069 //== NAMESPACES ===============================================================
00070 
00071 namespace ACG {
00072 
00073 
00074 //== IMPLEMENTATION ==========================================================
00075 
00076 
00077 
00078 #define MASK(x,y) (mask_[(x)+(y)*mask_width_])
00079 
00080 
00081 //-----------------------------------------------------------------------------
00082 
00083 
00084 QtLasso::
00085 QtLasso(GLState& _glstate) :
00086   glstate_(_glstate),
00087   mask_(0),
00088   mask_width_(0),
00089   mask_height_(0),
00090   is_active_(false)
00091 {
00092 }
00093 
00094 
00095 //-----------------------------------------------------------------------------
00096 
00097 
00098 QtLasso::
00099 ~QtLasso()
00100 {
00101   free_mask();
00102 }
00103 
00104 
00105 //-----------------------------------------------------------------------------
00106 
00107 
00108 void
00109 QtLasso::
00110 slotMouseEvent(QMouseEvent* _event)
00111 {
00112   bool emit_signal = false;
00113 
00114 
00115   // setup 2D projection
00116   unsigned int width  = glstate_.viewport_width();
00117   unsigned int height = glstate_.viewport_height();
00118 
00119   glDrawBuffer( GL_FRONT );
00120 
00121   glMatrixMode(GL_PROJECTION);
00122   glPushMatrix();
00123   glLoadIdentity();
00124   gluOrtho2D(0, width-1, 0, height-1);
00125 
00126   glMatrixMode(GL_MODELVIEW);
00127   glPushMatrix();
00128   glLoadIdentity();
00129 
00130   glDisable(GL_DEPTH_TEST);
00131   glDisable(GL_LIGHTING);
00132   glDisable(GL_DITHER);
00133   glLineWidth(2.0);
00134   glColor3ub(0, 255, 10);
00135 
00136   glFinish();
00137 
00138 
00139 
00140   // process mouse event
00141   switch(_event->type())
00142   {
00143     case QEvent::MouseButtonPress:
00144     {
00145       Vec2i p(_event->pos().x(), height-_event->pos().y()-1);
00146 
00147       // initialize
00148       if (!is_active())
00149       {
00150         is_active_ = true;
00151         first_point_ = last_point_ = p;
00152       }
00153 
00154       // draw line
00155       glBegin(GL_LINES);
00156       glVertex(last_point_);
00157       glVertex(p);
00158       glEnd();
00159       last_point_ = rubberband_point_ = p;
00160       break;
00161     }
00162 
00163 
00164     case QEvent::MouseMove:
00165     {
00166       if (is_active())
00167       {
00168         Vec2i p(_event->pos().x(), height-_event->pos().y());
00169 
00170         // draw freehand
00171         if (_event->modifiers() & Qt::LeftButton)
00172         {
00173           glBegin(GL_LINES);
00174           glVertex(last_point_);
00175           glVertex(p);
00176           glEnd();
00177           last_point_ = rubberband_point_ = p;
00178         }
00179 
00180         // draw rubber band
00181         else
00182         {
00183           glEnable(GL_COLOR_LOGIC_OP);
00184           glLogicOp(GL_XOR);
00185           glBegin(GL_LINES);
00186           glVertex(last_point_);
00187           glVertex(rubberband_point_);
00188           glVertex(last_point_);
00189           glVertex(p);
00190           glEnd();
00191           glDisable(GL_COLOR_LOGIC_OP);
00192           rubberband_point_ = p;
00193         }
00194       }
00195       break;
00196     }
00197 
00198 
00199     case QEvent::MouseButtonDblClick:
00200     {
00201       if (is_active())
00202       {
00203         // close polygon
00204         glBegin(GL_LINES);
00205         glVertex(last_point_);
00206         glVertex(first_point_);
00207         glEnd();
00208         glFinish();
00209 
00210 
00211         // mark reference point (0,0) with border color
00212         glPointSize(1.0);
00213         glBegin(GL_POINTS);
00214         glVertex2i(0, 0);
00215         glEnd();
00216         glPointSize(glstate_.point_size());
00217 
00218 
00219         // create mask and precompute matrix
00220         create_mask();
00221         is_active_ = false;
00222 
00223         emit_signal = true;
00224       }
00225       break;
00226     }
00227 
00228 
00229     default: // avoid warning
00230       break;
00231   }
00232 
00233 
00234   // restore GL settings
00235   glDrawBuffer(GL_BACK);
00236   glReadBuffer(GL_BACK);
00237 
00238   glLineWidth(glstate_.line_width());
00239   glColor4fv(glstate_.base_color().data());
00240   glEnable(GL_DEPTH_TEST);
00241 
00242   glMatrixMode(GL_PROJECTION );
00243   glPopMatrix();
00244 
00245   glMatrixMode(GL_MODELVIEW);
00246   glPopMatrix();
00247 
00248   glFinish();
00249 
00250 
00251 
00252   // emit signal
00253   if (emit_signal)
00254   {
00255     if (_event->modifiers() & Qt::ShiftModifier)
00256       emit(signalLassoSelection(AddToSelection));
00257 
00258     else if (_event->modifiers() & Qt::ControlModifier)
00259       emit(signalLassoSelection(DelFromSelection));
00260 
00261     else
00262       emit(signalLassoSelection(NewSelection));
00263   }
00264 }
00265 
00266 
00267 //-----------------------------------------------------------------------------
00268 
00269 
00270 void
00271 QtLasso::
00272 create_mask()
00273 {
00274   unsigned int  w, h, size, x, y, xx, yy, i, offset;
00275   GLubyte       *fbuffer;
00276   QRgb          rgb, borderRgb;
00277 
00278 
00279   // GL context
00280   w = glstate_.viewport_width();
00281   h = glstate_.viewport_height();
00282   size = w*h;
00283 
00284 
00285   // alloc mask
00286   free_mask();
00287   mask_ = new unsigned char[size];
00288   mask_width_ = w;
00289   mask_height_ = h;
00290 
00291 
00292   // alloc framebuffer
00293   fbuffer = new GLubyte[3*size];
00294   assert( fbuffer );
00295 
00296 
00297   // read framebuffer
00298   glReadBuffer( GL_FRONT );
00299   glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, fbuffer);
00300   glReadBuffer( GL_BACK );
00301 
00302 
00303   // read lasso color
00304   borderRgb = qRgb( fbuffer[0], fbuffer[1], fbuffer[2] );
00305   fbuffer[0] = fbuffer[1] = fbuffer[2] = 0;
00306 
00307 
00308   // mark lasso pixels
00309   for (y = 0; y < h; ++y)
00310   {
00311     offset = y*w;
00312     for (x = 0; x < w; ++x)
00313     {
00314       i = 3*(offset + x);
00315       rgb = qRgb(fbuffer[i], fbuffer[i+1], fbuffer[i+2]);
00316       mask_[offset+x] = (rgb == borderRgb) ? 3 : 1;
00317     }
00318   }
00319 
00320 
00321   // seed fill
00322   std::vector<Vec2i> toDo;
00323   toDo.reserve(w*h);
00324   toDo.push_back(Vec2i(0,0));
00325 
00326   while (!toDo.empty())
00327   {
00328     Vec2i p = toDo.back();
00329     toDo.pop_back();
00330 
00331     x = p[0];
00332     y = p[1];
00333     unsigned char &s = MASK(x, y);
00334 
00335     if (s != 3)
00336     {
00337       s = 0;
00338 
00339       xx = x-1; yy = y;
00340       if ((xx<w) && (MASK(xx,yy)==1))
00341       {
00342         toDo.push_back(Vec2i(xx,yy));
00343         MASK(xx,yy) = 2;
00344       }
00345 
00346       xx = x+1; yy = y;
00347       if ((xx<w) && (MASK(xx,yy)==1))
00348       {
00349         toDo.push_back(Vec2i(xx,yy));
00350         MASK(xx,yy) = 2;
00351       }
00352 
00353       xx = x; yy = y-1;
00354       if ((yy<h) && (MASK(xx,yy)==1))
00355       {
00356         toDo.push_back(Vec2i(xx,yy));
00357         MASK(xx,yy) = 2;
00358       }
00359 
00360       xx = x; yy = y+1;
00361       if ((yy<h) && (MASK(xx,yy)==1))
00362       {
00363         toDo.push_back(Vec2i(xx,yy));
00364         MASK(xx,yy) = 2;
00365       }
00366     }
00367   }
00368 
00369 
00370   // free
00371   delete[] fbuffer;
00372 }
00373 
00374 
00375 //-----------------------------------------------------------------------------
00376 
00377 
00378 void
00379 QtLasso::
00380 free_mask()
00381 {
00382   if (mask_)
00383   {
00384     delete[] mask_;
00385     mask_ = 0;
00386     mask_width_ = mask_height_ = 0;
00387   }
00388 }
00389 
00390 
00391 //-----------------------------------------------------------------------------
00392 
00393 
00394 bool
00395 QtLasso::
00396 is_vertex_selected(const Vec3d& _v)
00397 {
00398   unsigned int  x, y, w, h;
00399 
00400 
00401   // size changed?
00402   w = glstate_.viewport_width();
00403   h = glstate_.viewport_height();
00404   if ((w != mask_width_) || (h != mask_height_))
00405   {
00406     std::cerr << "Lasso: viewport size has changed.\n";
00407     return false;
00408   }
00409 
00410 
00411   // project vertex to 2D integer coordinates
00412   Vec3d v = glstate_.project(_v);
00413   x = (unsigned int)(v[0] + 0.5);
00414   y = (unsigned int)(v[1] + 0.5);
00415 
00416 
00417   // near and far plane clipping
00418   if (v[2] < 0.0 || v[2] > 1.0)
00419     return false;
00420 
00421 
00422   // visible ?
00423   return ((v[2]>0.0) && (x<w) && (y<h) && (MASK(x,y)));
00424 }
00425 
00426 
00427 //=============================================================================
00428 } // namespace ACG
00429 //=============================================================================

acg pic Project OpenFlipper, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .