From: rnv Date: Wed, 19 Jun 2019 15:01:00 +0000 (+0300) Subject: Selection by a circle in the OCC Viewer X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=984e478437a6d8f809eb3f50c29668de516d9fdb;p=modules%2Fgui.git Selection by a circle in the OCC Viewer --- diff --git a/src/OCCViewer/CMakeLists.txt b/src/OCCViewer/CMakeLists.txt index 6f2aa585d..5590a5c29 100644 --- a/src/OCCViewer/CMakeLists.txt +++ b/src/OCCViewer/CMakeLists.txt @@ -149,6 +149,8 @@ SET(_other_RESOURCES resources/occ_view_ray_tracing.png resources/occ_view_env_texture.png resources/occ_view_light_source.png + resources/occ_view_circle_style.png + resources/occ_view_rect_style.png ) # --- sources --- diff --git a/src/OCCViewer/OCCViewer_ViewSketcher.cxx b/src/OCCViewer/OCCViewer_ViewSketcher.cxx index e70aa8c2b..676a13e7e 100644 --- a/src/OCCViewer/OCCViewer_ViewSketcher.cxx +++ b/src/OCCViewer/OCCViewer_ViewSketcher.cxx @@ -313,14 +313,17 @@ OCCViewer_PolygonSketcher::OCCViewer_PolygonSketcher( OCCViewer_ViewWindow* vw, myToler ( 5, 5 ), //mypPoints ( 0L ), myAddButton ( 0 ), - myDelButton ( 0 ) + myDelButton ( 0 ), + myMode ( Poligone ) { mySketchButton = Qt::RightButton; if ( vw ) - { - OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort(); - mypPolyRB = new QtxPolyRubberBand( avp ); - } + { + OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort(); + mypPolyRB = new QtxPolyRubberBand( avp ); + mypCircleRB = new QtxCircleRubberBand( avp ); + } + mypData = new QPolygon( 0 ); } OCCViewer_PolygonSketcher::~OCCViewer_PolygonSketcher() @@ -332,7 +335,6 @@ OCCViewer_PolygonSketcher::~OCCViewer_PolygonSketcher() void OCCViewer_PolygonSketcher::onActivate() { myDbl = false; - mypData = new QPolygon( 0 ); //mypPoints = new QPolygon( 0 ); switch ( sketchButton() ) @@ -355,13 +357,11 @@ void OCCViewer_PolygonSketcher::onActivate() void OCCViewer_PolygonSketcher::onDeactivate() { - //delete mypPoints; - //mypPoints = 0; - delete (QPolygon*)mypData; - mypData = 0; - if ( mypPolyRB ) mypPolyRB->clearGeometry(); + if (mypCircleRB) + mypCircleRB->clearGeometry(); + ((QPolygon*)mypData)->clear(); } bool OCCViewer_PolygonSketcher::onKey( QKeyEvent* e ) @@ -471,45 +471,53 @@ void OCCViewer_PolygonSketcher::onMouse( QMouseEvent* e ) void OCCViewer_PolygonSketcher::onSketch( SketchState state ) { - //OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort(); - QPolygon* points = (QPolygon*)data(); - /*QPainter p( avp ); - p.setPen( Qt::white ); - p.setCompositionMode( QPainter::CompositionMode_Xor ); - if ( state != Debut ) - p.drawPolyline( *mypPoints ); - - if ( points->count() ) - { - mypPoints->resize( points->count() + 1 ); - for ( uint i = 0; i < points->count(); i++ ) - mypPoints->setPoint( i, points->point( i ) ); - mypPoints->setPoint( points->count(), myCurr ); - if ( state != Fin ) - p.drawPolyline( *mypPoints ); - }*/ - if ( mypPolyRB ) { - if ( state == Fin ) { - mypPolyRB->clearGeometry(); - mypPolyRB->hide(); - mypViewWindow->activateSketching( OCCViewer_ViewWindow::NoSketching ); - } else { - mypPolyRB->setUpdatesEnabled ( false ); - if ( !mypPolyRB->isVisible() ) - mypPolyRB->show(); - //if ( state != Debut ) - // mypPolyRB->repaint(); - - if ( state != Fin && points->count() ) - mypPolyRB->initGeometry( QPolygon(*points) << myCurr ); - //mypPolyRB->addNode( myCurr ); - - //if ( state != Fin ) - // mypPolyRB->repaint(); - mypPolyRB->setUpdatesEnabled ( true ); - //mypPolyRB->repaint(); + switch (myMode) { + case Poligone: + if (mypPolyRB) { + if (state == Fin) { + mypPolyRB->clearGeometry(); + mypPolyRB->hide(); + mypViewWindow->activateSketching(OCCViewer_ViewWindow::NoSketching); + } + else { + mypPolyRB->setUpdatesEnabled(false); + if (!mypPolyRB->isVisible()) + mypPolyRB->show(); + + if (state != Fin && points->count()) + mypPolyRB->initGeometry(QPolygon(*points) << myCurr); + mypPolyRB->setUpdatesEnabled(true); + } } + break; + case Circle: + if (mypCircleRB) { + if (state == Fin) { + mypCircleRB->getPoligon(points); + mypCircleRB->clearGeometry(); + mypCircleRB->hide(); + if (points->size() == CIRCLE_NB_POINTS) + myResult = Accept; + mypViewWindow->activateSketching(OCCViewer_ViewWindow::NoSketching); + } + else { + mypCircleRB->setUpdatesEnabled(false); + + if (state != Fin) { + if (mypCircleRB->isCenterDefined()) { + mypCircleRB->setRadius(myCurr); + if ((mypCircleRB->radius() > MIN_RADIUS) && (!mypCircleRB->isVisible())) + mypCircleRB->show(); + } + else { + mypCircleRB->initGeometry(myCurr); + } + } + mypCircleRB->setUpdatesEnabled(true); + } + } + break; } } @@ -589,3 +597,7 @@ bool OCCViewer_PolygonSketcher::isIntersect( const QPoint& aStart1, const QPoint } +void OCCViewer_PolygonSketcher::setSketcherMode(int theMode) +{ + myMode = (SketchMode)theMode; +} diff --git a/src/OCCViewer/OCCViewer_ViewSketcher.h b/src/OCCViewer/OCCViewer_ViewSketcher.h index 912865499..a1ec747cc 100644 --- a/src/OCCViewer/OCCViewer_ViewSketcher.h +++ b/src/OCCViewer/OCCViewer_ViewSketcher.h @@ -33,6 +33,7 @@ class QPolygon; class QtxRectRubberBand; class QtxPolyRubberBand; +class QtxCircleRubberBand; #ifdef WIN32 #pragma warning ( disable:4251 ) @@ -69,6 +70,8 @@ public: virtual bool isDefault() const; virtual bool eventFilter( QObject*, QEvent* ); + virtual void setSketcherMode(int theMode) {} + private slots: void onDrawViewPort(); @@ -119,9 +122,13 @@ protected: class OCCVIEWER_EXPORT OCCViewer_PolygonSketcher : public OCCViewer_ViewSketcher { public: + enum SketchMode { Poligone, Circle }; + OCCViewer_PolygonSketcher( OCCViewer_ViewWindow*, int ); virtual ~OCCViewer_PolygonSketcher(); + virtual void setSketcherMode(int theMode); + protected: virtual bool onKey( QKeyEvent* ); virtual void onMouse( QMouseEvent* ); @@ -142,6 +149,9 @@ private: int myDelButton; QtxPolyRubberBand* mypPolyRB; + QtxCircleRubberBand* mypCircleRB; + + SketchMode myMode; }; #ifdef WIN32 diff --git a/src/OCCViewer/OCCViewer_ViewWindow.cxx b/src/OCCViewer/OCCViewer_ViewWindow.cxx index f8abc653d..2d8b48f50 100644 --- a/src/OCCViewer/OCCViewer_ViewWindow.cxx +++ b/src/OCCViewer/OCCViewer_ViewWindow.cxx @@ -428,6 +428,10 @@ bool OCCViewer_ViewWindow::eventFilter( QObject* watched, QEvent* e ) emit keyPressed(this, (QKeyEvent*) e); return true; + case QEvent::KeyRelease: + emit keyReleased(this, (QKeyEvent*) e); + return true; + default: break; } @@ -1472,6 +1476,14 @@ void OCCViewer_ViewWindow::createActions() connect(aAction, SIGNAL(toggled(bool)), this, SLOT(onSwitchZoomingStyle(bool))); toolMgr()->registerAction( aAction, SwitchZoomingStyleId ); + // Switch advanced selection style (poligone/circle) + aAction = new QtxAction(tr("MNU_SELECTION_STYLE_SWITCH"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_RECT_STYLE" ) ), + tr( "MNU_SELECTION_STYLE_SWITCH" ), 0, this); + aAction->setStatusTip(tr("DSC_SELECTION_STYLE_SWITCH")); + aAction->setCheckable(true); + connect(aAction, SIGNAL(toggled(bool)), this, SLOT(onSwitchSelectionStyle(bool))); + toolMgr()->registerAction( aAction, SwitchSelectionStyleId); + // Maximized view aAction = new QtxAction(tr("MNU_MINIMIZE_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_MINIMIZE" ) ), tr( "MNU_MINIMIZE_VIEW" ), 0, this ); @@ -1543,6 +1555,7 @@ void OCCViewer_ViewWindow::createToolBar() toolMgr()->append( SwitchZoomingStyleId, tid ); toolMgr()->append( SwitchPreselectionId, tid ); toolMgr()->append( SwitchSelectionId, tid ); + toolMgr()->append(SwitchSelectionStyleId, tid ); if( myModel->trihedronActivated() ) toolMgr()->append( TrihedronShowId, tid ); @@ -2189,6 +2202,26 @@ void OCCViewer_ViewWindow::onSwitchSelection( bool on ) } } +void OCCViewer_ViewWindow::onSwitchSelectionStyle(bool on) +{ + // selection + QtxAction* a = dynamic_cast( toolMgr()->action(SwitchSelectionStyleId) ); + if (a) { + if (a->isChecked() != on) { + a->setChecked(on); + } + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + QPixmap aIcon = on ? aResMgr->loadPixmap("OCCViewer", tr("ICON_OCCVIEWER_CIRCLE_STYLE")) : + aResMgr->loadPixmap("OCCViewer", tr("ICON_OCCVIEWER_RECT_STYLE")); + a->setIcon(aIcon); + } + OCCViewer_ViewSketcher* aSkecher = getSketcher(Polygon); + if (aSkecher) { + aSkecher->setSketcherMode(on ? OCCViewer_PolygonSketcher::Circle : + OCCViewer_PolygonSketcher::Poligone); + } +} + /*! \brief Switches "keyboard free" interaction style on/off */ diff --git a/src/OCCViewer/OCCViewer_ViewWindow.h b/src/OCCViewer/OCCViewer_ViewWindow.h index 6375da086..056d4c5a1 100644 --- a/src/OCCViewer/OCCViewer_ViewWindow.h +++ b/src/OCCViewer/OCCViewer_ViewWindow.h @@ -152,6 +152,7 @@ public: SwitchPreselectionId, SwitchSelectionId, MaximizedId, SynchronizeId, ReturnTo3dViewId, OrthographicId, PerspectiveId, StereoId, RayTracingId, EnvTextureId, LightSourceId, + SwitchSelectionStyleId, UserId }; enum OperationType{ NOTHING, PANVIEW, ZOOMVIEW, ROTATE, @@ -313,6 +314,7 @@ public slots: virtual void onSwitchZoomingStyle( bool on ); virtual void onSwitchPreselection( bool on ); virtual void onSwitchSelection( bool on ); + virtual void onSwitchSelectionStyle( bool on ); virtual void onRayTracing(); virtual void onEnvTexture(); virtual void onLightSource(); diff --git a/src/OCCViewer/resources/OCCViewer_images.ts b/src/OCCViewer/resources/OCCViewer_images.ts index d91f20aaf..a9fc35485 100644 --- a/src/OCCViewer/resources/OCCViewer_images.ts +++ b/src/OCCViewer/resources/OCCViewer_images.ts @@ -119,6 +119,14 @@ ICON_OCCVIEWER_ZOOMING_STYLE_SWITCH occ_view_zooming_style_switch.png + + ICON_OCCVIEWER_RECT_STYLE + occ_view_rect_style.png + + + ICON_OCCVIEWER_CIRCLE_STYLE + occ_view_circle_style.png + ICON_OCCVIEWER_MAXIMIZE occ_view_maximized.png diff --git a/src/OCCViewer/resources/OCCViewer_msg_en.ts b/src/OCCViewer/resources/OCCViewer_msg_en.ts index 5b0a55a01..6d3ad7bf8 100644 --- a/src/OCCViewer/resources/OCCViewer_msg_en.ts +++ b/src/OCCViewer/resources/OCCViewer_msg_en.ts @@ -232,10 +232,18 @@ MNU_ZOOMING_STYLE_SWITCH Zooming style switch + + MNU_SELECTION_STYLE_SWITCH + Advanced selection style switch + DSC_ZOOMING_STYLE_SWITCH Zooming style switch + + DSC_SELECTION_STYLE_SWITCH + Advanced selection style switch + MNU_ENABLE_PRESELECTION Enable/disable preselection diff --git a/src/OCCViewer/resources/OCCViewer_msg_fr.ts b/src/OCCViewer/resources/OCCViewer_msg_fr.ts index 1aaa3ec68..7e0857404 100644 --- a/src/OCCViewer/resources/OCCViewer_msg_fr.ts +++ b/src/OCCViewer/resources/OCCViewer_msg_fr.ts @@ -231,10 +231,18 @@ MNU_ZOOMING_STYLE_SWITCH Changer le style de zoom + + MNU_SELECTION_STYLE_SWITCH + Advanced selection style switch + DSC_ZOOMING_STYLE_SWITCH Changer le style de zoom + + DSC_SELECTION_STYLE_SWITCH + Advanced selection style switch + MNU_ENABLE_PRESELECTION Activer/Désactiver préselection diff --git a/src/OCCViewer/resources/OCCViewer_msg_ja.ts b/src/OCCViewer/resources/OCCViewer_msg_ja.ts index 5613620c4..0820836f4 100644 --- a/src/OCCViewer/resources/OCCViewer_msg_ja.ts +++ b/src/OCCViewer/resources/OCCViewer_msg_ja.ts @@ -232,10 +232,18 @@ MNU_ZOOMING_STYLE_SWITCH ズームのスタイルを変更します。 + + MNU_SELECTION_STYLE_SWITCH + Advanced selection style switch + DSC_ZOOMING_STYLE_SWITCH ズームのスタイルを変更します。 + + DSC_SELECTION_STYLE_SWITCH + Advanced selection style switch + MNU_ENABLE_PRESELECTION 予選の有効/無効にします。 diff --git a/src/OCCViewer/resources/occ_view_circle_style.png b/src/OCCViewer/resources/occ_view_circle_style.png new file mode 100644 index 000000000..ee8bb5055 Binary files /dev/null and b/src/OCCViewer/resources/occ_view_circle_style.png differ diff --git a/src/OCCViewer/resources/occ_view_rect_style.png b/src/OCCViewer/resources/occ_view_rect_style.png new file mode 100644 index 000000000..18b4f0987 Binary files /dev/null and b/src/OCCViewer/resources/occ_view_rect_style.png differ diff --git a/src/Qtx/QtxRubberBand.cxx b/src/Qtx/QtxRubberBand.cxx index 83889d7c5..fe4bbd6a7 100644 --- a/src/Qtx/QtxRubberBand.cxx +++ b/src/Qtx/QtxRubberBand.cxx @@ -30,6 +30,8 @@ #include #include +#include + /*! \class QtxAbstractRubberBand \brief Analog of class QRubberBand with possibility of creation non-rectangular contour for selection. @@ -95,7 +97,7 @@ void QtxAbstractRubberBand::paintEvent( QPaintEvent* theEvent ) QPainter aPainter( this ); aPainter.setRenderHint( QPainter::Antialiasing ); QRect r = myPoints.boundingRect(); - aPainter.setClipRegion( r.normalized().adjusted( -1, -1, 2, 2 ) ); + //aPainter.setClipRegion( r.normalized().adjusted( -1, -1, 2, 2 ) ); aPainter.drawTiledPixmap( 0, 0, width(), height(), tiledPixmap); aPainter.end(); @@ -311,3 +313,95 @@ void QtxPolyRubberBand::setClosed( bool theFlag ) updateMask(); } } + +QtxCircleRubberBand::QtxCircleRubberBand(QWidget* parent) + :QtxAbstractRubberBand(parent), myHasCenter(false) +{ + myPoints.resize(2); + myIsClosed = true; +} + +QtxCircleRubberBand::~QtxCircleRubberBand() +{ +} + +void QtxCircleRubberBand::initGeometry(const QPoint& thePoint) +{ + myIsClosed = false; + myHasCenter = true; + myPoints.clear(); + myPoints << thePoint; + updateMask(); +} + +void QtxCircleRubberBand::setRadius(const QPoint& thePoint) +{ + if (myPoints.size() == 1) + myPoints << thePoint; + else + myPoints.setPoint(1, thePoint); + myIsClosed = true; + updateMask(); +} + +void QtxCircleRubberBand::updateMask() +{ + int aLen = radius(); + if (aLen > MIN_RADIUS) { + QRegion aReg1(myPoints[0].x() - aLen, + myPoints[0].y() - aLen, aLen * 2, aLen * 2, QRegion::Ellipse); + QRegion aReg2(myPoints[0].x() - aLen + 2, + myPoints[0].y() - aLen + 2, aLen * 2 - 4, aLen * 2 - 4, QRegion::Ellipse); + setMask(aReg1 - aReg2); + } +} + +bool QtxCircleRubberBand::isCenterDefined() const +{ + return myHasCenter; +} + +void QtxCircleRubberBand::clearGeometry() +{ + QtxAbstractRubberBand::clearGeometry(); + myHasCenter = false; + myIsClosed = false; +} + +QPoint rotatePoint(const QPoint& theStart, const QPoint& theCenter, double theAngle) +{ + double cosTheta = cos(theAngle); + double sinTheta = sin(theAngle); + int aX = (int)(cosTheta * (theStart.x() - theCenter.x()) - + sinTheta * (theStart.y() - theCenter.y()) + theCenter.x()); + int aY = (int)(sinTheta * (theStart.x() - theCenter.x()) + + cosTheta * (theStart.y() - theCenter.y()) + theCenter.y()); + return QPoint(aX, aY); +} + +static double m_pi = 4 * atan(1); +static double angle_deg = 360. / CIRCLE_NB_POINTS; +static double angle_rad = angle_deg * (m_pi / 180.); + + +void QtxCircleRubberBand::getPoligon(QPolygon* thePoints) const +{ + int aLen = radius(); + if (aLen > MIN_RADIUS) { + thePoints->clear(); + QPoint aCenter = myPoints[0]; + QPoint aStart = myPoints[1]; + for (int i = 0; i < CIRCLE_NB_POINTS; i++) { + thePoints->append(aStart); + aStart = rotatePoint(aStart, aCenter, angle_rad); + } + } +} + +int QtxCircleRubberBand::radius() const +{ + if (myPoints.size() < 2) + return -1; + QPoint aDist = myPoints[1] - myPoints[0]; + return (int)std::sqrt(std::pow(aDist.x(), 2) + std::pow(aDist.y(), 2)); +} \ No newline at end of file diff --git a/src/Qtx/QtxRubberBand.h b/src/Qtx/QtxRubberBand.h index 7d6b10831..4e8b1d939 100644 --- a/src/Qtx/QtxRubberBand.h +++ b/src/Qtx/QtxRubberBand.h @@ -90,4 +90,33 @@ public: void setClosed( bool ); }; + +#define CIRCLE_NB_POINTS 30 +#define MIN_RADIUS 5 + +class QTX_EXPORT QtxCircleRubberBand : public QtxAbstractRubberBand +{ + Q_OBJECT + +public: + QtxCircleRubberBand(QWidget*); + virtual ~QtxCircleRubberBand(); + + void initGeometry(const QPoint&); + + void setRadius(const QPoint&); + + bool isCenterDefined() const; + + virtual void clearGeometry(); + + void getPoligon(QPolygon* thePoints) const; + + int radius() const; + +protected: + virtual void updateMask(); + bool myHasCenter; +}; + #endif //QTXRUBBERBAND_H