1 // Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
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 <qapplication.h>
26 #include <qpointarray.h>
28 /****************************************************************
29 ** Class: OCCViewer_ViewSketcher
31 *****************************************************************/
33 OCCViewer_ViewSketcher::OCCViewer_ViewSketcher( OCCViewer_ViewWindow* vw, int type )
35 mySketchButton( Qt::LeftButton ),
44 OCCViewer_ViewSketcher::~OCCViewer_ViewSketcher()
48 void OCCViewer_ViewSketcher::activate()
50 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
52 mySavedCursor = avp->cursor();
53 avp->setCursor( Qt::PointingHandCursor );
54 avp->installEventFilter( this );
55 qApp->installEventFilter( this );
57 connect( avp, SIGNAL( vpDrawExternal( QPainter* ) ), this, SLOT( onDrawViewPort() ) );
65 void OCCViewer_ViewSketcher::deactivate()
67 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
69 disconnect( avp, SIGNAL( vpDrawExternal( QPainter* ) ), this, SLOT( onDrawViewPort() ) );
71 qApp->removeEventFilter( this );
72 avp->removeEventFilter( this );
73 avp->setCursor( mySavedCursor );
78 int OCCViewer_ViewSketcher::type() const
83 void* OCCViewer_ViewSketcher::data() const
88 int OCCViewer_ViewSketcher::result() const
93 int OCCViewer_ViewSketcher::buttonState() const
98 void OCCViewer_ViewSketcher::onActivate()
102 void OCCViewer_ViewSketcher::onDeactivate()
106 bool OCCViewer_ViewSketcher::isDefault() const
111 bool OCCViewer_ViewSketcher::eventFilter( QObject* o, QEvent* e )
113 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
115 SketchState state = EnTrain;
121 case QEvent::MouseMove:
122 case QEvent::MouseButtonPress:
123 case QEvent::MouseButtonRelease:
124 case QEvent::MouseButtonDblClick:
126 QMouseEvent* me = (QMouseEvent*)e;
128 myButtonState = me->state();
129 if ( e->type() == QEvent::MouseButtonPress )
130 myButtonState |= me->button();
132 if ( myStart.isNull() && ( myButtonState & sketchButton() ) )
142 if ( myResult != Neutral )
149 case QEvent::HideToParent:
157 if ( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease )
159 ignore = onKey( (QKeyEvent*)e );
160 if ( myResult != Neutral )
169 return QObject::eventFilter( o, e );
172 void OCCViewer_ViewSketcher::onDrawViewPort()
177 bool OCCViewer_ViewSketcher::onKey( QKeyEvent* )
182 void OCCViewer_ViewSketcher::onMouse( QMouseEvent* )
186 int OCCViewer_ViewSketcher::sketchButton()
188 return mySketchButton;
191 void OCCViewer_ViewSketcher::setSketchButton( int b )
196 /****************************************************************
197 ** Class: OCCViewer_RectSketcher
199 *****************************************************************/
201 OCCViewer_RectSketcher::OCCViewer_RectSketcher( OCCViewer_ViewWindow* vw, int typ )
202 : OCCViewer_ViewSketcher( vw, typ )
206 OCCViewer_RectSketcher::~OCCViewer_RectSketcher()
211 void OCCViewer_RectSketcher::onActivate()
213 mypData = new QRect();
216 void OCCViewer_RectSketcher::onDeactivate()
222 bool OCCViewer_RectSketcher::onKey( QKeyEvent* e )
224 if ( e->key() == Qt::Key_Escape )
226 else if ( e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return )
232 void OCCViewer_RectSketcher::onMouse( QMouseEvent* e )
234 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
236 if ( avp->rect().contains( myCurr ) )
237 avp->setCursor( Qt::PointingHandCursor );
239 avp->setCursor( Qt::ForbiddenCursor );
241 if ( e->type() == QEvent::MouseButtonRelease && e->button() == sketchButton() )
244 QApplication::postEvent( avp, new QMouseEvent( e->type(), e->pos(),
245 e->globalPos(), e->state(), e->button() ) );
249 void OCCViewer_RectSketcher::onSketch( SketchState state )
251 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
253 QRect* sketchRect = (QRect*)data();
254 if ( myButtonState & sketchButton() )
256 QRect rect( QMIN( myStart.x(), myCurr.x() ), QMIN( myStart.y(), myCurr.y() ),
257 QABS( myStart.x() - myCurr.x() ), QABS( myStart.y() - myCurr.y() ) );
259 p.setPen( Qt::white );
260 p.setRasterOp( Qt::XorROP );
261 if ( state != Debut && !sketchRect->isEmpty() )
262 p.drawRect( *sketchRect );
264 if ( !rect.isEmpty() && state != Fin )
265 p.drawRect( *sketchRect );
270 QApplication::syncX(); /* force rectangle redrawing */
271 mypViewWindow->activateSketching( OCCViewer_ViewWindow::NoSketching );
275 /****************************************************************
276 ** Class: OCCViewer_PolygonSketcher
278 *****************************************************************/
280 OCCViewer_PolygonSketcher::OCCViewer_PolygonSketcher( OCCViewer_ViewWindow* vw, int typ )
281 : OCCViewer_ViewSketcher( vw, typ ),
288 mySketchButton = Qt::RightButton;
291 OCCViewer_PolygonSketcher::~OCCViewer_PolygonSketcher()
297 void OCCViewer_PolygonSketcher::onActivate()
300 mypData = new QPointArray( 0 );
301 mypPoints = new QPointArray( 0 );
303 switch ( sketchButton() )
306 myAddButton = Qt::RightButton;
307 myDelButton = Qt::MidButton;
310 myAddButton = Qt::LeftButton;
311 myDelButton = Qt::RightButton;
313 case Qt::RightButton:
315 myAddButton = Qt::LeftButton;
316 myDelButton = Qt::MidButton;
321 void OCCViewer_PolygonSketcher::onDeactivate()
329 bool OCCViewer_PolygonSketcher::onKey( QKeyEvent* e )
331 if ( e->key() == Qt::Key_Escape )
336 else if ( e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return )
338 QPointArray* points = (QPointArray*)data();
339 if ( points->count() )
341 QPoint last = points->point( points->count() - 1 );
342 if ( last != myCurr )
344 points->resize( points->count() + 1 );
345 points->setPoint( points->count() - 1, myCurr );
351 else if ( e->key() == Qt::Key_Backspace && e->type() == QEvent::KeyRelease )
353 QPointArray* points = (QPointArray*)data();
354 if ( points->count() > 1 )
355 points->resize( points->count() - 1 );
363 void OCCViewer_PolygonSketcher::onMouse( QMouseEvent* e )
365 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
367 QPointArray* points = (QPointArray*)data();
368 if ( !points->count() && !myStart.isNull() )
370 points->resize( points->count() + 1 );
371 points->setPoint( points->count() - 1, myStart );
375 bool valid = avp->rect().contains( myCurr );
376 if ( !myStart.isNull() )
378 QRect aRect( myStart.x() - myToler.width(), myStart.y() - myToler.height(),
379 2 * myToler.width(), 2 * myToler.height() );
380 closed = aRect.contains( myCurr );
382 valid = valid && isValid( points, myCurr );
383 if ( closed && !valid )
387 avp->setCursor( Qt::CrossCursor );
389 avp->setCursor( Qt::PointingHandCursor );
391 avp->setCursor( Qt::ForbiddenCursor );
396 if ( e->type() == QEvent::MouseButtonRelease && ( e->button() & sketchButton() ) )
399 QApplication::postEvent( avp, new QMouseEvent( e->type(), e->pos(),
400 e->globalPos(), e->state(), e->button() ) );
402 else if ( e->type() == QEvent::MouseButtonRelease && ( e->button() & myAddButton ) )
408 if ( myStart.isNull() )
412 QPoint last = points->point( points->count() - 1 );
413 if ( last != myCurr && valid )
415 points->resize( points->count() + 1 );
416 points->setPoint( points->count() - 1, myCurr );
418 if ( valid && myDbl )
423 else if ( ( e->type() == QEvent::MouseButtonRelease && ( e->button() & myDelButton ) ) ||
424 ( e->type() == QEvent::MouseButtonDblClick && ( e->button() & myDelButton ) ) )
426 if ( points->count() > 1 )
427 points->resize( points->count() - 1 );
430 myDbl = e->type() == QEvent::MouseButtonDblClick && ( e->button() & myAddButton );
433 void OCCViewer_PolygonSketcher::onSketch( SketchState state )
435 OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
437 QPointArray* points = (QPointArray*)data();
439 p.setPen( Qt::white );
440 p.setRasterOp( Qt::XorROP );
441 if ( state != Debut )
442 p.drawPolyline( *mypPoints );
444 if ( points->count() )
446 mypPoints->resize( points->count() + 1 );
447 for ( uint i = 0; i < points->count(); i++ )
448 mypPoints->setPoint( i, points->point( i ) );
449 mypPoints->setPoint( points->count(), myCurr );
451 p.drawPolyline( *mypPoints );
456 QApplication::syncX();
457 mypViewWindow->activateSketching( OCCViewer_ViewWindow::NoSketching );
461 bool OCCViewer_PolygonSketcher::isValid( const QPointArray* aPoints, const QPoint& aCur ) const
463 if ( !aPoints->count() )
466 if ( aPoints->count() == 1 && aPoints->point( 0 ) == aCur )
469 const QPoint& aLast = aPoints->point( aPoints->count() - 1 );
475 for ( uint i = 0; i < aPoints->count() - 1 && res; i++ )
477 const QPoint& aStart = aPoints->point( i );
478 const QPoint& anEnd = aPoints->point( i + 1 );
479 res = !isIntersect( aStart, anEnd, aCur, aLast );
485 bool OCCViewer_PolygonSketcher::isIntersect( const QPoint& aStart1, const QPoint& anEnd1,
486 const QPoint& aStart2, const QPoint& anEnd2 ) const
488 if ( ( aStart1 == aStart2 && anEnd1 == anEnd2 ) ||
489 ( aStart1 == anEnd2 && anEnd1 == aStart2 ) )
492 if ( aStart1 == aStart2 || aStart2 == anEnd1 ||
493 aStart1 == anEnd2 || anEnd1 == anEnd2 )
496 double x11 = aStart1.x() * 1.0;
497 double x12 = anEnd1.x() * 1.0;
498 double y11 = aStart1.y() * 1.0;
499 double y12 = anEnd1.y() * 1.0;
501 double x21 = aStart2.x() * 1.0;
502 double x22 = anEnd2.x() * 1.0;
503 double y21 = aStart2.y() * 1.0;
504 double y22 = anEnd2.y() * 1.0;
506 double k1 = x12 == x11 ? 0 : ( y12 - y11 ) / ( x12 - x11 );
507 double k2 = x22 == x21 ? 0 : ( y22 - y21 ) / ( x22 - x21 );
509 double b1 = y11 - k1 * x11;
510 double b2 = y21 - k2 * x21;
517 return !( ( QMAX( x11, x12 ) <= QMIN( x21, x22 ) ||
518 QMIN( x11, x12 ) >= QMAX( x21, x22 ) ) &&
519 ( QMAX( y11, y12 ) <= QMIN( y21, y22 ) ||
520 QMIN( y11, y12 ) >= QMAX( y21, y22 ) ) );
524 double x0 = ( b2 - b1 ) / ( k1 - k2 );
525 double y0 = ( k1 * b2 - k2 * b1 ) / ( k1 - k2 );
527 if ( QMIN( x11, x12 ) < x0 && x0 < QMAX( x11, x12 ) &&
528 QMIN( y11, y12 ) < y0 && y0 < QMAX( y11, y12 ) &&
529 QMIN( x21, x22 ) < x0 && x0 < QMAX( x21, x22 ) &&
530 QMIN( y21, y22 ) < y0 && y0 < QMAX( y21, y22 ) )