1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #include "OCCViewer_ViewSketcher.h"
23 #include "OCCViewer_ViewWindow.h"
24 #include "OCCViewer_ViewPort3d.h"
26 #include "QtxRubberBand.h"
28 #include <QApplication>
31 #include <QMouseEvent>
34 /****************************************************************
35 ** Class: OCCViewer_ViewSketcher
37 *****************************************************************/
39 OCCViewer_ViewSketcher::OCCViewer_ViewSketcher( OCCViewer_ViewWindow* vw, int type )
41 mySketchButton( Qt::LeftButton ),
50 OCCViewer_ViewSketcher::~OCCViewer_ViewSketcher()
54 void OCCViewer_ViewSketcher::activate()
56 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
58 mySavedCursor = avp->cursor();
59 avp->setCursor( Qt::PointingHandCursor );
60 avp->installEventFilter( this );
61 qApp->installEventFilter( this );
63 connect( avp, SIGNAL( vpDrawExternal( QPainter* ) ), this, SLOT( onDrawViewPort() ) );
71 void OCCViewer_ViewSketcher::deactivate()
73 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
75 disconnect( avp, SIGNAL( vpDrawExternal( QPainter* ) ), this, SLOT( onDrawViewPort() ) );
77 qApp->removeEventFilter( this );
78 avp->removeEventFilter( this );
79 avp->setCursor( mySavedCursor );
84 int OCCViewer_ViewSketcher::type() const
89 void* OCCViewer_ViewSketcher::data() const
94 int OCCViewer_ViewSketcher::result() const
99 int OCCViewer_ViewSketcher::buttonState() const
101 return myButtonState;
104 void OCCViewer_ViewSketcher::onActivate()
108 void OCCViewer_ViewSketcher::onDeactivate()
112 bool OCCViewer_ViewSketcher::isDefault() const
117 bool OCCViewer_ViewSketcher::eventFilter( QObject* o, QEvent* e )
119 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
121 SketchState state = EnTrain;
127 case QEvent::MouseMove:
128 case QEvent::MouseButtonPress:
129 case QEvent::MouseButtonRelease:
130 case QEvent::MouseButtonDblClick:
132 QMouseEvent* me = (QMouseEvent*)e;
134 myButtonState = me->buttons();
135 if ( e->type() == QEvent::MouseButtonPress )
136 myButtonState |= me->button();
138 if ( myStart.isNull() && ( myButtonState & sketchButton() ) )
148 if ( myResult != Neutral )
155 case QEvent::HideToParent:
163 if ( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease )
165 ignore = onKey( (QKeyEvent*)e );
166 if ( myResult != Neutral )
175 return QObject::eventFilter( o, e );
178 void OCCViewer_ViewSketcher::onDrawViewPort()
183 bool OCCViewer_ViewSketcher::onKey( QKeyEvent* )
188 void OCCViewer_ViewSketcher::onMouse( QMouseEvent* )
192 int OCCViewer_ViewSketcher::sketchButton()
194 return mySketchButton;
197 void OCCViewer_ViewSketcher::setSketchButton( int b )
202 /****************************************************************
203 ** Class: OCCViewer_RectSketcher
205 *****************************************************************/
207 OCCViewer_RectSketcher::OCCViewer_RectSketcher( OCCViewer_ViewWindow* vw, int typ )
208 : OCCViewer_ViewSketcher( vw, typ )
212 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
213 mypRectRB = new QtxRectRubberBand( avp );
217 OCCViewer_RectSketcher::~OCCViewer_RectSketcher()
219 delete (QRect*)mypData;
222 void OCCViewer_RectSketcher::onActivate()
224 mypData = new QRect();
227 void OCCViewer_RectSketcher::onDeactivate()
229 delete (QRect*)mypData;
231 mypRectRB->clearGeometry();
234 bool OCCViewer_RectSketcher::onKey( QKeyEvent* e )
236 if ( e->key() == Qt::Key_Escape )
238 else if ( e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return )
244 void OCCViewer_RectSketcher::onMouse( QMouseEvent* e )
246 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
248 if ( avp->rect().contains( myCurr ) )
249 avp->setCursor( Qt::PointingHandCursor );
251 avp->setCursor( Qt::ForbiddenCursor );
253 if ( e->type() == QEvent::MouseButtonRelease && e->button() == sketchButton() )
256 QApplication::postEvent( avp, new QMouseEvent( e->type(), e->pos(),
257 e->globalPos(), e->button(),
258 e->buttons(), e->modifiers() ) );
262 void OCCViewer_RectSketcher::onSketch( SketchState state )
264 //OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
268 QRect* sketchRect = (QRect*)data();
269 if ( myButtonState & sketchButton() )
271 QRect rect = QRect( myStart, myCurr ).normalized();
272 /*QRect rect( qMin( myStart.x(), myCurr.x() ), qMin( myStart.y(), myCurr.y() ),
273 qAbs( myStart.x() - myCurr.x() ), qAbs( myStart.y() - myCurr.y() ) );
275 p.setPen( Qt::white );
276 p.setCompositionMode( QPainter::CompositionMode_Xor );
279 //if ( state != Debut && !sketchRect->isEmpty() )
280 // p.drawRect( *sketchRect );
283 if ( !rect.isEmpty() && state != Fin )
285 //p.drawRect( *sketchRect );
286 mypRectRB->initGeometry( rect );
296 QApplication::syncX(); /* force rectangle redrawing */
297 mypViewWindow->activateSketching( OCCViewer_ViewWindow::NoSketching );
301 /****************************************************************
302 ** Class: OCCViewer_PolygonSketcher
304 *****************************************************************/
306 OCCViewer_PolygonSketcher::OCCViewer_PolygonSketcher( OCCViewer_ViewWindow* vw, int typ )
307 : OCCViewer_ViewSketcher( vw, typ ),
314 mySketchButton = Qt::RightButton;
317 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
318 mypPolyRB = new QtxPolyRubberBand( avp );
322 OCCViewer_PolygonSketcher::~OCCViewer_PolygonSketcher()
325 delete (QPolygon*)mypData;
328 void OCCViewer_PolygonSketcher::onActivate()
331 mypData = new QPolygon( 0 );
332 //mypPoints = new QPolygon( 0 );
334 switch ( sketchButton() )
337 myAddButton = Qt::RightButton;
338 myDelButton = Qt::MidButton;
341 myAddButton = Qt::LeftButton;
342 myDelButton = Qt::RightButton;
344 case Qt::RightButton:
346 myAddButton = Qt::LeftButton;
347 myDelButton = Qt::MidButton;
352 void OCCViewer_PolygonSketcher::onDeactivate()
356 delete (QPolygon*)mypData;
360 mypPolyRB->clearGeometry();
363 bool OCCViewer_PolygonSketcher::onKey( QKeyEvent* e )
365 if ( e->key() == Qt::Key_Escape )
370 else if ( e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return )
372 QPolygon* points = (QPolygon*)data();
373 if ( points->count() )
375 QPoint last = points->point( points->count() - 1 );
376 if ( last != myCurr )
378 points->resize( points->count() + 1 );
379 points->setPoint( points->count() - 1, myCurr );
385 else if ( e->key() == Qt::Key_Backspace && e->type() == QEvent::KeyRelease )
387 QPolygon* points = (QPolygon*)data();
388 if ( points->count() > 1 )
389 points->resize( points->count() - 1 );
397 void OCCViewer_PolygonSketcher::onMouse( QMouseEvent* e )
399 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
401 QPolygon* points = (QPolygon*)data();
402 if ( !points->count() && !myStart.isNull() )
404 points->resize( points->count() + 1 );
405 points->setPoint( points->count() - 1, myStart );
409 bool valid = avp->rect().contains( myCurr );
410 if ( !myStart.isNull() )
412 QRect aRect( myStart.x() - myToler.width(), myStart.y() - myToler.height(),
413 2 * myToler.width(), 2 * myToler.height() );
414 closed = aRect.contains( myCurr );
416 valid = valid && isValid( points, myCurr );
417 if ( closed && !valid )
421 avp->setCursor( Qt::CrossCursor );
423 avp->setCursor( Qt::PointingHandCursor );
425 avp->setCursor( Qt::ForbiddenCursor );
430 if ( e->type() == QEvent::MouseButtonRelease && ( e->button() & sketchButton() ) )
433 QApplication::postEvent( avp, new QMouseEvent( e->type(), e->pos(),
434 e->globalPos(), e->button(),
435 e->buttons(), e->modifiers() ) );
437 else if ( e->type() == QEvent::MouseButtonRelease && ( e->button() & myAddButton ) )
443 if ( myStart.isNull() )
447 QPoint last = points->point( points->count() - 1 );
448 if ( last != myCurr && valid )
450 points->resize( points->count() + 1 );
451 points->setPoint( points->count() - 1, myCurr );
453 if ( valid && myDbl )
458 else if ( ( e->type() == QEvent::MouseButtonRelease && ( e->button() & myDelButton ) ) ||
459 ( e->type() == QEvent::MouseButtonDblClick && ( e->button() & myDelButton ) ) )
461 if ( points->count() > 1 )
462 points->resize( points->count() - 1 );
465 myDbl = e->type() == QEvent::MouseButtonDblClick && ( e->button() & myAddButton );
468 void OCCViewer_PolygonSketcher::onSketch( SketchState state )
470 //OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
472 QPolygon* points = (QPolygon*)data();
474 p.setPen( Qt::white );
475 p.setCompositionMode( QPainter::CompositionMode_Xor );
476 if ( state != Debut )
477 p.drawPolyline( *mypPoints );
479 if ( points->count() )
481 mypPoints->resize( points->count() + 1 );
482 for ( uint i = 0; i < points->count(); i++ )
483 mypPoints->setPoint( i, points->point( i ) );
484 mypPoints->setPoint( points->count(), myCurr );
486 p.drawPolyline( *mypPoints );
490 mypPolyRB->setUpdatesEnabled ( false );
491 if ( !mypPolyRB->isVisible() )
493 //if ( state != Debut )
494 // mypPolyRB->repaint();
496 if ( state != Fin && points->count() )
497 mypPolyRB->initGeometry( QPolygon(*points) << myCurr );
498 //mypPolyRB->addNode( myCurr );
500 //if ( state != Fin )
501 // mypPolyRB->repaint();
502 mypPolyRB->setUpdatesEnabled ( true );
503 //mypPolyRB->repaint();
510 mypPolyRB->clearGeometry();
513 QApplication::syncX();
514 mypViewWindow->activateSketching( OCCViewer_ViewWindow::NoSketching );
518 bool OCCViewer_PolygonSketcher::isValid( const QPolygon* aPoints, const QPoint& aCur ) const
520 if ( !aPoints->count() )
523 if ( aPoints->count() == 1 && aPoints->point( 0 ) == aCur )
526 const QPoint& aLast = aPoints->point( aPoints->count() - 1 );
532 for ( uint i = 0; i < aPoints->count() - 1 && res; i++ )
534 const QPoint& aStart = aPoints->point( i );
535 const QPoint& anEnd = aPoints->point( i + 1 );
536 res = !isIntersect( aStart, anEnd, aCur, aLast );
542 bool OCCViewer_PolygonSketcher::isIntersect( const QPoint& aStart1, const QPoint& anEnd1,
543 const QPoint& aStart2, const QPoint& anEnd2 ) const
545 if ( ( aStart1 == aStart2 && anEnd1 == anEnd2 ) ||
546 ( aStart1 == anEnd2 && anEnd1 == aStart2 ) )
549 if ( aStart1 == aStart2 || aStart2 == anEnd1 ||
550 aStart1 == anEnd2 || anEnd1 == anEnd2 )
553 double x11 = aStart1.x() * 1.0;
554 double x12 = anEnd1.x() * 1.0;
555 double y11 = aStart1.y() * 1.0;
556 double y12 = anEnd1.y() * 1.0;
558 double x21 = aStart2.x() * 1.0;
559 double x22 = anEnd2.x() * 1.0;
560 double y21 = aStart2.y() * 1.0;
561 double y22 = anEnd2.y() * 1.0;
563 double k1 = x12 == x11 ? 0 : ( y12 - y11 ) / ( x12 - x11 );
564 double k2 = x22 == x21 ? 0 : ( y22 - y21 ) / ( x22 - x21 );
566 double b1 = y11 - k1 * x11;
567 double b2 = y21 - k2 * x21;
574 return !( ( qMax( x11, x12 ) <= qMin( x21, x22 ) ||
575 qMin( x11, x12 ) >= qMax( x21, x22 ) ) &&
576 ( qMax( y11, y12 ) <= qMin( y21, y22 ) ||
577 qMin( y11, y12 ) >= qMax( y21, y22 ) ) );
581 double x0 = ( b2 - b1 ) / ( k1 - k2 );
582 double y0 = ( k1 * b2 - k2 * b1 ) / ( k1 - k2 );
584 if ( qMin( x11, x12 ) < x0 && x0 < qMax( x11, x12 ) &&
585 qMin( y11, y12 ) < y0 && y0 < qMax( y11, y12 ) &&
586 qMin( x21, x22 ) < x0 && x0 < qMax( x21, x22 ) &&
587 qMin( y21, y22 ) < y0 && y0 < qMax( y21, y22 ) )