1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "OCCViewer_ViewSketcher.h"
21 #include "OCCViewer_ViewWindow.h"
22 #include "OCCViewer_ViewPort3d.h"
24 #include "QtxRubberBand.h"
26 #include <QApplication>
29 #include <QMouseEvent>
32 /****************************************************************
33 ** Class: OCCViewer_ViewSketcher
35 *****************************************************************/
37 OCCViewer_ViewSketcher::OCCViewer_ViewSketcher( OCCViewer_ViewWindow* vw, int type )
39 mySketchButton( Qt::LeftButton ),
48 OCCViewer_ViewSketcher::~OCCViewer_ViewSketcher()
52 void OCCViewer_ViewSketcher::activate()
54 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
56 mySavedCursor = avp->cursor();
57 avp->setCursor( Qt::PointingHandCursor );
58 avp->installEventFilter( this );
59 qApp->installEventFilter( this );
61 connect( avp, SIGNAL( vpDrawExternal( QPainter* ) ), this, SLOT( onDrawViewPort() ) );
69 void OCCViewer_ViewSketcher::deactivate()
71 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
73 disconnect( avp, SIGNAL( vpDrawExternal( QPainter* ) ), this, SLOT( onDrawViewPort() ) );
75 qApp->removeEventFilter( this );
76 avp->removeEventFilter( this );
77 avp->setCursor( mySavedCursor );
82 int OCCViewer_ViewSketcher::type() const
87 void* OCCViewer_ViewSketcher::data() const
92 int OCCViewer_ViewSketcher::result() const
97 int OCCViewer_ViewSketcher::buttonState() const
102 void OCCViewer_ViewSketcher::onActivate()
106 void OCCViewer_ViewSketcher::onDeactivate()
110 bool OCCViewer_ViewSketcher::isDefault() const
115 bool OCCViewer_ViewSketcher::eventFilter( QObject* o, QEvent* e )
117 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
119 SketchState state = EnTrain;
125 case QEvent::MouseMove:
126 case QEvent::MouseButtonPress:
127 case QEvent::MouseButtonRelease:
128 case QEvent::MouseButtonDblClick:
130 QMouseEvent* me = (QMouseEvent*)e;
132 myButtonState = me->buttons();
133 if ( e->type() == QEvent::MouseButtonPress )
134 myButtonState |= me->button();
136 if ( myStart.isNull() && ( myButtonState & sketchButton() ) )
146 if ( myResult != Neutral )
153 case QEvent::HideToParent:
161 if ( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease )
163 ignore = onKey( (QKeyEvent*)e );
164 if ( myResult != Neutral )
173 return QObject::eventFilter( o, e );
176 void OCCViewer_ViewSketcher::onDrawViewPort()
181 bool OCCViewer_ViewSketcher::onKey( QKeyEvent* )
186 void OCCViewer_ViewSketcher::onMouse( QMouseEvent* )
190 int OCCViewer_ViewSketcher::sketchButton()
192 return mySketchButton;
195 void OCCViewer_ViewSketcher::setSketchButton( int b )
200 /****************************************************************
201 ** Class: OCCViewer_RectSketcher
203 *****************************************************************/
205 OCCViewer_RectSketcher::OCCViewer_RectSketcher( OCCViewer_ViewWindow* vw, int typ )
206 : OCCViewer_ViewSketcher( vw, typ )
210 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
211 mypRectRB = new QtxRectRubberBand( avp );
215 OCCViewer_RectSketcher::~OCCViewer_RectSketcher()
217 delete (QRect*)mypData;
220 void OCCViewer_RectSketcher::onActivate()
222 mypData = new QRect();
225 void OCCViewer_RectSketcher::onDeactivate()
227 delete (QRect*)mypData;
229 mypRectRB->clearGeometry();
232 bool OCCViewer_RectSketcher::onKey( QKeyEvent* e )
234 if ( e->key() == Qt::Key_Escape )
236 else if ( e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return )
242 void OCCViewer_RectSketcher::onMouse( QMouseEvent* e )
244 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
246 if ( avp->rect().contains( myCurr ) )
247 avp->setCursor( Qt::PointingHandCursor );
249 avp->setCursor( Qt::ForbiddenCursor );
251 if ( e->type() == QEvent::MouseButtonRelease && e->button() == sketchButton() )
254 QApplication::postEvent( avp, new QMouseEvent( e->type(), e->pos(),
255 e->globalPos(), e->button(),
256 e->buttons(), e->modifiers() ) );
260 void OCCViewer_RectSketcher::onSketch( SketchState state )
262 //OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
266 QRect* sketchRect = (QRect*)data();
267 if ( myButtonState & sketchButton() )
269 QRect rect = QRect( myStart, myCurr ).normalized();
270 /*QRect rect( qMin( myStart.x(), myCurr.x() ), qMin( myStart.y(), myCurr.y() ),
271 qAbs( myStart.x() - myCurr.x() ), qAbs( myStart.y() - myCurr.y() ) );
273 p.setPen( Qt::white );
274 p.setCompositionMode( QPainter::CompositionMode_Xor );
277 //if ( state != Debut && !sketchRect->isEmpty() )
278 // p.drawRect( *sketchRect );
281 if ( !rect.isEmpty() && state != Fin )
283 //p.drawRect( *sketchRect );
284 mypRectRB->initGeometry( rect );
294 QApplication::syncX(); /* force rectangle redrawing */
295 mypViewWindow->activateSketching( OCCViewer_ViewWindow::NoSketching );
299 /****************************************************************
300 ** Class: OCCViewer_PolygonSketcher
302 *****************************************************************/
304 OCCViewer_PolygonSketcher::OCCViewer_PolygonSketcher( OCCViewer_ViewWindow* vw, int typ )
305 : OCCViewer_ViewSketcher( vw, typ ),
312 mySketchButton = Qt::RightButton;
315 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
316 mypPolyRB = new QtxPolyRubberBand( avp );
320 OCCViewer_PolygonSketcher::~OCCViewer_PolygonSketcher()
323 delete (QPolygon*)mypData;
326 void OCCViewer_PolygonSketcher::onActivate()
329 mypData = new QPolygon( 0 );
330 //mypPoints = new QPolygon( 0 );
332 switch ( sketchButton() )
335 myAddButton = Qt::RightButton;
336 myDelButton = Qt::MidButton;
339 myAddButton = Qt::LeftButton;
340 myDelButton = Qt::RightButton;
342 case Qt::RightButton:
344 myAddButton = Qt::LeftButton;
345 myDelButton = Qt::MidButton;
350 void OCCViewer_PolygonSketcher::onDeactivate()
354 delete (QPolygon*)mypData;
358 mypPolyRB->clearGeometry();
361 bool OCCViewer_PolygonSketcher::onKey( QKeyEvent* e )
363 if ( e->key() == Qt::Key_Escape )
368 else if ( e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return )
370 QPolygon* points = (QPolygon*)data();
371 if ( points->count() )
373 QPoint last = points->point( points->count() - 1 );
374 if ( last != myCurr )
376 points->resize( points->count() + 1 );
377 points->setPoint( points->count() - 1, myCurr );
383 else if ( e->key() == Qt::Key_Backspace && e->type() == QEvent::KeyRelease )
385 QPolygon* points = (QPolygon*)data();
386 if ( points->count() > 1 )
387 points->resize( points->count() - 1 );
395 void OCCViewer_PolygonSketcher::onMouse( QMouseEvent* e )
397 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
399 QPolygon* points = (QPolygon*)data();
400 if ( !points->count() && !myStart.isNull() )
402 points->resize( points->count() + 1 );
403 points->setPoint( points->count() - 1, myStart );
407 bool valid = avp->rect().contains( myCurr );
408 if ( !myStart.isNull() )
410 QRect aRect( myStart.x() - myToler.width(), myStart.y() - myToler.height(),
411 2 * myToler.width(), 2 * myToler.height() );
412 closed = aRect.contains( myCurr );
414 valid = valid && isValid( points, myCurr );
415 if ( closed && !valid )
419 avp->setCursor( Qt::CrossCursor );
421 avp->setCursor( Qt::PointingHandCursor );
423 avp->setCursor( Qt::ForbiddenCursor );
428 if ( e->type() == QEvent::MouseButtonRelease && ( e->button() & sketchButton() ) )
431 QApplication::postEvent( avp, new QMouseEvent( e->type(), e->pos(),
432 e->globalPos(), e->button(),
433 e->buttons(), e->modifiers() ) );
435 else if ( e->type() == QEvent::MouseButtonRelease && ( e->button() & myAddButton ) )
441 if ( myStart.isNull() )
445 QPoint last = points->point( points->count() - 1 );
446 if ( last != myCurr && valid )
448 points->resize( points->count() + 1 );
449 points->setPoint( points->count() - 1, myCurr );
451 if ( valid && myDbl )
456 else if ( ( e->type() == QEvent::MouseButtonRelease && ( e->button() & myDelButton ) ) ||
457 ( e->type() == QEvent::MouseButtonDblClick && ( e->button() & myDelButton ) ) )
459 if ( points->count() > 1 )
460 points->resize( points->count() - 1 );
463 myDbl = e->type() == QEvent::MouseButtonDblClick && ( e->button() & myAddButton );
466 void OCCViewer_PolygonSketcher::onSketch( SketchState state )
468 //OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
470 QPolygon* points = (QPolygon*)data();
472 p.setPen( Qt::white );
473 p.setCompositionMode( QPainter::CompositionMode_Xor );
474 if ( state != Debut )
475 p.drawPolyline( *mypPoints );
477 if ( points->count() )
479 mypPoints->resize( points->count() + 1 );
480 for ( uint i = 0; i < points->count(); i++ )
481 mypPoints->setPoint( i, points->point( i ) );
482 mypPoints->setPoint( points->count(), myCurr );
484 p.drawPolyline( *mypPoints );
488 mypPolyRB->setUpdatesEnabled ( false );
489 if ( !mypPolyRB->isVisible() )
491 //if ( state != Debut )
492 // mypPolyRB->repaint();
494 if ( state != Fin && points->count() )
495 mypPolyRB->initGeometry( QPolygon(*points) << myCurr );
496 //mypPolyRB->addNode( myCurr );
498 //if ( state != Fin )
499 // mypPolyRB->repaint();
500 mypPolyRB->setUpdatesEnabled ( true );
501 //mypPolyRB->repaint();
508 mypPolyRB->clearGeometry();
511 QApplication::syncX();
512 mypViewWindow->activateSketching( OCCViewer_ViewWindow::NoSketching );
516 bool OCCViewer_PolygonSketcher::isValid( const QPolygon* aPoints, const QPoint& aCur ) const
518 if ( !aPoints->count() )
521 if ( aPoints->count() == 1 && aPoints->point( 0 ) == aCur )
524 const QPoint& aLast = aPoints->point( aPoints->count() - 1 );
530 for ( uint i = 0; i < aPoints->count() - 1 && res; i++ )
532 const QPoint& aStart = aPoints->point( i );
533 const QPoint& anEnd = aPoints->point( i + 1 );
534 res = !isIntersect( aStart, anEnd, aCur, aLast );
540 bool OCCViewer_PolygonSketcher::isIntersect( const QPoint& aStart1, const QPoint& anEnd1,
541 const QPoint& aStart2, const QPoint& anEnd2 ) const
543 if ( ( aStart1 == aStart2 && anEnd1 == anEnd2 ) ||
544 ( aStart1 == anEnd2 && anEnd1 == aStart2 ) )
547 if ( aStart1 == aStart2 || aStart2 == anEnd1 ||
548 aStart1 == anEnd2 || anEnd1 == anEnd2 )
551 double x11 = aStart1.x() * 1.0;
552 double x12 = anEnd1.x() * 1.0;
553 double y11 = aStart1.y() * 1.0;
554 double y12 = anEnd1.y() * 1.0;
556 double x21 = aStart2.x() * 1.0;
557 double x22 = anEnd2.x() * 1.0;
558 double y21 = aStart2.y() * 1.0;
559 double y22 = anEnd2.y() * 1.0;
561 double k1 = x12 == x11 ? 0 : ( y12 - y11 ) / ( x12 - x11 );
562 double k2 = x22 == x21 ? 0 : ( y22 - y21 ) / ( x22 - x21 );
564 double b1 = y11 - k1 * x11;
565 double b2 = y21 - k2 * x21;
572 return !( ( qMax( x11, x12 ) <= qMin( x21, x22 ) ||
573 qMin( x11, x12 ) >= qMax( x21, x22 ) ) &&
574 ( qMax( y11, y12 ) <= qMin( y21, y22 ) ||
575 qMin( y11, y12 ) >= qMax( y21, y22 ) ) );
579 double x0 = ( b2 - b1 ) / ( k1 - k2 );
580 double y0 = ( k1 * b2 - k2 * b1 ) / ( k1 - k2 );
582 if ( qMin( x11, x12 ) < x0 && x0 < qMax( x11, x12 ) &&
583 qMin( y11, y12 ) < y0 && y0 < qMax( y11, y12 ) &&
584 qMin( x21, x22 ) < x0 && x0 < qMax( x21, x22 ) &&
585 qMin( y21, y22 ) < y0 && y0 < qMax( y21, y22 ) )