From eb62b48bcde4c7b5c8d30b549e8ea89186dd9215 Mon Sep 17 00:00:00 2001 From: isn Date: Wed, 8 Nov 2017 15:17:46 +0300 Subject: [PATCH] refs #1329 (draft) --- src/OCCViewer/OCCViewer_Utilities.cxx | 33 ++++ src/OCCViewer/OCCViewer_Utilities.h | 2 + src/OCCViewer/OCCViewer_ViewWindow.cxx | 208 ++++++++++++++++++++++--- src/OCCViewer/OCCViewer_ViewWindow.h | 10 +- 4 files changed, 229 insertions(+), 24 deletions(-) diff --git a/src/OCCViewer/OCCViewer_Utilities.cxx b/src/OCCViewer/OCCViewer_Utilities.cxx index e88b29182..8bb0bd4cd 100755 --- a/src/OCCViewer/OCCViewer_Utilities.cxx +++ b/src/OCCViewer/OCCViewer_Utilities.cxx @@ -232,3 +232,36 @@ bool OCCViewer_Utilities::computeVisibleBBCenter( const Handle(V3d_View) theView return true; } + +bool OCCViewer_Utilities::computeSceneBBCenter( const Handle(V3d_View) theView, + double& theX, double& theY, double& theZ ) +{ + theX = 0, theY = 0, theZ = 0; + Bnd_Box aBox = theView->View()->MinMaxValues(); + if (!aBox.IsVoid()) + { + double Xmin, Ymin, Zmin, Xmax, Ymax, Zmax; + aBox.Get (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax); + gp_Pnt aPnts[8] = + { + gp_Pnt (Xmin, Ymin, Zmin), gp_Pnt (Xmin, Ymin, Zmax), + gp_Pnt (Xmin, Ymax, Zmin), gp_Pnt (Xmin, Ymax, Zmax), + gp_Pnt (Xmax, Ymin, Zmin), gp_Pnt (Xmax, Ymin, Zmax), + gp_Pnt (Xmax, Ymax, Zmin), gp_Pnt (Xmax, Ymax, Zmax) + }; + + for (Standard_Integer i = 0; i < 8; i++) + { + const gp_Pnt& aCornPnt = aPnts[i]; + theX += aCornPnt.X(); + theY += aCornPnt.Y(); + theZ += aCornPnt.Z(); + } + + theX /= 8; + theY /= 8; + theZ /= 8; + return true; + } + return false; +} \ No newline at end of file diff --git a/src/OCCViewer/OCCViewer_Utilities.h b/src/OCCViewer/OCCViewer_Utilities.h index 68f845a8f..7db427e50 100755 --- a/src/OCCViewer/OCCViewer_Utilities.h +++ b/src/OCCViewer/OCCViewer_Utilities.h @@ -80,6 +80,8 @@ public: * \return \c true if the bounding box center is computed */ static bool computeVisibleBBCenter( const Handle(V3d_View) theView, double& theX, double& theY, double& theZ ); + + static bool computeSceneBBCenter( const Handle(V3d_View) theView, double& theX, double& theY, double& theZ ); }; #endif // OCCVIEWER_UTILITIES_H diff --git a/src/OCCViewer/OCCViewer_ViewWindow.cxx b/src/OCCViewer/OCCViewer_ViewWindow.cxx index cfeb79fb4..0ef29a1b9 100644 --- a/src/OCCViewer/OCCViewer_ViewWindow.cxx +++ b/src/OCCViewer/OCCViewer_ViewWindow.cxx @@ -85,6 +85,7 @@ #if OCC_VERSION_LARGE > 0x06090000 #include #include +#include #endif #if OCC_VERSION_MAJOR < 7 @@ -244,8 +245,8 @@ const char* imageCrossCursor[] = { "................................", "................................"}; - -/*! + + /*! \brief Constructor \param theDesktop main window of application \param theModel OCC 3D viewer @@ -277,6 +278,7 @@ OCCViewer_ViewWindow::OCCViewer_ViewWindow( SUIT_Desktop* theDesktop, myCursorIsHand = false; myPanningByBtn = false; + myAutomaticZoom = true; clearViewAspects(); } @@ -714,13 +716,16 @@ bool OCCViewer_ViewWindow::computeGravityCenter( double& theX, double& theY, dou continue; #if OCC_VERSION_LARGE > 0x06070100 - Bnd_Box aBox = aStructure->MinMaxValues(); - aXmin = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().X(); - aYmin = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().Y(); - aZmin = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().Z(); - aXmax = aBox.IsVoid() ? RealLast() : aBox.CornerMax().X(); - aYmax = aBox.IsVoid() ? RealLast() : aBox.CornerMax().Y(); - aZmax = aBox.IsVoid() ? RealLast() : aBox.CornerMax().Z(); + Bnd_Box aBox1 = aStructure->MinMaxValues(); + const Graphic3d_BndBox3d& aBox = aStructure->CStructure()->BoundingBox(); + if (!aBox.IsValid()) + continue; + aXmin = /*aBox.IsVoid() ? RealFirst() :*/ aBox.CornerMin().x(); + aYmin = /*aBox.IsVoid() ? RealFirst() : */aBox.CornerMin().y(); + aZmin = /*aBox.IsVoid() ? RealFirst() : */aBox.CornerMin().z(); + aXmax = /*aBox.IsVoid() ? RealLast() : */aBox.CornerMax().x(); + aYmax = /*aBox.IsVoid() ? RealLast() : */aBox.CornerMax().y(); + aZmax = /*aBox.IsVoid() ? RealLast() : */aBox.CornerMax().z(); #else aStructure->MinMaxValues( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax ); #endif @@ -771,8 +776,85 @@ bool OCCViewer_ViewWindow::computeGravityCenter( double& theX, double& theY, dou theX /= aPointsNb; theY /= aPointsNb; theZ /= aPointsNb; + return true; } - return true; + else + return false; +} + +bool OCCViewer_ViewWindow::computeGravityCenter1(gp_XYZ& gravityCenter) +{ + Handle(V3d_View) aView3d = myViewPort->getView(); + Graphic3d_MapOfStructure aSetOfStructures; + aView3d->View()->DisplayedStructures (aSetOfStructures); + + Standard_Boolean hasSelection = Standard_False; + for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aSetOfStructures); + aStructIter.More(); aStructIter.Next()) + { + if (aStructIter.Key()->IsHighlighted() + && aStructIter.Key()->IsVisible()) + { + hasSelection = Standard_True; + break; + } + } + + Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax; + Standard_Integer aNbPoints = 0; + gravityCenter.SetCoord(0,0,0); + for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aSetOfStructures); + aStructIter.More(); aStructIter.Next()) + { + const Handle(Graphic3d_Structure)& aStruct = aStructIter.Key(); + if (!aStruct->IsVisible() + || aStruct->IsInfinite() + || (hasSelection && !aStruct->IsHighlighted())) + { + continue; + } + + const Graphic3d_BndBox3d& aBox = aStruct->CStructure()->BoundingBox(); + if (!aBox.IsValid()) + { + continue; + } + + // skip transformation-persistent objects + if (!aStruct->TransformPersistence().IsNull()) + continue; + + // use camera projection to find gravity point + Xmin = aBox.CornerMin().x(); + Ymin = aBox.CornerMin().y(); + Zmin = aBox.CornerMin().z(); + Xmax = aBox.CornerMax().x(); + Ymax = aBox.CornerMax().y(); + Zmax = aBox.CornerMax().z(); + gp_Pnt aPnts[8] = + { + gp_Pnt (Xmin, Ymin, Zmin), gp_Pnt (Xmin, Ymin, Zmax), + gp_Pnt (Xmin, Ymax, Zmin), gp_Pnt (Xmin, Ymax, Zmax), + gp_Pnt (Xmax, Ymin, Zmin), gp_Pnt (Xmax, Ymin, Zmax), + gp_Pnt (Xmax, Ymax, Zmin), gp_Pnt (Xmax, Ymax, Zmax) + }; + + for (Standard_Integer aPntIt = 0; aPntIt < 8; ++aPntIt) + { + const gp_Pnt& aBndPnt = aPnts[aPntIt]; + const gp_Pnt aProjected = aView3d->Camera()->Project (aBndPnt); + if (Abs (aProjected.X()) <= 1.0 + && Abs (aProjected.Y()) <= 1.0) + { + gravityCenter += aBndPnt.XYZ(); + ++aNbPoints; + } + } + } + if (aNbPoints > 0) + return true; + else + return false; } /*! @@ -1612,8 +1694,14 @@ void OCCViewer_ViewWindow::onFrontView() { emit vpTransformationStarted ( FRONTVIEW ); Handle(V3d_View) aView3d = myViewPort->getView(); - if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Xpos); - onViewFitAll(); + if (myAutomaticZoom) + { + if ( !aView3d.IsNull() ) + aView3d->SetProj (V3d_Xpos); + onViewFitAll(); + } + else + ProjAndPanToGravity(V3d_Xpos); emit vpTransformationFinished ( FRONTVIEW ); } @@ -1624,8 +1712,14 @@ void OCCViewer_ViewWindow::onBackView() { emit vpTransformationStarted ( BACKVIEW ); Handle(V3d_View) aView3d = myViewPort->getView(); - if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Xneg); - onViewFitAll(); + if (myAutomaticZoom) + { + if ( !aView3d.IsNull() ) + aView3d->SetProj (V3d_Xneg); + onViewFitAll(); + } + else + ProjAndPanToGravity(V3d_Xneg); emit vpTransformationFinished ( BACKVIEW ); } @@ -1636,8 +1730,14 @@ void OCCViewer_ViewWindow::onTopView() { emit vpTransformationStarted ( TOPVIEW ); Handle(V3d_View) aView3d = myViewPort->getView(); - if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Zpos); - onViewFitAll(); + if (myAutomaticZoom) + { + if ( !aView3d.IsNull() ) + aView3d->SetProj (V3d_Zpos); + onViewFitAll(); + } + else + ProjAndPanToGravity(V3d_Zpos); emit vpTransformationFinished ( TOPVIEW ); } @@ -1648,8 +1748,14 @@ void OCCViewer_ViewWindow::onBottomView() { emit vpTransformationStarted ( BOTTOMVIEW ); Handle(V3d_View) aView3d = myViewPort->getView(); - if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Zneg); - onViewFitAll(); + if (myAutomaticZoom) + { + if ( !aView3d.IsNull() ) + aView3d->SetProj (V3d_Zneg); + onViewFitAll(); + } + else + ProjAndPanToGravity(V3d_Zneg); emit vpTransformationFinished ( BOTTOMVIEW ); } @@ -1660,8 +1766,14 @@ void OCCViewer_ViewWindow::onLeftView() { emit vpTransformationStarted ( LEFTVIEW ); Handle(V3d_View) aView3d = myViewPort->getView(); - if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Yneg); - onViewFitAll(); + if (myAutomaticZoom) + { + if ( !aView3d.IsNull() ) + aView3d->SetProj (V3d_Yneg); + onViewFitAll(); + } + else + ProjAndPanToGravity(V3d_Yneg); emit vpTransformationFinished ( LEFTVIEW ); } @@ -1672,8 +1784,14 @@ void OCCViewer_ViewWindow::onRightView() { emit vpTransformationStarted ( RIGHTVIEW ); Handle(V3d_View) aView3d = myViewPort->getView(); - if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Ypos); - onViewFitAll(); + if (myAutomaticZoom) + { + if ( !aView3d.IsNull() ) + aView3d->SetProj (V3d_Ypos); + onViewFitAll(); + } + else + ProjAndPanToGravity(V3d_Ypos); emit vpTransformationFinished ( RIGHTVIEW ); } @@ -3416,7 +3534,6 @@ bool OCCViewer_ViewWindow::isQuadBufferSupport() const return enable; } - bool OCCViewer_ViewWindow::isOpenGlStereoSupport() const { GLboolean support[1]; @@ -3805,3 +3922,48 @@ void OCCViewer_ViewWindow::onLightSource() aDlg->show(); } } + +void OCCViewer_ViewWindow::ProjAndPanToGravity(V3d_TypeOfOrientation CamOri) +{ + Handle(V3d_View) aView3d = myViewPort->getView(); + if (aView3d.IsNull()) + return; + double X = 0, Y = 0, Z = 0; + //bool IsGr = computeGravityCenter1(gc); + bool IsGr = computeGravityCenter(X, Y, Z); + if ( !IsGr ) + IsGr = OCCViewer_Utilities::computeSceneBBCenter(aView3d, X, Y, Z); + aView3d->SetProj(CamOri); + if (IsGr) + { + //aView3d->Update(); + Handle(Graphic3d_Camera) Cam = aView3d->Camera(); + gp_XYZ gp(X, Y, Z); + gp_Vec dir (Cam->Direction()); + gp_Pnt eye = Cam->Eye(); + gp_Vec V1(eye, gp); + Standard_Real D = dir.Dot(V1); + gp_Pnt ppdir = eye.Translated(D*dir); + gp_Vec V2(ppdir, gp); + gp_XYZ trEye = eye.XYZ() + V2.XYZ(); + + double xat, yat, zat; + aView3d->At(xat, yat, zat); + gp_Pnt At(xat, yat, zat); + gp_XYZ trAt = At.XYZ() + V2.XYZ(); + aView3d->SetEye(trEye.X(), trEye.Y(), trEye.Z()); + aView3d->SetAt(trAt.X(), trAt.Y(), trAt.Z()); + } +} + + +bool OCCViewer_ViewWindow::isAutomaticZoom() const +{ + return myAutomaticZoom; +} + +void OCCViewer_ViewWindow::setAutomaticZoom(const bool isOn) +{ + myAutomaticZoom = isOn; +} + diff --git a/src/OCCViewer/OCCViewer_ViewWindow.h b/src/OCCViewer/OCCViewer_ViewWindow.h index c68465fa5..88e6f7af3 100755 --- a/src/OCCViewer/OCCViewer_ViewWindow.h +++ b/src/OCCViewer/OCCViewer_ViewWindow.h @@ -39,6 +39,7 @@ class OCCViewer_SetRotationPointDlg; class OCCViewer_Viewer; class OCCViewer_CubeAxesDlg; class QtxAction; +class gp_XYZ; struct viewAspect { @@ -242,6 +243,9 @@ public: virtual bool isQuadBufferSupport() const; virtual void setQuadBufferSupport( const bool ); + virtual bool isAutomaticZoom() const; + virtual void setAutomaticZoom( const bool ); + void setTransformEnabled( const OperationType, const bool ); bool transformEnabled( const OperationType ) const; @@ -368,6 +372,10 @@ protected: bool computeGravityCenter( double& theX, double& theY, double& theZ ); + bool computeGravityCenter1(gp_XYZ& gravityCenter); + + void ProjAndPanToGravity(V3d_TypeOfOrientation CamOri); + virtual void onSketchingStarted(); virtual void onSketchingFinished(); @@ -406,7 +414,7 @@ protected: bool myPaintersRedrawing; // set to draw with external painters bool IsSketcherStyle; bool myIsKeyFree; - + bool myAutomaticZoom; QCursor myCursor; double myCurScale; -- 2.39.2